All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.enhydra.xml.dom.DOMTraversal Maven / Gradle / Ivy

The newest version!
/*
 * Enhydra Java Application Server Project
 * 
 * The contents of this file are subject to the Enhydra Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License on
 * the Enhydra web site ( http://www.enhydra.org/ ).
 * 
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 
 * the License for the specific terms governing rights and limitations
 * under the License.
 * 
 * The Initial Developer of the Enhydra Application Server is Lutris
 * Technologies, Inc. The Enhydra Application Server and portions created
 * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s):
 * 
 * $Id: DOMTraversal.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
 */

package org.enhydra.xml.dom;

import java.util.Iterator;
import java.util.TreeMap;

import org.enhydra.xml.lazydom.LazyDOMTraversal;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Entity;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Notation;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;

/**
 * Class that traverse a DOM tree or subtree, calling handler methods for
 * each node.  It is up to the handler methods to make a decision on
 * processing child and element nodes by explictly calling the methods
 * to continue the traversal.  This is gives the handler more control and
 * actually kept the code simpler for both this class and the client.
 * 

* While DOM traversal is straight-forward, traversing the LazyDOM while * avoiding expansion made things tricker. This class, and the derived class * for the LazyDOM, handles these special cases. */ public class DOMTraversal { /** * Option flag to indicate that attributes should be sorted before calling * the handlers. */ public static final int SORT_ATTRIBUTES = 0x01; /** * Option flag to indicate that unspecified attributes should be included. */ public static final int ALL_ATTRIBUTES = 0x02; /** * Interface for node callback object. */ public interface Handler { /** * Handler called for Document nodes. * Call processDocumentType to traverse child nodes. * Call processChildren to traverse child nodes. */ public void handleDocument(Document document) throws Exception; /** * Handler called for DocumentType nodes. * Use processDocumentTypeContents to traverse contain nodes. */ public void handleDocumentType(DocumentType documentType) throws Exception; /** * Handler called for DocumentFragment nodes. * Call processChildren to traverse child nodes. */ public void handleDocumentFragment(DocumentFragment documentFragment) throws Exception; /** * Handler called for Attr nodes. * Call processChildren to traverse child nodes. */ public void handleAttr(Attr attr) throws Exception; /** * Handler called for Entity nodes. * Call processChildren to traverse child nodes. */ public void handleEntity(Entity entity) throws Exception; /** * Handler called for EntityReference nodes. * Call processChildren to traverse child nodes. */ public void handleEntityReference(EntityReference entityRef) throws Exception; /** * Handler called for Element nodes. * Call processChildren to traverse child nodes. * Call processAttributes to traverse attribute nodes. */ public void handleElement(Element element) throws Exception; /** * Handler called for Notation nodes. */ public void handleNotation(Notation notation) throws Exception; /** * Handler called for ProcessingInstruction nodes. */ public void handleProcessingInstruction(ProcessingInstruction pi) throws Exception; /** * Handler called for CDATASection nodes. */ public void handleCDATASection(CDATASection cdata) throws Exception; /** * Handler called for Comment nodes. */ public void handleComment(Comment comment) throws Exception; /** * Handler called for Text nodes. */ public void handleText(Text text) throws Exception; } /** * Implementation of handler that calls a single method for * all node types. */ abstract public class NodeHandler implements Handler { /** * Method that is called for all nodes. */ abstract public void handleNode(Node node) throws Exception; /** * All standrd handler methods. */ public void handleDocument(Document document) throws Exception { handleNode(document); } public void handleDocumentType(DocumentType documentType) throws Exception { handleNode(documentType); } public void handleDocumentFragment(DocumentFragment documentFragment) throws Exception { handleNode(documentFragment); } public void handleAttr(Attr attr) throws Exception { handleNode(attr); } public void handleEntity(Entity entity) throws Exception { handleNode(entity); } public void handleEntityReference(EntityReference entityRef) throws Exception { handleNode(entityRef); } public void handleElement(Element element) throws Exception { handleNode(element); } public void handleNotation(Notation notation) throws Exception { handleNode(notation); } public void handleProcessingInstruction(ProcessingInstruction pi) throws Exception { handleNode(pi); } public void handleCDATASection(CDATASection cdata) throws Exception { handleNode(cdata); } public void handleComment(Comment comment) throws Exception { handleNode(comment); } public void handleText(Text text) throws Exception { handleNode(text); } } /** Handler object for the traversal */ protected Handler fHandler; /** Options controlling the traversal. */ protected int fOptions; /** Current traversal tree depth */ protected int fDepth; /** Are we processing an attribute or its children? */ protected boolean fProcessingAttribute; /** * Constructor. * @param handler The object that will be called to handle each * node. * @param options Bit set of the option flags. */ public DOMTraversal(DOMTraversal.Handler handler, int options) { fHandler = handler; fOptions = options; } /** * Default constructor, set handler later. */ public DOMTraversal(int options) { fOptions = options; } /** * Set the handler. */ public void setHandler(DOMTraversal.Handler handler) { fHandler = handler; } /** * Traverse a DOM tree or subtree. * * @param root The root of the DOM tree or subtree that is to * be traversed. * @exception DOMError Any internal exceptions are encapsulated * in this error. */ public void traverse(Node root) { fDepth = 0; fProcessingAttribute = false; // Don't let XMLObject cause confusion processNode(DOMOps.getActualNode(root)); } /** * Get the current depth in the DOM tree that is being traversed. */ public final int getDepth() { return fDepth; } /** * Are we currently processing an attribute node or its descendents? */ public final boolean processingAttribute() { return fProcessingAttribute; } /** * Process the children of a node. */ public void processChildren(Node node) { fDepth++; for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) { if (!(child instanceof DocumentType)) { processNode(child); } } fDepth--; } /** * Process the attributes of an element. */ public void processAttributes(Element element) { NamedNodeMap attrMap = element.getAttributes(); if (attrMap != null) { fDepth++; if ((fOptions & SORT_ATTRIBUTES) != 0) { processAttrsSorted(attrMap); } else { processAttrsUnsorted(attrMap); } fDepth--; } } /** * Process a DocumentType attribute of a Document node, if it exists. */ public void processDocumentType(Document document) { DocumentType docType = document.getDoctype(); if (docType != null) { processNode(docType); } } /** * Process the contents of a DocumentType node, */ public void processDocumentTypeContents(DocumentType documentType) { processNamedNodeMap(documentType.getEntities()); processNamedNodeMap(documentType.getNotations()); } /** * Process attributes, sorted by name. */ private void processAttrsSorted(NamedNodeMap attrMap) { // Build sorted list int len = attrMap.getLength(); TreeMap map = new TreeMap(); for (int i = 0; i < len; i++) { Node node = attrMap.item(i); map.put(node.getNodeName(), node); } // Process attributes Iterator attrs = map.values().iterator(); while (attrs.hasNext()) { processNode((Node)attrs.next()); } } /** * Process attributes in the order that they occur. */ private void processAttrsUnsorted(NamedNodeMap attrMap) { int len = attrMap.getLength(); for (int i = 0; i < len; i++) { processNode(attrMap.item(i)); } } /** * Process contents of a NamedNodeMap. */ private void processNamedNodeMap(NamedNodeMap nodeMap) { if (nodeMap != null) { fDepth++; int len = nodeMap.getLength(); for (int i = 0; i < len; i++) { processNode(nodeMap.item(i)); } fDepth--; } } /** * Processing based on node type. All nodes go through here. */ protected void processNode(Node node) { try { switch (node.getNodeType()) { case Node.DOCUMENT_NODE: fHandler.handleDocument((Document)node); break; case Node.DOCUMENT_TYPE_NODE: fHandler.handleDocumentType((DocumentType)node); break; case Node.DOCUMENT_FRAGMENT_NODE: fHandler.handleDocumentFragment((DocumentFragment)node); break; case Node.ATTRIBUTE_NODE: processAttr((Attr)node); break; case Node.ELEMENT_NODE: fHandler.handleElement((Element)node); break; case Node.ENTITY_NODE: fHandler.handleEntity((Entity)node); break; case Node.ENTITY_REFERENCE_NODE: fHandler.handleEntityReference((EntityReference)node); break; case Node.NOTATION_NODE: fHandler.handleNotation((Notation)node); break; case Node.PROCESSING_INSTRUCTION_NODE: fHandler.handleProcessingInstruction((ProcessingInstruction)node); break; case Node.TEXT_NODE: fHandler.handleText((Text)node); break; case Node.CDATA_SECTION_NODE: fHandler.handleCDATASection((CDATASection)node); break; case Node.COMMENT_NODE: fHandler.handleComment((Comment)node); break; default: throw new DOMError("unknown node type: " + node.getNodeType()); } } catch (RuntimeException except) { // Just Exception catch from getting 'em throw except; } catch (Exception except) { throw new DOMError(except); } } /** * Process an Attr node. */ private void processAttr(Attr attr) throws Exception { if (((fOptions & ALL_ATTRIBUTES) != 0) || attr.getSpecified()) { fProcessingAttribute = true; fHandler.handleAttr(attr); fProcessingAttribute = false; } } /** * Factory method to create a traverser based on the type of * a document. */ public static DOMTraversal getTraverser(Handler handler, int options, Node node) { /* * Find the document to determine type. The LazyDOM traverser is only * used on instance documents. If a template DOM node is specified, * the template LazyDocument is traverse as any other done. */ if (DOMOps.isLazyDOMInstance(DOMOps.getDocument(node))) { return new LazyDOMTraversal(handler, options); } else { return new DOMTraversal(handler, options); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy