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 }