0 Replies Latest reply on Mar 21, 2002 8:29 PM by IPOz

    using XML to package data

    IPOz Newbie

      The 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!