commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b p <trashspam2...@yahoo.com>
Subject [betwixt] XML includes
Date Fri, 16 Apr 2004 21:32:43 GMT
Hi Robert,
 
One way I started using betwixt is to allow our testing organization to easily create XML
test data (they can modify the XML values to create a large test bed without writting a lot
of java code).  One thing they asked for was a way to include XML files for some pieces of
data.  I originally fought with finding a way to create a custom digester rule to do that,
but then realized it could be done relatively easily with a custom BeanCreator.  
 
Below is a "IncludeBeanCreator" along with a test case for it.  If you think it would be useful
for others,  you can include it in Betwixt (I still haven't dealt with looping  includes,
but I think I could add that relatively quickly when I get some additional time to look at
it).
 
-Brian
 
IncludeBeanCreator.java
------------------------------------
package org.apache.commons.betwixt.io.read;
import org.apache.commons.betwixt.io.BeanReader;
import org.apache.commons.betwixt.BindingConfiguration;
import org.xml.sax.SAXException;
import org.xml.sax.Attributes;
import java.net.URL;
import java.io.IOException;
import java.beans.IntrospectionException;
import java.util.List;
/**
 * BeanCreator that allows for "include" files.  The current element's "include-file" property
 * indicates the name of the XML file that should be processed.  For example, the following
XML indicates
 * that the "venue" property should be created by parsing the file "org/apache/commons/betwixt/io/read/venue.xml":
 * <p/>
 * <p/>
 * <PRE>
 * &lt;?xml version="1.0"?&gt;
 * &lt;PartyBean&gt;
 * &lt;dateOfParty&gt;Wed Apr 14 19:46:55 MDT 2004&lt;/dateOfParty&gt;
 * &lt;excuse&gt;tired&lt;/excuse&gt;
 * &lt;fromHour&gt;2&lt;/fromHour&gt;
 * &lt;venue include-file="org/apache/commons/betwixt/io/read/venue.xml"/&gt;
 * &lt;/PartyBean&gt;
 * </PRE>
 * <p/>
 * The venue.xml file would be a standard XML input for betwixt:
 * <p/>
 * <PRE>
 * &lt;?xml version="1.0"?&gt;
 * &lt;venue&gt;
 * &lt;city&gt;San Francisco&lt;/city&gt;
 * &lt;code&gt;94404&lt;/code&gt;
 * &lt;country&gt;USA&lt;/country&gt;
 * &lt;street&gt;123 Here&lt;/street&gt;
 * &lt;/venue&gt;
 * </PRE>
 * <p/>
 * <p/>
 * The include file is loaded as a resource using the current <code>ClassLoader</code>
following the rules
 * as described by the <code>ClassLoader.getResource</code> method.
 * <p/>
 * The include file is parsed using a <code>BeanReader</code> with the <code>BindingConfiguration</code>
 * and <code>ReadConfiguration</code> which can be explicitly set, or if it is
not set,
 * a default will be used.
 * <p/>
 * The current class (obtained from the <code>ElementMapping</code>) will be registered
with the <code>BeanReader</code>
 * using the "name" of the current <code>ElementMapping</code>.
 *
 * @author Brian Pugh
 */
public class IncludeBeanCreator implements ChainedBeanCreator {
  private BindingConfiguration bindingConfiguration;
  private ReadConfiguration readConfiguration;
  private List parsedFiles;

  /**
   * Constructs a new IncludeBeanCreator.
   */
  public IncludeBeanCreator() {
  }
  /**
   * Constructs a new IncludeBeanCreator.
   *
   * @param bindingConfiguration the <code>BindingConfiguration</code> that will
be used to parse include files.
   */
  public IncludeBeanCreator(BindingConfiguration bindingConfiguration, ReadConfiguration readConfiguration)
{
    setBindingConfiguration(bindingConfiguration);
    setReadConfiguration(readConfiguration);
  }

