KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sapia > util > xml > confix > Dom4jProcessor


1 package org.sapia.util.xml.confix;
2
3
4 // Import of dom4j classes
5
// ----------------------
6
import org.dom4j.Attribute;
7 import org.dom4j.Document;
8 import org.dom4j.DocumentException;
9 import org.dom4j.DocumentHelper;
10 import org.dom4j.Element;
11
12
13 import org.dom4j.io.OutputFormat;
14 import org.dom4j.io.SAXReader;
15 import org.dom4j.io.XMLWriter;
16
17 // Import of Sapia's utility classes
18
// ---------------------------------
19
import org.sapia.util.xml.ProcessingException;
20 import org.xml.sax.InputSource JavaDoc;
21
22 // Import of Sun's JDK classes
23
// ---------------------------
24
import java.io.ByteArrayInputStream JavaDoc;
25 import java.io.ByteArrayOutputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.io.UnsupportedEncodingException JavaDoc;
29
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32
33 /**
34  * This class creates an object graph for a given XML input stream. It internally
35  * uses Dom4J to transform the stream into a document object model, and then to create
36  * objects from the elements found in the document.
37  * <p>
38  * Usage:
39  * <p>
40  * <pre>
41  * ObjectFactoryIF fac = new ReflectionFactory("com.newtrade.company");
42  * Dom4jProcessor proc = new Dom4jProcessor(fac);
43  * Company comp = (Company)proc.process(new FileInputStream("d:/dev/company.xml"));
44  * </pre>
45  *
46  * @author Yanick Duchesne
47  *
48  * <dl>
49  * <dt><b>Copyright:</b><dd>Copyright &#169; 2002-2003 <a HREF="http://www.sapia-oss.org">Sapia Open Source Software</a>. All Rights Reserved.</dd></dt>
50  * <dt><b>License:</b><dd>Read the license.txt file of the jar or visit the
51  * <a HREF="http://www.sapia-oss.org/license.html">license page</a> at the Sapia OSS web site</dd></dt>
52  * </dl>
53  */

