Jato: The new kid on the open source block, Part 3

Translate XML documents into Java objects

1 2 3 Page 3
Page 3 of 3
1.  public class JatoTree {
2.         public static void main(String[] args)  throws Exception {
3.            new JatoTree();
4.         }
5.
6.         public JatoTree() throws JatoException, IOException, JDOMException {
7.            //create a helper, get the root node, and build the tree
8.            NodeIntegrator integrator = new NodeIntegrator();
9.            FileNode root = integrator.getRootNode();
10.     JTreeTable treeTable = new JTreeTable(new FileSystemModel(root));
11.
12.     //create a frame, add JTreeTable, size window, and other GUI stuff here
13.   }
14. 
15. //Interface point between Jato and Java application code
16. class NodeIntegrator implements JatoIntegrator {
17.   DirNode fRoot;
18. 
19.   FileNode getRootNode() throws JatoException, IOException, JDOMException
20.    {
21.       //load the default tags into the builder
22.       ScriptBuilder.loadDefaultJatoDefs();
23. 
24.       //create script document from the static string class variable
25.       InputStream xmlIS = new FileInputStream("xml-to-java.xml");
26.       Document scriptDoc = new SAXBuilder().build(xmlIS);
27.       xmlIS.close();
28. 
29.       //create the script and interpreter with no debug information
30.       JatoScript script = ScriptBuilder.createJatoScript(scriptDoc.getRootElement(), 
31.                                                             false);
32.       Interpreter jato = new Interpreter(script, this);
33. 
34.       //read in the XML input document for the transformation
35.       xmlIS = new FileInputStream("site.xml");
36.       Document xmlIn = new SAXBuilder().build(xmlIS);
37.       xmlIS.close();
38. 
39.       //perform the transformation using the root elements of the input document
40.       //the script does not produce any output so pass in null for output element
41.       jato.transform(xmlIn.getRootElement(), null);
42. 
43.       //return the root node which was set in the publish method
44.       return fRoot;
45.    }
46. 
47. 
48.    /**
49.     * Method invoked by interpreter when Jato script tag contains a 50.     * 'publish' attribute.
51.     *
52.     * @param key -- value of the 'publish' attribute in the Jato script
53.     * tag. This value is used to distinguish the category of object being published.
54.     * @param obj -- the object being published
55.     * @param state -- one of CREATED_STATE or INITIALIZED_STATE.
56.     */
57.    public void publish(String key, Object obj, int state)  {
58.       DirNode node;
59. 
60.       if (key.equalsIgnoreCase("root")) {
61.          if (state == CREATED_STATE) {
62.             fRoot = (DirNode)obj;
63.          }
64.       } else {
65.          throw new IllegalArgumentException("Unknown key: " + key);
66.       }
67.    }
68. 
69.    /**
70.     * Method invoked by interpreter when Jato script tag requests a Get command.
71.     *
72.     * @param key - the value of the 'get' attribute or 'key'
73.     * attribute for &ltJato:get> tags.
74.     * @param parms - the parameters specified for the Get command using
75.     * &ltJato:param> tags. The tags must be specified using a
76.     * name attribute.
77.     */
78.    public Object getObject(String key, Properties parms) {
79.       throw new IllegalStateException("getObject() not supported by integrator");
80.    }
81. }

Jato has undergone a few design changes since Part 2 was published. The changes that affect the code in Listing 7 deal with creating Jato interpreters and providing an integration point between Jato and the Java application code. Specifically, executing a Jato script now involves these tasks:

  1. Implement the JatoIntegrator interface: This interface replaces the InterpreterHelper interface and contains just two methods: getObject() and publish(). These two methods were part of the InterpreterHelper interface and their use remains unchanged.
  2. Create a JatoScript instance: The new design encapsulates the information contained in a Jato script within the JatoScript class and provides the ScriptBuilder class for constructing JatoScript instances. This change allows scripts to be safely executed by multiple threads concurrently.
  3. Create an Interpreter instance: Interpreters are now instantiated using a JatoScript instance and an optional JatoIntegrator instance. A single JatoScript instance may be shared by multiple Interpreter instances.
  4. Execute the script using the interpreter's transform() method: The XML input and output elements to be utilized during the transformation are passed in as transform() parameters. The helper provided the XML elements in the previous design and this led to needless helper class complications and serious limitations.

Having said all that, Java code written to the two Jato designs are very similar; consequently, most of Listing 7 should look similar to previous Jato examples. This is the first application, however, that uses Jato to read configuration data for a larger purpose. In that regard, the JatoTree class represents a stereotypical Jato scenario. Some interesting code points are:

  • Lines 8 and 9: All Jato code is removed from the main application and placed in the integrator class, NodeIntegrator. The integrator class's only visible role is to "get" the root element.
  • Line 16: The integrator class implements the JatoIntegrator interface.
  • Lines 21-44: The getRootNode() method does all the heavy lifting for the application. The default script tags are loaded into the Jato environment at line 22. The method ends by returning the DirNode root object created by our script and published using the key of "root". The instance variable assignment takes place at line 62 during script execution.
  • Line 41: The transform() method is invoked by passing the site.xml root element in as the input element and no output element.

All that is left is the simple command:

c:\> java JatoTree :-)

The smiley face is optional.

Conclusion

Could this assignment have been simplified by providing more JavaBeans methods, using consistent file and directory tag structures, and performing more data conversions in the node classes? Or thought of differently, could the problem be rigged to make creating a Swing-based GUI look brain-dead simple? Sure, but where is the fun in making examples simple; especially when projects involving actual requirements are rarely simple and trivial. I will leave the cooked demos to the proprietary vendors and keep the real-world tasks for the open source community.

This article provides a more in-depth look at using Jato to perform XML-to-Java transformations. We jazzed it up a bit by creating a nifty Swing user interface using information stored in the pedestrian sites.xml file. The solution demonstrates instantiating objects, invoking complex constructors and methods, evaluating conditional parameter lists, using recursive macro calls to traverse hierarchical XML structures, and setting JavaBeans properties. Finally, the article provides an initial sighting of the all-powerful Jato expression engine. But that, as they say, is a story for another day.

Learn more about this topic

1 2 3 Page 3
Page 3 of 3