using XML to package data
ipozeng Mar 21, 2002 8:29 PMThe following is a general class used to package data in XML format. I copied it from some place and i really want to hear your comments about it :
//Import the JAXP classes.
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
//Import the DOM classes.
import org.w3c.dom.Document;
import org.w3c.dom.Element;
//Import the EJB classes.
import javax.ejb.EJBLocalObject;
//Import the Collection classes.
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
//Import the bean introspection classes.
import java.beans.Introspector;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.beans.IntrospectionException;
//Import the reflection classes:
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
/**
usage:
User user = userHome.findByPrimaryKey("1");
return new DOMGenerator("user",4).getDOM(user);
(the User is a EJBLocalObject)
entity relation:
UserEJB -------<-ServiceRequestEJB------>ProductEJB
| |
| --------<-ServiceRequestHistoryEJB
|-----------<-PhoneEJB
result:
<?xml version="1.0" encoding="UTF-8"?>
<requests-child description="Outlook not working" id="2" status="P">
</requests-child>
<requests-child description="PC not booting" id="1" status="O">
<histories-child description="Informtion requested" id="2"
loggedAt="2000-12-12 12:12:12.0"/>
<histories-child description="Request logged" id="1"
loggedAt="2000-12-12 00:00:00.0"/>
</requests-child>
<phones-child id="2" number="0771 8210586" type="M"/>
<phones-child id="1" number="01908 251575" type="W"/>
*/
public class DOMGenerator
{
//The document that is generated:
private Document doc;
//Drill-down depth defined by the user:
private int drillDownDepth;
//A private instance variable to store circular references:
private ArrayList _circularRef = new ArrayList();
//A private instance variable to store the current depth of the drilldown:
private int _currentDepth;
//The methods getEJBLocalHome, getLocalHandle, getClass and getPrimaryKey need not be processed.
private static String RESERVED = "EJBLocalHome^localHandle^class^primaryKey";
public DOMGenerator(String docElementName, int drillDownDepth)
{
try {
//Use standard JAXP calls to create a DOM and store it as an instance variable.
DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = fact.newDocumentBuilder();
doc = builder.newDocument();
}
catch(ParserConfigurationException ex) {
throw new RuntimeChainedException(ex);
}
//Store the drilldown depth.
this.drillDownDepth = drillDownDepth;
//Create the document element by the name defined by the user.
doc.appendChild(doc.createElement(docElementName));
}
//This method passes the local reference for which the DOM is to be created.
public Document getDOM(EJBLocalObject local)
{
try {
//Call the method to populate the element with container managed persistent and
//relationship fields for the passed local reference.
populateElement(doc.getDocumentElement(), local);
//Return the DOM.
return doc;
}
catch(IntrospectionException ex) {
throw new RuntimeException(ex.getMessage());
}catch(IllegalAccessException ex) {
throw new RuntimeException(ex.getMessage());
}catch(InvocationTargetException ex) {
throw new RuntimeException(ex.getMessage());
}
}
private void populateElement(Element parent, EJBLocalObject local)
throws IntrospectionException, IllegalAccessException, InvocationTargetException
{
//Add the current local reference to the list of linked references.
_circularRef.add(local);
//Increment the current drilldown depth.
_currentDepth++;
//Get the bean information for the current local references.
BeanInfo info = Introspector.getBeanInfo(local.getClass());
//Get the list of property descriptors and iterate through the array.
PropertyDescriptor[] properties = info.getPropertyDescriptors();
for(int i = 0;i < properties.length;i++) {
//Get the property read method.
Method propReadMethod = properties.getReadMethod();
//Get the property name.
String propName = properties.getName();
//Get the property value using reflection.
Object prop = propReadMethod.invoke(local, null);
//Skip the reserved properties.
if(RESERVED.indexOf(propName) >= 0)
continue;
try {
//Try casting the property to an EJB local reference. Please note that you can't use
//instanceof because the implementation may vary from container to container.
EJBLocalObject locProp = (EJBLocalObject)prop;
//If the local reference is already available in the list of link references or the
//current drilldown depth is greater than the set drilldown depth, skip processing.
if(isCircularRef(locProp) || _currentDepth >= drillDownDepth)
continue;
//Create an element by the property.
Element child = doc.createElement(propName);
//Recursively populate the newly created element with the persistent and the
//relationship fields of the child local reference.
populateElement(child, locProp);
//Add the newly created child to the parent.
parent.appendChild(child);
}
catch(ClassCastException ex1) {
//If a ClassCastException is thrown, try casting the property to a collection of local
//references. Please note that you can't use instanceof because the implementation
//may vary from container to container.
try {
Collection colProp = (Collection)prop;
//If the current drilldown depth is greater than the set drilldown depth, skip processing.
if(_currentDepth >= drillDownDepth)
continue;
//Create a child element that will encapsulate the collection.
Element child = doc.createElement(propName);
Iterator it = colProp.iterator();
while(it.hasNext()) {
//Get each local reference in the collection.
EJBLocalObject locProp = (EJBLocalObject)it.next();
//If the local reference is already available in the list of link references or the
//current drilldown depth is greater than the set drilldown depth, skip processing.
if(isCircularRef(locProp))
continue;
//Create an element that will contain the persistent and relationship information for
//the current local reference in the collection, add it to the element representing the
//collection and populate it.
Element grandChild = doc.createElement(propName + "-child");
child.appendChild(grandChild);
populateElement(grandChild, locProp);
}
//Populate the parent with the child.
parent.appendChild(child);
}
catch(ClassCastException ex2) {
//If a ClassCastException is thrown, the property is a persistent field and add its
//value as an attribute to the current node.
parent.setAttribute(propName, prop.toString()); }
}
}
//Remove the current local reference from the list to track circular references.
_circularRef.remove(local);
//Decrement the current drilldown depth.
_currentDepth--;
}
//This is a utility method to check whether a reference is already there in the list
//of linked references.
private boolean isCircularRef(EJBLocalObject local)
{
Iterator it = _circularRef.iterator();
while(it.hasNext())
if(local.isIdentical((EJBLocalObject)it.next()))
return true;
return false;
}
}
Best Regards!