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 }