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();
}
}
}