commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From robert burrell donkin <robertburrelldon...@blueyonder.co.uk>
Subject Re: [betwixt] XML includes
Date Sat, 08 May 2004 16:00:05 GMT
hi brian

i've taken a look and i like what i see. so i committed it.

yes, similar things can be done with xml entities but they are not  
always convenient. it would good think about a caching implementation  
(it would cache the results so that a particular file need not need to  
be re-read).

there are a couple of issues with it that are a bit wider then just  
this code.

1 loading classes: really the classloader to be used needs to be  
obtained from digester (which contains code to support proper  
in-container loading) and passed around as part of the configuration

2 exception handling: really need to think about exception handling  
strategy for the reading stuff. it's a bit of a mess at the moment.  
digester takes the approach that implementations can throw whatever  
exceptions they wish.

i'll probably do the work to fix the first sometime soonish but  
comments would be welcome on that and on the second.

- robert

On 16 Apr 2004, at 22:32, b p wrote:

> 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


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


Mime
View raw message