KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > xml > dom > DOMTraversal


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: DOMTraversal.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
22  */

23
24 package org.enhydra.xml.dom;
25
26 import java.util.Iterator JavaDoc;
27 import java.util.TreeMap JavaDoc;
28
29 import org.enhydra.xml.lazydom.LazyDOMTraversal;
30 import org.w3c.dom.Attr JavaDoc;
31 import org.w3c.dom.CDATASection JavaDoc;
32 import org.w3c.dom.Comment JavaDoc;
33 import org.w3c.dom.Document JavaDoc;
34 import org.w3c.dom.DocumentFragment JavaDoc;
35 import org.w3c.dom.DocumentType JavaDoc;
36 import org.w3c.dom.Element JavaDoc;
37 import org.w3c.dom.Entity JavaDoc;
38 import org.w3c.dom.EntityReference JavaDoc;
39 import org.w3c.dom.NamedNodeMap JavaDoc;
40 import org.w3c.dom.Node JavaDoc;
41 import org.w3c.dom.Notation JavaDoc;
42 import org.w3c.dom.ProcessingInstruction JavaDoc;
43 import org.w3c.dom.Text JavaDoc;
44
45 /**
46  * Class that traverse a DOM tree or subtree, calling handler methods for
47  * each node. It is up to the handler methods to make a decision on
48  * processing child and element nodes by explictly calling the methods
49  * to continue the traversal. This is gives the handler more control and
50  * actually kept the code simpler for both this class and the client.
51  * <P>
52  * While DOM traversal is straight-forward, traversing the LazyDOM while
53  * avoiding expansion made things tricker. This class, and the derived class
54  * for the LazyDOM, handles these special cases.
55  */

