The java.pattern.visitor option adds a visitor facility for Relaxer objects.
The visitor facility, which is a kind of Visitor pattern from the GoF's Design Pattern book, enables a facility to traverse object structure.
The java.pattern.visitor option takes one of the following values as a parameter:
The default configuration is false
.
No parameter implies that the parameter is true
.
The java.pattern.visitor option generates additional classes as follows:
The java.pattern.visitor option adds the following methods to Relaxer objects.
rGetParentRNode()
rSetParentRNode(IRNode)
rGetRNodes()
enter(IVisitor)
leave(IRVisitor)
List 7.20.3.1[javaPatternVisitor.rng] is a sample schema for the java.pattern.visitor option.
<grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <ref name="account"/> </start> <define name="account"> <element name="account"> <attribute name="accountNo"> <data type="token"/> </attribute> <element name="balance"> <data type="int"/> </element> <element name="owner"> <data type="token"/> </element> <ref name="address"/> <zeroOrMore> <ref name="phone"/> </zeroOrMore> </element> </define> <define name="address"> <element name="address"> <attribute name="zip"> <data type="token"/> </attribute> <text/> </element> </define> <define name="phone"> <element name="phone"> <attribute name="area"> <data type="token"/> </attribute> <data type="token"/> </element> </define> </grammar>
Execution of Relaxer with the java.pattern.visitor option is as follows:
$ relaxer -java -java.pattern.visitor javaPatternVisitor.rng
Because the Java generator is a default generator, execution of Relaxer as shown below has the same effect:
$ relaxer -java.pattern.visitor javaPatternVisitor.rng
As a result, Relaxer generates 11 files:
The IRNode
is a interface for the composite pattern.
The composite pattern is used automatically when the visitor pattern is used.
The IRVisitable
,
the URVisitor
,
the IRVisitor
, and
the RVisitorBase
are the visitor pattern specific classes.
List 7.20.3.1.1[JavaPatternVisitor.java] is a sample program for the java.pattern.visitor option.
import java.io.IOException; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.SAXException; public class JavaPatternVisitor { public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException { String uri = args[0]; Account account = makeAccount(uri); printAccount(account); visitAccount(account); } private static Account makeAccount(String uri) throws IOException, SAXException, ParserConfigurationException { System.out.println("*** makeAccount ***"); Account account = new Account(uri); return (account); } private static void printAccount(Account account) { System.out.println("*** printAccount ***"); String accountNo = account.getAccountNo(); long balance = account.getBalance(); String owner = account.getOwner(); System.out.println("AccountNo:" + accountNo); System.out.println("Balance:" + balance); System.out.println("Owner:" + owner); Address address = account.getAddress(); if (address != null) { String zip = address.getZip(); String place = address.getContent(); System.out.println("Address: [" + zip + "] " + place); } Phone[] phones = account.getPhone(); for (int i = 0;i < phones.length;i++) { Phone phone = phones[i]; String area = phone.getArea(); String number = phone.getContent(); System.out.println("Phone: [" + area + "] " + number); } } private static void showAccount(Account account) { System.out.println("*** showAccount ***"); System.out.println("XML:" + account); } private static void visitAccount(Account account) { System.out.println("*** visitAccount ***"); PrintVisitor visitor = new PrintVisitor(); URVisitor.traverse(account, visitor); } }
In the JavaPatternVisitor
, the visitor class
PrintVisitor
as shown in List 7.20.3.1.2[PrintVisitor.java]
is used.
public class PrintVisitor extends RVisitorBase { public boolean enter(Account account) { System.out.println("enter - Account"); String accountNo = account.getAccountNo(); long balance = account.getBalance(); String owner = account.getOwner(); System.out.println("AccountNo:" + accountNo); System.out.println("Balance:" + balance); System.out.println("Owner:" + owner); return (true); } public void leave(Account account) { System.out.println("leave - Account"); } public boolean enter(Address address) { System.out.println("enter - Address"); String zip = address.getZip(); String place = address.getContent(); System.out.println("Address: [" + zip + "] " + place); return (true); } public void leave(Address address) { System.out.println("leave - Address"); } public boolean enter(Phone phone) { System.out.println("enter - Phone"); String area = phone.getArea(); String number = phone.getContent(); System.out.println("Phone: [" + area + "] " + number); return (true); } public void leave(Phone phone) { System.out.println("leave - Phone"); } }
Compilation of JavaPatternVisitor.java
is shown here:
$ javac JavaPatternVisitor.java
List 7.20.3.2.1[javapatternVisitor.xml] is an XML document for testing.
<account accountNo="12345"> <balance>102030</balance> <owner>XML Taro</owner> <address zip="213">Yokohama</address> <phone area="123">456-7890</phone> <phone area="090">123-4567</phone> </account>
Execution of the JavaPatternVisitor
class is shown here:
$ java JavaPatternVisitor javaPatternVisitor.xml AccountNo:12345 Balance:102030 Owner:XML Taro XML:<account xmlns="http://example.com/account" \ accountNo="12345"><balance>102030</balance><owner>XML \ Taro</owner></account>