blob: 0736bdad455cf0853c02f2ddc88ddd9c235740e0 [file] [log] [blame]
package org.apache.commons.digester3.examples.api.dbinsert;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import org.apache.commons.digester3.Digester;
import org.xml.sax.SAXException;
/**
* A simple program to demonstrate that the Commons Digester module can be
* used to trigger actions as the xml is parsed, rather than just build
* up in-memory representations of the parsed data. This example also shows
* how to write a custom Rule class.
* <p>
* This code will parse the provided "example.xml" file, and immediately
* insert the processed data into a database as each row tag is parsed,
* instead of building up an in-memory representation. Actually, in order
* to keep this example simple and easy to run, sql insert statements are
* printed out rather than actually performing database inserts, but the
* principle remains.
* <p>
* Very verbose comments are included here, as this class is intended
* as a tutorial; if you look closely at method "addRules", you will
* see that the amount of code required to use the Digester is actually
* quite low.
* <p>
* Usage: java Main example.xml
*/
public class Main
{
/**
* Main method : entry point for running this example program.
* <p>
* Usage: java Main example.xml
*/
public static void main( final String[] args )
{
if ( args.length != 1 )
{
usage();
System.exit( -1 );
}
final String filename = args[0];
// Create a Digester instance
final Digester d = new Digester();
// Here you would establish a real connection.
// There would also be a finally clause to ensure it is
// closed after parsing terminates, etc.
final Connection connection = null;
// Add rules to the digester that will be triggered while
// parsing occurs.
addRules( d, connection );
// Process the input file.
System.out.println( "Parsing commencing..." );
try
{
final File srcfile = new File( filename );
d.parse( srcfile );
}
catch ( final IOException ioe )
{
System.out.println( "Error reading input file:" + ioe.getMessage() );
System.exit( -1 );
}
catch ( final SAXException se )
{
System.out.println( "Error parsing input file:" + se.getMessage() );
System.exit( -1 );
}
// And here there is nothing to do. The digester rules have
// (deliberately) not built a representation of the input, but
// instead processed the data as it was read.
System.out.println( "Parsing complete." );
}
private static void addRules( final Digester d, final java.sql.Connection conn )
{
// --------------------------------------------------
// when we encounter a "table" tag, do the following:
// Create a new instance of class Table, and push that
// object onto the digester stack of objects. We only need
// this so that when a row is inserted, it can find out what
// the enclosing tablename was.
//
// Note that the object is popped off the stack at the end of the
// "table" tag (normal behavior for ObjectCreateRule). Because we
// never added the table object to some parent object, when it is
// popped off the digester stack it becomes garbage-collected. That
// is fine in this situation; we've done all the necessary work and
// don't need the table object any more.
d.addObjectCreate( "database/table", Table.class );
// Map *any* attributes on the table tag to appropriate
// setter-methods on the top object on the stack (the Table
// instance created by the preceeding rule). We only expect one
// attribute, though: a 'name' attribute specifying what table
// we are inserting rows into.
d.addSetProperties( "database/table" );
// --------------------------------------------------
// When we encounter a "row" tag, invoke methods on the provided
// RowInserterRule instance.
//
// This rule creates a Row instance and pushes it on the digester
// object stack, rather like ObjectCreateRule, so that the column
// tags have somewhere to store their information. And when the
// </row> end tag is found, the rule will trigger to remove this
// object from the stack, and also do an actual database insert.
//
// Note that the rule instance we are passing to the digester has
// been initialized with some useful data (the SQL connection).
//
// Note also that in this case we are not using the digester's
// factory methods to create the rule instance; that's just a
// convenience - and obviously not an option for Rule classes
// that are not part of the digester core implementation.
final RowInserterRule rowInserterRule = new RowInserterRule( conn );
d.addRule( "database/table/row", rowInserterRule );
// --------------------------------------------------
// when we encounter a "column" tag, call setColumn on the top
// object on the stack, passing two parameters: the "name"
// attribute, and the text within the tag body.
d.addCallMethod( "database/table/row/column", "addColumn", 2 );
d.addCallParam( "database/table/row/column", 0, "name" );
d.addCallParam( "database/table/row/column", 1 );
}
private static void usage()
{
System.out.println( "Usage: java Main example.xml" );
}
}