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 }