Powered by SmartDoc

Advanced Techniques

On top of Java classes generated by Relaxer, programmers have to add their own programs, which provide application-specific behaviours. In the HelloWorld example, the application program is external to the generated Java classes, and an XML document was handled as merely passive data from the application program.

This approach certainly works for simple programs. But more complicated programs require more advanced techniques for combining programs and data.

To demonstrate more advanced techniques, we use a RELAX model list[menu.rlx] as an example.

menu.rlx
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "relaxCore.dtd">
<module moduleVersion="1.0">

  <interface>
    <export label="menubar"/>
  </interface>

  <elementRule label="menubar" role="menubar">
    <ref label="menu" occurs="*"/>
  </elementRule>

  <tag name="menubar"/>

  <elementRule label="menu" role="menu">
    <sequence>
      <ref label="title"/>
      <choice occurs="*">
        <ref label="item"/>
        <ref label="menu"/>
      </choice>
    </sequence>
  </elementRule>

  <tag name="menu"/>

  <elementRule label="title" role="title" type="string"/>

  <tag name="title"/>

  <elementRule label="item" role="item" type="string"/>

  <tag name="item">
    <attribute name="className" type="NMTOKEN"/>
    <attribute name="method" type="NMTOKEN"/>
  </tag>

</module>

Object tree

The simplest approach to combine generated Java classes and user programs is to handle the generated classes as passive data from user programs.

The HelloWorld explained above uses this approach.

Figure[Object tree]is the class generated from list[menu.rlx] without any options.

Object tree

Factory

Use of generated Java classes as merely passive data does not take full advantage of object-oriented programming, since programs (written by programmers) and data (created by Relaxer) are separated.

A more powerful approach is to combine user programs and Relaxer-generated classes.

To support this approach, Relaxer provides the "factory" option.

C:\tmp>relaxer -factory sample.rlx
Example of factory

The "factory" option is designed on the basis of design patterns.

Collaboration icons in figure[Example of factory] represent three patterns as below:

The "AbstractFactory" pattern and the "FactoryMethod" pattern were introduced in the book "Design Patterns". They are patterns for creating objects. In this figure, these patterns are used to create instances of programmer-defined classes, namely MyMenubar,MyMenu, and MyItem, rather than Relaxer-generated classes, namely Menubar, Menu, and Item.

The "GenerationGap" pattern is a pattern for automatic program generation introduced by the book "Pattern Hatching".

It is not a good idea for programmers to modify Relaxer-generated classes so as to embed their source codes. When the RELAX module is later revised, Java classes have to be generated again, and thus embedded programs will be lost.

Inheritance provide a nice solution: programmers creates subclasses of Relaxer-generated classes and write their own programs as methods of these subclasses.

In other words, even if the class generated by Relaxer is modified, programmers can often use its subclasses without any changes and can further use new features of the re-generated class.

Composite

Since an XML document is inherently hierarchical, classes generated by Relaxer naturally form hierarchical structures.

The design pattern "composite" (shown in "Design Patterns") is a mechanism for handling nodes in tree structures in an unified manner.

Composite
C:\tmp>relaxer -composite sample.rlx

Classes generated by the composite option is shown in figure[Example of composite]. Menubar,Menu and Item implements a common interface IRNode. Access to superior or subordinate nodes can be implemented by providing codes required by this interface.

Example of composite

Visitor

The design pattern "Visitor" (shown in "Design Patterns") is extremely useful for applications that traverse tree structures.

C:\tmp>relaxer -visitor sample.rlx

Classes generated with the visitor option is shown in figure[Example of visitor].

On top of classes generated with the composite mechanism, three classes, namely IRVisitable, IRVisitor and RVisitorBase, are created as well. Moreover, although it is not shown this figure, VRVisitor is created as a utility class for visitor operations.

Example of visitor

List list[IRVisitor.java] shows IRVisitor interface, which is generated as a visitor interface. Automatic generation of such visitor interfaces is very helpful to programmers, since visitor interfaces are mandatory and routine.

Relaxer generates not only IRVisitor but also some other programs automatically. For each class in the tree sturture, Relaxer generates two methods, namely "enter" and "leave", (declared by IRVisitable), which are used by visitors. Furthermore, Relaxer generates a class URVisitor and its traversal functions, namely "traverseBreadth" and "traverseDepth".

IRVisitor.java
/**
 * @version menu.rlx 1.0 (Sun Jun 11 12:58:24 JST 2000)
 * @author  Relaxer 0.9.2b (by ASAMI@Yokohama)
 */
public interface IRVisitor {
    /**
     * Visits this node for enter behavior.
     *
     * @param visitor
     */
    void enter(Menubar visitor);

    /**
     * Visits this node for leave behavior.
     *
     * @param visitor
     */
    void leave(Menubar visitor);

    /**
     * Visits this node for enter behavior.
     *
     * @param visitor
     */
    void enter(Menu visitor);

    /**
     * Visits this node for leave behavior.
     *
     * @param visitor
     */
    void leave(Menu visitor);

    /**
     * Visits this node for enter behavior.
     *
     * @param visitor
     */
    void enter(Item visitor);

    /**
     * Visits this node for leave behavior.
     *
     * @param visitor
     */
    void leave(Item visitor);

    /**
     * Visits this node for enter behavior.
     *
     * @param visitor
     */
    void enter(RString visitor);

    /**
     * Visits this node for leave behavior.
     *
     * @param visitor
     */
    void leave(RString visitor);
}

A concrete example of visitor functions will be shown in the section "document oriented application".