54 public class Dom4jProcessor extends AbstractXMLProcessor {
55   /////////////////////////////////////////////////////////////////////////////////////////
56
//////////////////////////////////// CONSTRUCTORS /////////////////////////////////////
57
/////////////////////////////////////////////////////////////////////////////////////////
58

59   /**
60    * Creates a new JDOMProcessor instance with the argument passed in.
61    *
62    * @param anObjectFactory The object factory of this processor.
63    */

64   public Dom4jProcessor(ObjectFactoryIF anObjectFactory) {
65     super(anObjectFactory);
66   }
67
68   /////////////////////////////////////////////////////////////////////////////////////////
69
////////////////////////////////// OVERRIDEN METHODS //////////////////////////////////
70
/////////////////////////////////////////////////////////////////////////////////////////
71

72   /**
73    * This method takes an XML stream as input and returns an object
74    * representation of the passed-in XML.
75    *
76    * @param is an XML stream
77    * @return an object representation of the XML stream.
78    * @exception ProcessingException
79    */

80   public Object JavaDoc process(InputStream JavaDoc is) throws ProcessingException {
81     try {
82       // Build the document from the input stream
83
SAXReader builder = new SAXReader();
84       builder.setStripWhitespaceText(false);
85       builder.setMergeAdjacentText(false);
86       Document doc = builder.read(is);
87
88       // Process the document
89
Object JavaDoc aResult = process(null, doc.getRootElement());
90
91       return aResult;
92     } catch (DocumentException de) {
93       String JavaDoc aMessage = "Error parsing the XML of the input stream.";
94       throw new ProcessingException(aMessage, de);
95     } finally {
96       try {
97         if (is != null) {
98           is.close();
99         }
100       } catch (IOException JavaDoc ioe) {
101         String JavaDoc aMessage = "Error closing the input stream to process.";
102
103         throw new ProcessingException(aMessage, ioe);
104       }
105     }
106   }
107
108   /**
109    * This method takes an object and assigns to it the object representation
110    * of the passed XML stream.
111    *
112    * @param root an <code>Object</code> that is the root of the object graph to create
113    * from the given XML.
114    * @param is an XML <code>InputStream</code>.
115    * @throws ProcessingException if an error occurs while processing the given XML stream.
116    */

117   public void process(Object JavaDoc root, InputStream JavaDoc is) throws ProcessingException {
118     try {
119       // Build the document from the input stream
120
SAXReader reader = new SAXReader();
121       Document doc = reader.read(is);
122
123       // Process the document
124
Object JavaDoc aResult = process(root, doc.getRootElement());
125     } catch (DocumentException de) {
126       String JavaDoc aMessage = "Error parsing the XML of the input stream.";
127       throw new ProcessingException(aMessage, de);
128     } finally {
129       try {
130         if (is != null) {
131           is.close();
132         }
133       } catch (IOException JavaDoc ioe) {
134         String JavaDoc aMessage = "Error closing the input stream to process.";
135
136         throw new ProcessingException(aMessage, ioe);
137       }
138     }
139   }
140
141   /////////////////////////////////////////////////////////////////////////////////////////
142
/////////////////////////////////// HELPER METHODS ////////////////////////////////////
143
/////////////////////////////////////////////////////////////////////////////////////////
144

145   /**
146    * This method will process the dom element passed in to create an object.
147    *
148    * @param aParent The parent object of the one to create.
149    * @param anElement The dom element to process.
150    * @exception ProcessingException If an error occurs while processing the dom tree.
151    */

152   public Object JavaDoc process(Object JavaDoc aParent, Element anElement)
153     throws ProcessingException {
154     return process(aParent, anElement, null);
155   }
156
157   private Object JavaDoc process(Object JavaDoc aParent, Element anElement, String JavaDoc setterName)
158     throws ProcessingException {
159     String JavaDoc aName = anElement.getName();
160     
161     if (setterName == null) {
162       setterName = aName;
163     }
164
165     CreationStatus status = null;
166
167     try {
168       status = getObjectFactory().newObjectFor(anElement.getNamespace()
169                                                         .getPrefix(),
170           anElement.getNamespace().getURI(), aName, aParent);
171     } catch (ObjectCreationException oce) {
172       if (aParent == null) {
173         String JavaDoc aMessage = "Unable to create an object for the element " +
174           anElement;
175
176         throw new ProcessingException(aMessage, oce);
177       }
178             List JavaDoc children;
179       if ((aParent != null) &&
180             (containsMethod("set", aParent, aName) ||
181             containsMethod("add", aParent, aName)) &&
182             ((children = anElement.elements()).size() == 1)) {
183         Element child = (Element) children.get(0);
184         process(aParent, child, setterName);
185
186         return aParent;
187       }
188
189       try {
190         String JavaDoc aValue = anElement.getTextTrim();
191
192         invokeSetter(aParent.getClass().getName(), aParent, aName, aValue);
193
194         return aParent;
195       } catch (ConfigurationException ce) {
196         String JavaDoc aMessage =
197           "Unable to create an object nor to call a setter for the element " +
198           anElement;
199         oce.printStackTrace();
200         throw new ProcessingException(aMessage, ce);
201       }
202     }
203
204     String JavaDoc text = anElement.getTextTrim();
205
206     if (text.length() > 0) {
207       try {
208         invokeSetter(aName, status.getCreated(), "Text", text);
209       } catch (ConfigurationException ce) {
210         String JavaDoc aMessage = "The object '" + aName +
211           "' does not accept free text";
212
213         throw new ProcessingException(aMessage, ce);
214       }
215     }
216
217     try {
218       // Process the attributes of the DOM element
219
for (Iterator JavaDoc it = anElement.attributeIterator(); it.hasNext();) {
220         Attribute attr = (Attribute) it.next();
221
222         invokeSetter(aName, status.getCreated(), attr.getName(), attr.getValue());
223       }
224
225       // Process the child elements
226
for (Iterator JavaDoc it = anElement.elementIterator(); it.hasNext();) {
227         Element child = (Element) it.next();
228
229         if (status.getCreated() instanceof Dom4jHandlerIF) {
230           ((Dom4jHandlerIF) status.getCreated()).handleElement(child);
231         } else if(status.getCreated() instanceof XMLConsumer) {
232             XMLConsumer cons = (XMLConsumer)status.getCreated();
233           ByteArrayOutputStream JavaDoc bos = new ByteArrayOutputStream JavaDoc();
234                     XMLWriter writer;
235                     try{
236                         writer = new XMLWriter(bos, OutputFormat.createPrettyPrint());
237                     }catch(UnsupportedEncodingException JavaDoc e){
238                         throw new ProcessingException("Could not instantiate XMLWriter", e);
239                     }
240                                
241                     try{
242                         Element copy = child.createCopy();
243                         copy.setDocument(null);
244             writer.write(DocumentHelper.createDocument(copy));
245             ByteArrayInputStream JavaDoc in = new ByteArrayInputStream JavaDoc(bos.toByteArray());
246             InputSource JavaDoc is = new InputSource JavaDoc(in);
247             cons.consume(is);
248           }catch(Exception JavaDoc e){
249             throw new ProcessingException("Could not pipe content of element: " + child.getQualifiedName() + " to XMLConsumer", e);
250           }
251         } else {
252           process(status.getCreated(), child);
253         }
254       }
255
256       // before assigning to parent, check if object
257
// implements ObjectCreationCallback.
258
if (status.getCreated() instanceof ObjectCreationCallback) {
259         status._created = ((ObjectCreationCallback) status.getCreated()).onCreate();
260       }
261
262       // assign obj to parent through setXXX or addXXX
263
if ((aParent != null) && !status.wasAssigned() &&
264             !(status.getCreated() instanceof NullObject)) {
265         assignToParent(aParent, status.getCreated(), setterName);
266       }
267
268       if (status.getCreated() instanceof NullObject) {
269         return null;
270       }
271
272       return status.getCreated();
273     } catch (ConfigurationException ce) {
274       String JavaDoc aMessage = "Unable to process the content of the element " +
275         aName;
276
277       throw new ProcessingException(aMessage, ce);
278     }
279   }
280 }
281
Popular Tags