  /**
   * Get the <code>BindingConfiguration</code> that will be used to parse include
files.
   *
   * @return the <code>BindingConfiguration</code> that will be used to parse
include files.
   */
  public BindingConfiguration getBindingConfiguration() {
    return bindingConfiguration;
  }
  /**
   * Set the <code>BindingConfiguration</code> that will be used to parse include
files.
   *
   * @param bindingConfiguration the <code>BindingConfiguration</code> that will
be used to parse include files.
   */
  public void setBindingConfiguration(BindingConfiguration bindingConfiguration) {
    this.bindingConfiguration = bindingConfiguration;
  }
  /**
   * Get the <code>ReadConfiguration</code> that will be used to parse include
files.
   * @return the <code>ReadConfiguration</code> that will be used to parse include
files.
   */
  public ReadConfiguration getReadConfiguration() {
    return readConfiguration;
  }
  /**
   * Set the <code>ReadConfiguration</code> that will be used to parse include
files.
   * @param readConfiguration the <code>ReadConfiguration</code> that will be
used to parse include files.
   */
  public void setReadConfiguration(ReadConfiguration readConfiguration) {
    this.readConfiguration = readConfiguration;
  }
  /**
   * If the "include-file" attribute is found, the bean is created by parsing the include
xml file.
   * Otherwise bean creation is delegated to the other members of the chain.
   *
   * @param elementMapping specifies the mapping between the type and element.
   * @param context        the context in which this converision happens, not null
   * @param chain          not null
   * @return the Object created, possibly null
   */
  public Object create(ElementMapping elementMapping, ReadContext context, BeanCreationChain
chain) {
    Attributes attributes = elementMapping.getAttributes();
    String file = attributes.getValue("include-file");
    if (file != null && !file.equals("")) {
      BeanReader beanReader = new BeanReader();
      if (bindingConfiguration != null) {
        beanReader.setBindingConfiguration(bindingConfiguration);
      }
      if (readConfiguration != null) {
        beanReader.setReadConfiguration(readConfiguration);
      }
      String name = elementMapping.getName();
      Class clazz = elementMapping.getType();
      ClassLoader loader = getClass().getClassLoader();
      URL url = loader.getResource(file);
      if (url == null) {
        url = loader.getResource("/" + file);
      }
      if (url == null) {
        throw new RuntimeException("Unable to locate include file: " + file);
      }
      try {
        beanReader.registerBeanClass(name, clazz);
        return beanReader.parse(url.toString());        
      }
      catch (IntrospectionException e) {
        throw new RuntimeException("Unable to register class with beanReader.  Classname:
" + clazz, e);
      }
      catch (IOException e) {
        throw new RuntimeException("Unable to process include file: " + file, e);
      }
      catch (SAXException e) {
        throw new RuntimeException("Unable to process include file: " + file, e);
      }
    }
    return chain.create(elementMapping, context);
  }
}

TestInclude.java
----------------------------------------------------------------------
package org.apache.commons.betwixt.io.read;
import junit.framework.TestCase;
import org.apache.commons.betwixt.PartyBean;
import org.apache.commons.betwixt.io.BeanReader;
import java.net.URL;
import java.util.Date;
/**
 * Test the IncludeBeanCreator.
 *
 * @author Brian Pugh
 */
public class TestInclude extends TestCase {

  /**
   * Test IncludeBeanCreator.
   *
   * @throws Exception if test fails.
   */
  public void testInclude() throws Exception {
    URL url = getClass().getClassLoader().getResource("org/apache/commons/betwixt/io/read/party.xml");
    assertNotNull("couldn't load party xml file!", url);
    BeanReader beanReader = new BeanReader();
    beanReader.registerBeanClass(PartyBean.class);
    BeanCreationList chain = BeanCreationList.createStandardChain();
    //put in second place (let the idref creator run first)
    chain.insertBeanCreator(2, new IncludeBeanCreator(beanReader.getBindingConfiguration(),
                                                      beanReader.getReadConfiguration()));
    beanReader.getReadConfiguration().setBeanCreationChain(chain);
    PartyBean result = (PartyBean)beanReader.parse(url.toString());
    assertNotNull("Couldn't read a PartyBean!", result);
    assertEquals("didn't get a Date right!", new Date("Wed Apr 14 19:46:55 MDT 2004"), result.getDateOfParty());
    assertEquals("didn't get excuse right!", "tired", result.getExcuse());
    assertEquals("didn't get fromhour right!", 2, result.getFromHour());
    assertNotNull("didn't get venue back!", result.getVenue());
    assertEquals("didn't get venue city right!", "San Francisco", result.getVenue().getCity());
    assertEquals("didn't get venue code right!", "94404", result.getVenue().getCode());
    assertEquals("didn't get venue country right!", "USA", result.getVenue().getCountry());
    assertEquals("didn't get venue street right!", "123 Here", result.getVenue().getStreet());
  }
}
 
 
XML files (n the org.apache.commons.betwixt.io.read package)
party.xml
----------------------------------------------------------------
<?xml version="1.0"?>
<PartyBean>
    <dateOfParty>Wed Apr 14 19:46:55 MDT 2004</dateOfParty>
    <excuse>tired</excuse>
    <fromHour>2</fromHour>
    <venue include-file="org/apache/commons/betwixt/io/read/venue.xml"/>
</PartyBean>
 
venue.xml
--------------------------------------------------------------
<?xml version="1.0"?>
<venue>
  <city>San Francisco</city>
  <code>94404</code>
  <country>USA</country>
  <street>123 Here</street>
</venue>

 

		
---------------------------------
Do you Yahoo!?
Yahoo! Tax Center - File online by April 15th
Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message