commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject cvs commit: jakarta-commons/digester/src/examples/api/catalog
Date Sat, 17 Apr 2004 11:05:13 GMT
skitching    2004/04/17 04:05:13

  Added:       digester/src/examples/api/catalog
  Removed:     digester/src/examples/api/catalog
  Rename CatalogDigester->Main, as the former name is too confusing now
  there is an example showing how to subclass digester. Also fixed
  incorrect copyright date.
  Revision  Changes    Path
  1.1                  jakarta-commons/digester/src/examples/api/catalog/
   * 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
   * 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;
  import org.apache.commons.digester.AbstractObjectCreationFactory;
   * A simple program to demonstrate some of the functionality of the
   * Commons Digester module.
   * <p>
   * This code will parse the provided "example.xml" file to build a tree
   * of java objects, then cause those objects to print out their values
   * to demonstrate that the input file has been processed correctly. The
   * input file represents a catalog of items in a library.
   * <p>
   * As with all code, there are many ways of achieving the same goal;
   * the solution here is only one possible implementation.
  * <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 CatalogDigester example.xml
      public static void main(String[] args) {
          if (args.length != 1) {
          String filename = args[0];
          // Create a Digester instance
          Digester d = new Digester();
          // Add rules to the digester that will be triggered while
          // parsing occurs.
          // Process the input file.
          try {
     reader = getInputData(filename);
          catch( ioe) {
              System.out.println("Error reading input file:" + ioe.getMessage());
          catch(org.xml.sax.SAXException se) {
              System.out.println("Error parsing input file:" + se.getMessage());
          // Get the first object created by the digester's rules
          // (the "root" object). Note that this is exactly the same object
          // returned by the Digester.parse method; either approach works.
          Catalog catalog = (Catalog) d.getRoot();
          // Print out all the contents of the catalog, as loaded from
          // the input file.
      private static void addRules(Digester d) {
          // when we encounter the root "catalog" tag, create an
          // instance of the Catalog class. 
          // Note that this approach is different from the approach taken in 
          // the AddressBook example, where an initial "root" object was 
          // explicitly created and pushed onto the digester stack before 
          // parsing started instead
          // Either approach is fine.
          d.addObjectCreate("catalog", Catalog.class);
          // when we encounter a book tag, we want to create a Book
          // instance. However the Book class doesn't have a default
          // constructor (one with no arguments), so we can't use
          // the ObjectCreateRule. Instead, we use the FactoryCreateRule.
          BookFactory factory = new BookFactory();
          d.addFactoryCreate("catalog/book", factory);
          // and add the book to the parent catalog object (which is
          // the next-to-top object on the digester object stack).
          d.addSetNext("catalog/book", "addItem");
          // we want each subtag of book to map the text contents of
          // the tag into a bean property with the same name as the tag.
          // eg <title>foo</title> --> setTitle("foo")
          // We are using the "AudioVisual" class to represent both
          // dvds and videos, so when the "dvd" tag is encountered,
          // create an AudioVisual object.
          d.addObjectCreate("catalog/dvd", AudioVisual.class);
          // add this dvd to the parent catalog object
          d.addSetNext("catalog/dvd", "addItem");
          // We want to map every xml attribute onto a corresponding
          // property-setter method on the Dvd class instance. However
          // this doesn't work with the xml attribute "year-made", because
          // of the internal hyphen. We could use explicit CallMethodRule
          // rules instead, or use a version of the SetPropertiesRule that
          // allows us to override any troublesome mappings...
          // If there was more than one troublesome mapping, we could
          // use the method variant that takes arrays of xml-attribute-names
          // and bean-property-names to override multiple mappings.
          // For any attributes not explicitly mapped here, the default
          // processing is applied, so xml attribute "category" --> setCategory.
          d.addSetProperties("catalog/dvd", "year-made", "yearMade");
          // We also need to tell this AudioVisual object that it is actually
          // a dvd; we can use the ObjectParamRule to pass a string to any
          // method. This usage is a little artificial - normally in this
          // situation there would be separate Dvd and Video classes.
          // Note also that equivalent behaviour could be implemented by
          // using factory objects to create & initialise the AudioVisual
          // objects with their type rather than using ObjectCreateRule.
          d.addCallMethod("catalog/dvd", "setType", 1);
          d.addObjectParam("catalog/dvd", 0, "dvd"); // pass literal "dvd" string
          // Each tag of form "<attr id="foo" value="bar"/> needs to map
          // to a call to setFoo("bar").
          // This is an alternative to the syntax used for books above (see
          // method addSetNestedProperties), where the name of the subtag 
          // indicated which property to set. Using this syntax in the xml has 
          // advantages and disadvantages both for the user and the application 
          // developer. It is commonly used with the FactoryCreateRule variant 
          // which allows the target class to be created to be specified in an 
          // xml attribute; this feature of FactoryCreateRule is not demonstrated
          // in this example, but see the Apache Tomcat configuration files for 
          // an example of this usage.
          // Note that despite the name similarity, there is no link
          // between SetPropertyRule and SetPropertiesRule.
          d.addSetProperty("catalog/dvd/attr", "id", "value");
          // and here we repeat the dvd rules, but for the video tag.
          d.addObjectCreate("catalog/video", AudioVisual.class);
          d.addSetNext("catalog/video", "addItem");
          d.addSetProperties("catalog/video", "year-made", "yearMade");
          d.addCallMethod("catalog/video", "setType", 1);
          d.addObjectParam("catalog/video", 0, "video");
          d.addSetProperty("catalog/video/attr", "id", "value");
       * Reads the specified file into memory, and returns a StringReader
       * object which reads from that in-memory buffer.
       * <p>
       * This method exists just to demonstrate that the input to the
       * digester doesn't need to be from a file; for example, xml could
       * be read from a database or generated dynamically; any old buffer
       * in memory can be processed by the digester.
       * <p>
       * Clearly, if the data is always coming from a file, then calling
       * the Digester.parse method that takes a File object would be
       * more sensible (see AddressBook example).
      private static getInputData(String filename) 
      throws {
 srcfile = new;
 baos = new;
          byte[] buf = new byte[100];
 fis = new;
          for(;;) {
              int nread =;
              if (nread == -1) {
              baos.write(buf, 0, nread);
          return new baos.toString() );
      private static void usage() {
          System.out.println("Usage: java Main example.xml");

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message