Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

lachoy (1663)


I am actually Chris Winters; I am actually living in Pittsburgh, Pennsylvania, USA; I am actually married and have three cats. (Guess what one of them is named?) I am the "OpenInteract" guy, which could be good or bad.

Journal of lachoy (1663)

Friday March 11, 2005
03:11 PM

Using a factory in commons-digester

[ #23610 ]

commons-digester is one of the more useful jakarta commons libraries. Yeah, it's verbose and it might take a little while to grok if you're not used to stack processing and other xml-isms. But once grokked it's applicable many places, especially since lots of systems are passing around XML these days. Parsing a message-based document (short) into an object seems to be pretty quick too and since you're using rules it's pretty easy to extend once you get the basics down -- this article has a practical application of it.

The idea behind the digester is that you have events that fire based on element paths. A common scenario: when you hit a path create a new object, then set its attributes and child elements as properties, something like:

  // Process the address from a message like:
  // <customer first="foo" last="bar">
  //   <address
  //       street="1234 Main Street" city="Wilmerding" state="PA" />
  // </customer>

  Digest d = new Digester();
  // push a new object on the stack...
  d.addObjectCreate( "customer/address", Address.class );

  // this will call on the topmost stack object
  // 'setStreet()', 'setCity()', 'setState()'
  d.addSetProperties( "customer/address" );

  // ...or you can do it explicitly
  d.addSetProperties( "customer/address", "street", "street" );
  d.addSetProperties( "customer/address", "city", "city" );
  d.addSetProperties( "customer/address", "state", "state" );

  // add the topmost stack object to the previous one
  d.addSetNext( "customer/address" );

Verbose, but not so bad. What happens when you have different types of addresses?

  // <customer first="foo" last="bar">
  //   <address country="USA"
  //       street="1234 Main Street" city="Wilmerding" state="PA" />
  //   <address country="Canada"
  //       street="1234 Main Street" city="Toronto" province="ON" />
  // </customer>

Assuming e've got a parent class 'Address' and subclasses 'CanadaAddress', 'UnitedStatesAddress', etc. How do we tell digester to create the right object? A factory, of course:

  // just change the 'addObjectCreate()' to:
  d.addFactoryCreate( "customer/address", AddressFactory.class );

The factory class is cake:

// 'AbstractObjectCreationFactory' is from commons-digester
public class AddressFactory extends AbstractObjectCreationFactory
    public Object createObject( Attributes attributes )
        throws Exception
        String country = attributes.getValue( "country);
        if ( "USA".equals( country ) ) {
            return new UnitedStatesAddress();
        else if ( "Canada".equals( country ) ) {
            return new CanadaAddress();

Posted from; read original

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.