1 package org.apache.commons.digester3.examples.api.dbinsert; 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 java.io.File; 21 import java.io.IOException; 22 import java.sql.Connection; 23 24 import org.apache.commons.digester3.Digester; 25 import org.xml.sax.SAXException; 26 27 /** 28 * A simple program to demonstrate that the Commons Digester module can be 29 * used to trigger actions as the xml is parsed, rather than just build 30 * up in-memory representations of the parsed data. This example also shows 31 * how to write a custom Rule class. 32 * <p> 33 * This code will parse the provided "example.xml" file, and immediately 34 * insert the processed data into a database as each row tag is parsed, 35 * instead of building up an in-memory representation. Actually, in order 36 * to keep this example simple and easy to run, sql insert statements are 37 * printed out rather than actually performing database inserts, but the 38 * principle remains. 39 * <p> 40 * Very verbose comments are included here, as this class is intended 41 * as a tutorial; if you look closely at method "addRules", you will 42 * see that the amount of code required to use the Digester is actually 43 * quite low. 44 * <p> 45 * Usage: java Main example.xml 46 */ 47 public class Main 48 { 49 50 /** 51 * Main method : entry point for running this example program. 52 * <p> 53 * Usage: java Main example.xml 54 */ 55 public static void main( String[] args ) 56 { 57 if ( args.length != 1 ) 58 { 59 usage(); 60 System.exit( -1 ); 61 } 62 63 String filename = args[0]; 64 65 // Create a Digester instance 66 Digester d = new Digester(); 67 68 // Here you would establish a real connection. 69 // There would also be a finally clause to ensure it is 70 // closed after parsing terminates, etc. 71 Connection connection = null; 72 73 // Add rules to the digester that will be triggered while 74 // parsing occurs. 75 addRules( d, connection ); 76 77 // Process the input file. 78 System.out.println( "Parsing commencing..." ); 79 try 80 { 81 File srcfile = new File( filename ); 82 d.parse( srcfile ); 83 } 84 catch ( IOException ioe ) 85 { 86 System.out.println( "Error reading input file:" + ioe.getMessage() ); 87 System.exit( -1 ); 88 } 89 catch ( SAXException se ) 90 { 91 System.out.println( "Error parsing input file:" + se.getMessage() ); 92 System.exit( -1 ); 93 } 94 95 // And here there is nothing to do. The digester rules have 96 // (deliberately) not built a representation of the input, but 97 // instead processed the data as it was read. 98 System.out.println( "Parsing complete." ); 99 } 100 101 private static void addRules( Digester d, java.sql.Connection conn ) 102 { 103 104 // -------------------------------------------------- 105 // when we encounter a "table" tag, do the following: 106 107 // Create a new instance of class Table, and push that 108 // object onto the digester stack of objects. We only need 109 // this so that when a row is inserted, it can find out what 110 // the enclosing tablename was. 111 // 112 // Note that the object is popped off the stack at the end of the 113 // "table" tag (normal behaviour for ObjectCreateRule). Because we 114 // never added the table object to some parent object, when it is 115 // popped off the digester stack it becomes garbage-collected. That 116 // is fine in this situation; we've done all the necessary work and 117 // don't need the table object any more. 118 d.addObjectCreate( "database/table", Table.class ); 119 120 // Map *any* attributes on the table tag to appropriate 121 // setter-methods on the top object on the stack (the Table 122 // instance created by the preceeding rule). We only expect one 123 // attribute, though: a 'name' attribute specifying what table 124 // we are inserting rows into. 125 d.addSetProperties( "database/table" ); 126 127 // -------------------------------------------------- 128 // When we encounter a "row" tag, invoke methods on the provided 129 // RowInserterRule instance. 130 // 131 // This rule creates a Row instance and pushes it on the digester 132 // object stack, rather like ObjectCreateRule, so that the column 133 // tags have somewhere to store their information. And when the 134 // </row> end tag is found, the rule will trigger to remove this 135 // object from the stack, and also do an actual database insert. 136 // 137 // Note that the rule instance we are passing to the digester has 138 // been initialised with some useful data (the SQL connection). 139 // 140 // Note also that in this case we are not using the digester's 141 // factory methods to create the rule instance; that's just a 142 // convenience - and obviously not an option for Rule classes 143 // that are not part of the digester core implementation. 144 RowInserterRule rowInserterRule = new RowInserterRule( conn ); 145 d.addRule( "database/table/row", rowInserterRule ); 146 147 // -------------------------------------------------- 148 // when we encounter a "column" tag, call setColumn on the top 149 // object on the stack, passing two parameters: the "name" 150 // attribute, and the text within the tag body. 151 d.addCallMethod( "database/table/row/column", "addColumn", 2 ); 152 d.addCallParam( "database/table/row/column", 0, "name" ); 153 d.addCallParam( "database/table/row/column", 1 ); 154 } 155 156 private static void usage() 157 { 158 System.out.println( "Usage: java Main example.xml" ); 159 } 160 161 }