56 public class DOMTraversal {
57     /**
58      * Option flag to indicate that attributes should be sorted before calling
59      * the handlers.
60      */

61     public static final int SORT_ATTRIBUTES = 0x01;
62
63     /**
64      * Option flag to indicate that unspecified attributes should be included.
65      */

66     public static final int ALL_ATTRIBUTES = 0x02;
67
68     /**
69      * Interface for node callback object.
70      */

71     public interface Handler {
72         /**
73          * Handler called for Document nodes.
74          * Call processDocumentType to traverse child nodes.
75          * Call processChildren to traverse child nodes.
76          */

77         public void handleDocument(Document JavaDoc document) throws Exception JavaDoc;
78
79         /**
80          * Handler called for DocumentType nodes.
81          * Use processDocumentTypeContents to traverse contain nodes.
82          */

83         public void handleDocumentType(DocumentType JavaDoc documentType) throws Exception JavaDoc;
84
85         /**
86          * Handler called for DocumentFragment nodes.
87          * Call processChildren to traverse child nodes.
88          */

89         public void handleDocumentFragment(DocumentFragment JavaDoc documentFragment) throws Exception JavaDoc;
90
91         /**
92          * Handler called for Attr nodes.
93          * Call processChildren to traverse child nodes.
94          */

95         public void handleAttr(Attr JavaDoc attr) throws Exception JavaDoc;
96
97         /**
98          * Handler called for Entity nodes.
99          * Call processChildren to traverse child nodes.
100          */

101         public void handleEntity(Entity JavaDoc entity) throws Exception JavaDoc;
102
103         /**
104          * Handler called for EntityReference nodes.
105          * Call processChildren to traverse child nodes.
106          */

107         public void handleEntityReference(EntityReference JavaDoc entityRef) throws Exception JavaDoc;
108
109         /**
110          * Handler called for Element nodes.
111          * Call processChildren to traverse child nodes.
112          * Call processAttributes to traverse attribute nodes.
113          */

114         public void handleElement(Element JavaDoc element) throws Exception JavaDoc;
115
116         /**
117          * Handler called for Notation nodes.
118          */

119         public void handleNotation(Notation JavaDoc notation) throws Exception JavaDoc;
120
121         /**
122          * Handler called for ProcessingInstruction nodes.
123          */

124         public void handleProcessingInstruction(ProcessingInstruction JavaDoc pi) throws Exception JavaDoc;
125
126         /**
127          * Handler called for CDATASection nodes.
128          */

129         public void handleCDATASection(CDATASection JavaDoc cdata) throws Exception JavaDoc;
130
131         /**
132          * Handler called for Comment nodes.
133          */

134         public void handleComment(Comment JavaDoc comment) throws Exception JavaDoc;
135
136         /**
137          * Handler called for Text nodes.
138          */

139         public void handleText(Text JavaDoc text) throws Exception JavaDoc;
140     }
141
142     /**
143      * Implementation of handler that calls a single method for
144      * all node types.
145      */

146     abstract public class NodeHandler implements Handler {
147         /**
148          * Method that is called for all nodes.
149          */

150         abstract public void handleNode(Node JavaDoc node) throws Exception JavaDoc;
151
152         /**
153          * All standrd handler methods.
154          */

155         public void handleDocument(Document JavaDoc document) throws Exception JavaDoc {
156             handleNode(document);
157         }
158         public void handleDocumentType(DocumentType JavaDoc documentType) throws Exception JavaDoc {
159             handleNode(documentType);
160         }
161         public void handleDocumentFragment(DocumentFragment JavaDoc documentFragment) throws Exception JavaDoc {
162             handleNode(documentFragment);
163         }
164         public void handleAttr(Attr JavaDoc attr) throws Exception JavaDoc {
165             handleNode(attr);
166         }
167         public void handleEntity(Entity JavaDoc entity) throws Exception JavaDoc {
168             handleNode(entity);
169         }
170         public void handleEntityReference(EntityReference JavaDoc entityRef) throws Exception JavaDoc {
171             handleNode(entityRef);
172         }
173         public void handleElement(Element JavaDoc element) throws Exception JavaDoc {
174             handleNode(element);
175         }
176         public void handleNotation(Notation JavaDoc notation) throws Exception JavaDoc {
177             handleNode(notation);
178         }
179         public void handleProcessingInstruction(ProcessingInstruction JavaDoc pi) throws Exception JavaDoc {
180             handleNode(pi);
181         }
182         public void handleCDATASection(CDATASection JavaDoc cdata) throws Exception JavaDoc {
183             handleNode(cdata);
184         }
185         public void handleComment(Comment JavaDoc comment) throws Exception JavaDoc {
186             handleNode(comment);
187         }
188         public void handleText(Text JavaDoc text) throws Exception JavaDoc {
189             handleNode(text);
190         }
191     }
192
193     /** Handler object for the traversal */
194     protected Handler fHandler;
195
196     /** Options controlling the traversal. */
197     protected int fOptions;
198
199     /** Current traversal tree depth */
200     protected int fDepth;
201
202     /** Are we processing an attribute or its children? */
203     protected boolean fProcessingAttribute;
204
205     /**
206      * Constructor.
207      * @param handler The object that will be called to handle each
208      * node.
209      * @param options Bit set of the option flags.
210      */

211     public DOMTraversal(DOMTraversal.Handler handler,
212                         int options) {
213         fHandler = handler;
214         fOptions = options;
215     }
216     
217     /**
218      * Default constructor, set handler later.
219      */

220     public DOMTraversal(int options) {
221         fOptions = options;
222     }
223
224     /**
225      * Set the handler.
226      */

227     public void setHandler(DOMTraversal.Handler handler) {
228         fHandler = handler;
229     }
230     
231     /**
232      * Traverse a DOM tree or subtree.
233      *
234      * @param root The root of the DOM tree or subtree that is to
235      * be traversed.
236      * @exception DOMError Any internal exceptions are encapsulated
237      * in this error.
238      */

239     public void traverse(Node JavaDoc root) {
240         fDepth = 0;
241         fProcessingAttribute = false;
242         // Don't let XMLObject cause confusion
243
processNode(DOMOps.getActualNode(root));
244     }
245
246     /**
247      * Get the current depth in the DOM tree that is being traversed.
248      */

249     public final int getDepth() {
250         return fDepth;
251     }
252
253     /**
254      * Are we currently processing an attribute node or its descendents?
255      */

256     public final boolean processingAttribute() {
257         return fProcessingAttribute;
258     }
259
260     /**
261      * Process the children of a node.
262      */

263     public void processChildren(Node JavaDoc node) {
264         fDepth++;
265         for (Node JavaDoc child = node.getFirstChild(); child != null;
266              child = child.getNextSibling()) {
267             if (!(child instanceof DocumentType JavaDoc)) {
268                 processNode(child);
269             }
270         }
271         fDepth--;
272     }
273     
274     /**
275      * Process the attributes of an element.
276      */

277     public void processAttributes(Element JavaDoc element) {
278         NamedNodeMap JavaDoc attrMap = element.getAttributes();
279         if (attrMap != null) {
280             fDepth++;
281             if ((fOptions & SORT_ATTRIBUTES) != 0) {
282                 processAttrsSorted(attrMap);
283             } else {
284                 processAttrsUnsorted(attrMap);
285             }
286             fDepth--;
287         }
288     }
289
290     /**
291      * Process a DocumentType attribute of a Document node, if it exists.
292      */

293     public void processDocumentType(Document JavaDoc document) {
294         DocumentType JavaDoc docType = document.getDoctype();
295         if (docType != null) {
296             processNode(docType);
297         }
298     }
299
300     /**
301      * Process the contents of a DocumentType node,
302      */

303     public void processDocumentTypeContents(DocumentType JavaDoc documentType) {
304         processNamedNodeMap(documentType.getEntities());
305         processNamedNodeMap(documentType.getNotations());
306     }
307
308     /**
309      * Process attributes, sorted by name.
310      */

311     private void processAttrsSorted(NamedNodeMap JavaDoc attrMap) {
312         // Build sorted list
313
int len = attrMap.getLength();
314         TreeMap JavaDoc map = new TreeMap JavaDoc();
315         for (int i = 0; i < len; i++) {
316             Node JavaDoc node = attrMap.item(i);
317             map.put(node.getNodeName(), node);
318         }
319
320         // Process attributes
321
Iterator JavaDoc attrs = map.values().iterator();
322         while (attrs.hasNext()) {
323             processNode((Node JavaDoc)attrs.next());
324         }
325     }
326
327     /**
328      * Process attributes in the order that they occur.
329      */

330     private void processAttrsUnsorted(NamedNodeMap JavaDoc attrMap) {
331         int len = attrMap.getLength();
332         for (int i = 0; i < len; i++) {
333             processNode(attrMap.item(i));
334         }
335     }
336
337     /**
338      * Process contents of a NamedNodeMap.
339      */

340     private void processNamedNodeMap(NamedNodeMap JavaDoc nodeMap) {
341         if (nodeMap != null) {
342             fDepth++;
343             int len = nodeMap.getLength();
344             for (int i = 0; i < len; i++) {
345                 processNode(nodeMap.item(i));
346             }
347             fDepth--;
348         }
349     }
350
351     /**
352      * Processing based on node type. All nodes go through here.
353      */

354     protected void processNode(Node JavaDoc node) {
355         try {
356             switch (node.getNodeType()) {
357             case Node.DOCUMENT_NODE:
358                 fHandler.handleDocument((Document JavaDoc)node);
359                 break;
360             case Node.DOCUMENT_TYPE_NODE:
361                 fHandler.handleDocumentType((DocumentType JavaDoc)node);
362                 break;
363             case Node.DOCUMENT_FRAGMENT_NODE:
364                 fHandler.handleDocumentFragment((DocumentFragment JavaDoc)node);
365                 break;
366             case Node.ATTRIBUTE_NODE:
367                 processAttr((Attr JavaDoc)node);
368                 break;
369             case Node.ELEMENT_NODE:
370                 fHandler.handleElement((Element JavaDoc)node);
371                 break;
372             case Node.ENTITY_NODE:
373                 fHandler.handleEntity((Entity JavaDoc)node);
374                 break;
375             case Node.ENTITY_REFERENCE_NODE:
376                 fHandler.handleEntityReference((EntityReference JavaDoc)node);
377                 break;
378             case Node.NOTATION_NODE:
379                 fHandler.handleNotation((Notation JavaDoc)node);
380                 break;
381             case Node.PROCESSING_INSTRUCTION_NODE:
382                 fHandler.handleProcessingInstruction((ProcessingInstruction JavaDoc)node);
383                 break;
384             case Node.TEXT_NODE:
385                 fHandler.handleText((Text JavaDoc)node);
386                 break;
387             case Node.CDATA_SECTION_NODE:
388                 fHandler.handleCDATASection((CDATASection JavaDoc)node);
389                 break;
390             case Node.COMMENT_NODE:
391                 fHandler.handleComment((Comment JavaDoc)node);
392                 break;
393             default:
394                 throw new DOMError("unknown node type: " + node.getNodeType());
395             }
396         } catch (RuntimeException JavaDoc except) {
397             // Just Exception catch from getting 'em
398
throw except;
399         } catch (Exception JavaDoc except) {
400             throw new DOMError(except);
401         }
402     }
403
404     /**
405      * Process an Attr node.
406      */

407     private void processAttr(Attr JavaDoc attr) throws Exception JavaDoc {
408         if (((fOptions & ALL_ATTRIBUTES) != 0) || attr.getSpecified()) {
409             fProcessingAttribute = true;
410             fHandler.handleAttr(attr);
411             fProcessingAttribute = false;
412         }
413     }
414
415     /**
416      * Factory method to create a traverser based on the type of
417      * a document.
418      */

419     public static DOMTraversal getTraverser(Handler handler,
420                                             int options,
421                                             Node JavaDoc node) {
422         /*
423          * Find the document to determine type. The LazyDOM traverser is only
424          * used on instance documents. If a template DOM node is specified,
425          * the template LazyDocument is traverse as any other done.
426          */

427         if (DOMOps.isLazyDOMInstance(DOMOps.getDocument(node))) {
428             return new LazyDOMTraversal(handler, options);
429         } else {
430             return new DOMTraversal(handler, options);
431         }
432     }
433 }
434
Popular Tags