commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From skitch...@apache.org
Subject cvs commit: jakarta-commons/digester/src/examples/api/dbinsert Main.java Row.java RowInserterRule.java Table.java build.xml example.xml readme.txt
Date Tue, 30 Nov 2004 02:38:24 GMT
skitching    2004/11/29 18:38:24

  Added:       digester/src/examples/api/dbinsert Main.java Row.java
                        RowInserterRule.java Table.java build.xml
                        example.xml readme.txt
  Log:
  Added examples, inspired by Michael Schuerig.
  
  Revision  Changes    Path
  1.1                  jakarta-commons/digester/src/examples/api/dbinsert/Main.java
  
  Index: Main.java
  ===================================================================
  /*
   * Copyright 2004 The Apache Software Foundation.
   * 
   * Licensed 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 org.apache.commons.digester.Digester;
  
  /**
   * 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(String[] args) {
          if (args.length != 1) {
              usage();
              System.exit(-1);
          }
          
          String filename = args[0];
          
          // Create a Digester instance
          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.
          java.sql.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 {
              java.io.File srcfile = new java.io.File(filename);
              d.parse(srcfile);
          }
          catch(java.io.IOException ioe) {
              System.out.println("Error reading input file:" + ioe.getMessage());
              System.exit(-1);
          }
          catch(org.xml.sax.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(Digester d, 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 behaviour 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 initialised 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.
          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");
      }
  }
  
  
  1.1                  jakarta-commons/digester/src/examples/api/dbinsert/Row.java
  
  Index: Row.java
  ===================================================================
  /*
   * Copyright 2001-2004 The Apache Software Foundation.
   * 
   * Licensed 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.util.List;
  import java.util.LinkedList;
  
  /**
   * See Main.java.
   */
  public class Row {
      
    /**
     * Alas, we can't just use a Map to store the (name, value) pairs
     * because the output will look weird if we don't preserve the column
     * order. This wouldn't be a problem if we were really inserting into
     * a database; it only matters because we are displaying the SQL statements
     * via stdout instead. The LinkedHashMap class would be nice to use, but
     * that would require java 1.4, so we'll use a list instead, and may as
     * well call the entries in the list 'Column' objects.
     */
    public static class Column {
        private String name, value;
        
        public Column(String name, String value) {
            this.name = name; 
            this.value = value;
        }
        
        public String getName() {
            return name;
        }
        
        public String getValue() {
            return value;
        }
    }
      
    private LinkedList columns = new LinkedList();
  
    public Row() {
    }
    
    public void addColumn(String name, String value) {
        columns.add(new Column(name, value));
    }
  
    public List getColumns() {
        return columns;
    }
  }  
  
  
  
  
  1.1                  jakarta-commons/digester/src/examples/api/dbinsert/RowInserterRule.java
  
  Index: RowInserterRule.java
  ===================================================================
  /*
   * Copyright 2003-2004 The Apache Software Foundation.
   * 
   * Licensed 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.util.Map;
  import java.util.Iterator;
  
  /**
   * See Main.java.
   */
  public class RowInserterRule extends org.apache.commons.digester.Rule {
  
      private java.sql.Connection conn;
      
      public RowInserterRule(java.sql.Connection conn) {
          this.conn = conn;
      }
      
      /**
       * This method is invoked when the start tag for an xml element representing
       * a database row is encountered. It pushes a new Row instance onto the
       * digester stack (rather like an ObjectCreateRule) so that column data
       * can be stored on it.
       */
      public void begin(String namespace, String name, org.xml.sax.Attributes attrs) {
          digester.push(new Row());
      }
      
      /**
       * This method is invoked when the end tag for an xml element representing
       * a database row is encountered. It pops a fully-configured Row instance
       * off the digester stack, accesses the object below it on the stack (a
       * Table object) to get the tablename, then does an SQL insert). Actually,
       * here we just print out text rather than do the sql insert, but the
       * real implementation should be fairly simple.
       * <p>
       * Note that after this rule completes, the row/column information is
       * <i>discarded</i>, ie this rule performs actions <i>as the input
is
       * parsed</i>. This contrasts with the more usual way digester is used,
       * which is to build trees of objects for later use. But it's a perfectly
       * valid use of Digester.
       */
      public void end(String namespace, String name) {
          Row row = (Row) digester.pop();
          Table table = (Table) digester.peek();
  
          // Obviously, all this would be replaced by code like:
          //   stmt = conn.prepareStatement();
          //   stmt.setString(n, value);
          //
          // Many improvements can then be implemented, such as using the 
          // PreparedStatement.getParameterMetaData method to retrieve
          // retrieve parameter types, etc.
          
          StringBuffer colnames = new StringBuffer();
          StringBuffer colvalues = new StringBuffer();
          
          for(Iterator i = row.getColumns().iterator(); i.hasNext();)
          {
              Row.Column column = (Row.Column) i.next();
              
              if (colnames.length() > 0)
              {
                  colnames.append(", ");
                  colvalues.append(", ");
              }
          
              colnames.append("'");
              colnames.append(column.getName());
              colnames.append("'");
              
              colvalues.append("'");
              colvalues.append(column.getValue());
              colvalues.append("'");
          }
  
          StringBuffer buf = new StringBuffer();
          buf.append("insert into ");
          buf.append(table.getName());
          buf.append(" (");
          buf.append(colnames.toString());
          buf.append(") values (");
          buf.append(colvalues.toString());
          buf.append(")");
          
          // here the prepared statement would be executed....
          System.out.println(buf.toString());
      }
  }
  
  
  
  1.1                  jakarta-commons/digester/src/examples/api/dbinsert/Table.java
  
  Index: Table.java
  ===================================================================
  /*
   * Copyright 2001-2004 The Apache Software Foundation.
   * 
   * Licensed 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.
   */ 
  
  /**
   * See Main.java.
   */
  public class Table {
    private String name;
  
    public Table() {
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
  }  
  
  
  
  
  1.1                  jakarta-commons/digester/src/examples/api/dbinsert/build.xml
  
  Index: build.xml
  ===================================================================
  <!--
   Copyright 2004 The Apache Software Foundation.
    
   Licensed 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.
  -->
  
  <project name="Example-AddressBook" default="compile" basedir=".">
  
  
  <!-- ========== Initialize Properties ===================================== -->
  
  
    <property file="build.properties"/>                <!-- Component local   -->
    <property file="../build.properties"/>             <!-- examples/api local-->
    <property file="../../../../build.properties"/>    <!-- Digester local     -->
    <property file="../../../../../build.properties"/> <!-- Commons local     -->
    <property file="${user.home}/build.properties"/>   <!-- User local        -->
  
  
  <!-- ========== External Dependencies ===================================== -->
  
  
    <!-- The directories corresponding to your necessary dependencies -->
    <property name="jaxp.home"               value="/usr/local/jaxp1.1"/>
    <property name="commons.home"            value="../../../../.."/>
    <property name="beanutils.home"          value="${commons.home}/beanutils"/>
    <property name="collections.home"        value="${commons.home}/collections"/>
    <property name="logging.home"            value="${commons.home}/logging"/>
    <property name="digester.home"            value="${commons.home}/digester"/>
  
  
  <!-- ========== Derived Values ============================================ -->
  
  
    <!-- The locations of necessary jar files -->
    <property name="jaxp.jaxp.jar"           value="${jaxp.home}/jaxp.jar"/>
    <property name="jaxp.parser.jar"         value="${jaxp.home}/crimson.jar"/>
    <property name="commons-beanutils.jar"   value="${beanutils.home}/dist/commons-beanutils.jar"/>
    <property name="commons-collections.jar" value="${collections.home}/dist/commons-collections.jar"/>
    <property name="commons-logging.jar"     value="${logging.home}/dist/commons-logging.jar"/>
    <property name="commons-digester.jar"     value="${digester.home}/dist/commons-digester.jar"/>
  
  
  <!-- ========== Component Declarations ==================================== -->
  
    <!-- The name of this component -->
    <property name="component.name"          value="addressbook"/>
  
  
  <!-- ========== Compiler Defaults ========================================= -->
  
    <!-- Should Java compilations set the 'debug' compiler option? -->
    <property name="compile.debug"           value="true"/>
  
    <!-- Should Java compilations set the 'deprecation' compiler option? -->
    <property name="compile.deprecation"     value="false"/>
  
    <!-- Should Java compilations set the 'optimize' compiler option? -->
    <property name="compile.optimize"        value="true"/>
  
    <!-- Construct compile classpath -->
    <path id="compile.classpath">
      <pathelement location="."/>
      <pathelement location="${jaxp.jaxp.jar}"/>
      <pathelement location="${jaxp.parser.jar}"/>
      <pathelement location="${commons-beanutils.jar}"/>
      <pathelement location="${commons-collections.jar}"/>
      <pathelement location="${commons-logging.jar}"/>
      <pathelement location="${commons-digester.jar}"/>
    </path>
  
  
  <!-- ========== Executable Targets ======================================== -->
  
  
    <target name="compile">
      <javac  srcdir="."
             destdir="."
               debug="${compile.debug}"
         deprecation="${compile.deprecation}"
            optimize="${compile.optimize}">
        <classpath refid="compile.classpath"/>
      </javac>
    </target>
  
  
    <target name="clean">
      <delete>
        <fileset dir="." includes="*.class"/>
      </delete>
      <delete dir="docs"/>
    </target>
  
    <target name="all" depends="clean,compile"/>
  
    <target name="javadoc" depends="compile">
      <mkdir      dir="docs"/>
      <javadoc destdir="docs"
                   author="true"
                  private="true"
                  version="true">
        <classpath  refid="compile.classpath"/>
        <fileset dir="." includes="*.java"/>
      </javadoc>
    </target>
  
    <target name="run" depends="compile">
      <java classname="Main" fork="yes">
        <arg value="example.xml"/>
        <classpath refid="compile.classpath"/>
        <classpath>
          <pathelement location="."/>
        </classpath>
      </java>
    </target>
  </project>
  
  
  
  1.1                  jakarta-commons/digester/src/examples/api/dbinsert/example.xml
  
  Index: example.xml
  ===================================================================
  <!--
   Copyright 2004 The Apache Software Foundation.
    
   Licensed 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.
  -->
  
  <database>
    <table name="muppets">
      <row>
        <column name="name">Kermit</column>
        <column name="colour">green</column>
        <column name="hobby">worrying</column>
      </row>
      <row>
        <column name="name">Miss Piggy</column>
        <column name="colour">pink</column>
        <column name="hobby">karate</column>
      </row>
    </table>
    
    <table name="things">
      <row>
        <column name="name">Drums</column>
        <column name="owner">Animal</column>
      </row>
    </table>
  </database>
  
  
  1.1                  jakarta-commons/digester/src/examples/api/dbinsert/readme.txt
  
  Index: readme.txt
  ===================================================================
  #########################################################################
  # Copyright 2004 The Apache Software Foundation.
  #  
  # Licensed 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.
  #########################################################################
  
  == overview
  
  The files in this directory are intended as an example of how to use
  the Apache Digester's basic functionality via its java interface.
  
  Topics covered:
  * how to write a custom Rule class.
  * How to use digester to perform actions during parsing, rather
    than just build in-memory models of the input.
  
  == compiling and running
  
  First rename the build.properties.sample file in the parent directory
  to build.properties and edit it to suit your environment. Then in this
  directory:
  
  * to compile:
    ant compile
  
  * to run:
    ant run
  
  Alternatively, you can set up your CLASSPATH appropriately, and
  run the example directly. See the build.properties and build.xml
  files for details.
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message