View Javadoc

1   package org.apache.commons.digester3.examples.api.addressbook;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements.  See the NOTICE file distributed with
6    * this work for additional information regarding copyright ownership.
7    * The ASF licenses this file to You under the Apache License, Version 2.0
8    * (the "License"); you may not use this file except in compliance with
9    * the License.  You may obtain a copy of the License at
10   * 
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */ 
19  
20  import org.apache.commons.digester3.Digester;
21  
22  /**
23   * A simple program to demonstrate the basic functionality of the
24   * Commons Digester module.
25   * <p>
26   * This code will parse the provided "example.xml" file to build a tree
27   * of java objects, then cause those objects to print out their values
28   * to demonstrate that the input file has been processed correctly.
29   * <p>
30   * As with all code, there are many ways of achieving the same goal;
31   * the solution here is only one possible solution to the problem.
32  * <p> 
33   * Very verbose comments are included here, as this class is intended
34   * as a tutorial; if you look closely at method "addRules", you will
35   * see that the amount of code required to use the Digester is actually
36   * quite low.
37   * <p>
38   * Usage: java Main example.xml
39   */
40  public class Main
41  {
42  
43      /**
44       * Main method : entry point for running this example program.
45       * <p>
46       * Usage: java Example example.xml
47       */
48      public static void main( String[] args )
49      {
50          if ( args.length != 1 )
51          {
52              usage();
53              System.exit( -1 );
54          }
55  
56          String filename = args[0];
57  
58          // Create a Digester instance
59          Digester d = new Digester();
60  
61          // Prime the digester stack with an object for rules to
62          // operate on. Note that it is quite common for "this"
63          // to be the object pushed.
64          AddressBook book = new AddressBook();
65          d.push( book );
66  
67          // Add rules to the digester that will be triggered while
68          // parsing occurs.
69          addRules( d );
70  
71          // Process the input file.
72          try
73          {
74              java.io.File srcfile = new java.io.File( filename );
75              d.parse( srcfile );
76          }
77          catch ( java.io.IOException ioe )
78          {
79              System.out.println( "Error reading input file:" + ioe.getMessage() );
80              System.exit( -1 );
81          }
82          catch ( org.xml.sax.SAXException se )
83          {
84              System.out.println( "Error parsing input file:" + se.getMessage() );
85              System.exit( -1 );
86          }
87  
88          // Print out all the contents of the address book, as loaded from
89          // the input file.
90          book.print();
91      }
92  
93      private static void addRules( Digester d )
94      {
95  
96          // --------------------------------------------------
97          // when we encounter a "person" tag, do the following:
98  
99          // create a new instance of class Person, and push that
100         // object onto the digester stack of objects
101         d.addObjectCreate( "address-book/person", Person.class );
102 
103         // map *any* attributes on the tag to appropriate
104         // setter-methods on the top object on the stack (the Person
105         // instance created by the preceeding rule).
106         //
107         // For example:
108         // if attribute "id" exists on the xml tag, and method setId
109         // with one parameter exists on the object that is on top of
110         // the digester object stack, then a call will be made to that
111         // method. The value will be type-converted from string to
112         // whatever type the target method declares (where possible),
113         // using the commons ConvertUtils functionality.
114         //
115         // Attributes on the xml tag for which no setter methods exist
116         // on the top object on the stack are just ignored.
117         d.addSetProperties( "address-book/person" );
118 
119         // call the addPerson method on the second-to-top object on
120         // the stack (the AddressBook object), passing the top object
121         // on the stack (the recently created Person object).
122         d.addSetNext( "address-book/person", "addPerson" );
123 
124         // --------------------------------------------------
125         // when we encounter a "name" tag, call setName on the top
126         // object on the stack, passing the text contained within the
127         // body of that name element [specifying a zero parameter count
128         // implies one actual parameter, being the body text].
129         // The top object on the stack will be a person object, because
130         // the pattern address-book/person always triggers the
131         // ObjectCreateRule we added previously.
132         d.addCallMethod( "address-book/person/name", "setName", 0 );
133 
134         // --------------------------------------------------
135         // when we encounter an "email" tag, call addEmail on the top
136         // object on the stack, passing two parameters: the "type"
137         // attribute, and the text within the tag body.
138         d.addCallMethod( "address-book/person/email", "addEmail", 2 );
139         d.addCallParam( "address-book/person/email", 0, "type" );
140         d.addCallParam( "address-book/person/email", 1 );
141 
142         // --------------------------------------------------
143         // When we encounter an "address" tag, create an instance of class
144         // Address and push it on the digester stack of objects. After
145         // doing that, call addAddress on the second-to-top object on the
146         // digester stack (a "Person" object), passing the top object on
147         // the digester stack (the "Address" object). And also set things
148         // up so that for each child xml element encountered between the start
149         // of the address tag and the end of the address tag, the text
150         // contained in that element is passed to a setXXX method on the
151         // Address object where XXX is the name of the xml element found.
152         d.addObjectCreate( "address-book/person/address", Address.class );
153         d.addSetNext( "address-book/person/address", "addAddress" );
154         d.addSetNestedProperties( "address-book/person/address" );
155     }
156 
157     private static void usage()
158     {
159         System.out.println( "Usage: java Main example.xml" );
160     }
161 
162 }