package com.javaranch.dynadto; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import org.apache.commons.beanutils.BasicDynaClass; import org.apache.commons.beanutils.DynaBean; import org.apache.commons.beanutils.DynaClass; import org.apache.commons.digester.Digester; import org.xml.sax.SAXException; /** *

A class that makes new instances of Dynamic Data Transfer Objects (DTO). * The DTOs are implementations of org.apache.commons.beanutils.DynaBean. * The DTOS and their properties are specified in an xml configuration file.

* *

The default name of the configuration file is "dto-config.xml", and should * reside somewhere in the classpath. The configuration file is validated * with "dynaDTO.dtd", which can be found in this package, and must point to the * location of this DTD.

* *

An example "dto-config.xml" file:

* *

 * <?xml version="1.0" encoding="ISO-8859-1"?>
 * <!DOCTYPE dto-config SYSTEM "file://C/dynaDTO/dynaDTO.dtd">
 * <dto-config>
 *   <dto name="book" type="org.apache.commons.beanutils.BasicDynaBean">
 *     <property name="title" type="java.lang.String"/>
 *     <property name="isbn" type="java.lang.String"/>
 *   </dto>
 *   <dto name="author">
 *     <property name="firstName" type="java.lang.String"/>
 *     <property name="lastName" type="java.lang.String"/>
 *   </dto>
 * </dto-config>
 * 

* *

Each <dto> element represents a different Data Transfer Object. * The name attribute of the <dto> element indicates the name of * the DTO which will be used when calling newInstance(). The * type attribute of the <dto> element is the class type * instantiated by a call to newInstance(), and must be a class which * implements the org.apache.commons.beanutils.DynaBean interface. * The type attribute is optional, with DTOs of type * com.javaranch.dynadto.DynaDTODynaBean being instantiated if * no type is specified.

* *

The properties of each DTO are specified with <property> elements. * The name of each property is indicated by the name attribute, and the * type of each property is indicated by the type attribute. Both of * these attributes are required.

* *

As has already been mentioned, DTOs are instantiated by a call to the * newInstance() method of the DynaDTOFactory class. If the * above "dto-config.xml" file were used, we could retrieve and use a new * instance of a book DTO in the following manner:

* *

 * DynaDTOFactory factory = new DynaDTOFactory();
 * DynaBean book = factory.newInstance("book");
 * book.set("title", "War and Peace");
 * String title = (String) book.get("title");
 * 

* * @author Jason Menard * @version 1.0 */ public class DynaDTOFactory { /* * The set of DynaClass objects that are part of this factory, * keyed by the name of the DynaBean associated with each DynaClass. */ private Map dynaClassMap = new HashMap(); /* Default file name for the config file. */ private String config = "dto-config.xml"; /** * Constructs a new DynaDTOFactory with default parameters. * @throws FileNotFoundException * @throws IOException * @throws SAXException */ public DynaDTOFactory() throws FileNotFoundException, IOException, SAXException { init(); } /** * Constructs a new DynaDTOFactory with the specified parameters. * @param config the name of the configuration file to use with this * instance * @throws FileNotFoundException * @throws IOException * @throws SAXException */ public DynaDTOFactory(String config) throws FileNotFoundException, IOException, SAXException { this.config = config; init(); } /** * Instantiate a new instance of the specified DynaDTO * @param name the name of the DynaDTO to return * @return a new instance of the DynaDTO specified * @throws java.lang.InstantiationException * @throws java.lang.IllegalAccessException */ public DynaBean newInstance(String name) throws InstantiationException, IllegalAccessException { DynaBean dynaBean = null; DynaClass dynaClass = (DynaClass) dynaClassMap.get(name); if (dynaClass != null) { dynaBean = dynaClass.newInstance(); } return dynaBean; } /** * Add a DynaClass to the DynaDTOFactory * @param dynaClass the DynaClass to add to this factory */ void addDynaClass(DynaClass dynaClass) { dynaClassMap.put(dynaClass.getName(), dynaClass); } /* Initialize the DynaDTOFactory by digesting the config file */ private void init() throws FileNotFoundException, IOException, SAXException { InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(config); if (is == null) { throw new FileNotFoundException(config + " file not found."); } Digester digester = new Digester(); digester.setNamespaceAware(true); digester.setValidating(true); digester.setUseContextClassLoader(true); digester.addRuleSet(new DynaDTORuleSet()); digester.push(this); digester.parse(is); is.close(); } public static void main(String[] args) { try { DynaDTOFactory ddf = null; ddf = new DynaDTOFactory(); DynaDTODynaBean program = (DynaDTODynaBean)ddf.newInstance("program"); program.set("name", "KIV-7"); System.out.println(program.get("name")); System.out.println(program); } catch (Exception e) { e.printStackTrace(); } } }