nodeiteratorimpl.java

来自「JAVA 所有包」· Java 代码 · 共 372 行

JAVA
372
字号
/* * Copyright 1999-2002,2004 The Apache Software Foundation. *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *  *      http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.sun.org.apache.xerces.internal.dom;import org.w3c.dom.DOMException;import org.w3c.dom.Node;import org.w3c.dom.traversal.NodeFilter;import org.w3c.dom.traversal.NodeIterator;/** DefaultNodeIterator implements a NodeIterator, which iterates a  *  DOM tree in the expected depth first way.  * *  <p>The whatToShow and filter functionality is implemented as expected. *   *  <p>This class also has method removeNode to enable iterator "fix-up"  *  on DOM remove. It is expected that the DOM implementation call removeNode *  right before the actual DOM transformation. If not called by the DOM, *  the client could call it before doing the removal. *   * @xerces.internal * * @version $Id: NodeIteratorImpl.java,v 1.2.6.1 2005/08/31 12:28:02 sunithareddy Exp $ */public class NodeIteratorImpl implements NodeIterator {        //    // Data    //        /** The DocumentImpl which created this iterator, so it can be detached. */    private DocumentImpl fDocument;    /** The root. */    private Node fRoot;    /** The whatToShow mask. */    private int fWhatToShow = NodeFilter.SHOW_ALL;    /** The NodeFilter reference. */    private NodeFilter fNodeFilter;    /** If detach is called, the fDetach flag is true, otherwise flase. */    private boolean fDetach = false;        //     // Iterator state - current node and direction.    //    // Note: The current node and direction are sufficient to implement    // the desired behaviour of the current pointer being _between_    // two nodes. The fCurrentNode is actually the last node returned,     // and the    // direction is whether the pointer is in front or behind this node.    // (usually akin to whether the node was returned via nextNode())     // (eg fForward = true) or previousNode() (eg fForward = false).    // Note also, if removing a Node, the fCurrentNode    // can be placed on a Node which would not pass filters.         /** The last Node returned. */    private Node fCurrentNode;        /** The direction of the iterator on the fCurrentNode.     *  <pre>     *  nextNode()  ==      fForward = true;     *  previousNode() ==   fForward = false;     *  </pre>     */    private boolean fForward = true;        /** When TRUE, the children of entites references are returned in the iterator. */    private boolean fEntityReferenceExpansion;        //     // Constructor    //        /** Public constructor */    public NodeIteratorImpl( DocumentImpl document,                             Node root,                              int whatToShow,                              NodeFilter nodeFilter,                             boolean entityReferenceExpansion) {        fDocument = document;        fRoot = root;        fCurrentNode = null;        fWhatToShow = whatToShow;        fNodeFilter = nodeFilter;        fEntityReferenceExpansion = entityReferenceExpansion;    }        public Node getRoot() {	return fRoot;    }    // Implementation Note: Note that the iterator looks at whatToShow    // and filter values at each call, and therefore one _could_ add    // setters for these values and alter them while iterating!        /** Return the whatToShow value */    public int                getWhatToShow() {        return fWhatToShow;    }    /** Return the filter */    public NodeFilter         getFilter() {        return fNodeFilter;    }        /** Return whether children entity references are included in the iterator. */    public boolean            getExpandEntityReferences() {        return fEntityReferenceExpansion;    }                /** Return the next Node in the Iterator. The node is the next node in      *  depth-first order which also passes the filter, and whatToShow.      *  If there is no next node which passes these criteria, then return null.     */    public Node               nextNode() {            	if( fDetach) {    		throw new DOMException(    		DOMException.INVALID_STATE_ERR,                 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));        }                // if root is null there is no next node.        if (fRoot == null) return null;                Node nextNode = fCurrentNode;        boolean accepted = false; // the next node has not been accepted.             accepted_loop:        while (!accepted) {                        // if last direction is not forward, repeat node.            if (!fForward && nextNode!=null) {                //System.out.println("nextNode():!fForward:"+fCurrentNode.getNodeName());                nextNode = fCurrentNode;            } else {             // else get the next node via depth-first                if (!fEntityReferenceExpansion                    && nextNode != null                    && nextNode.getNodeType() == Node.ENTITY_REFERENCE_NODE) {                    nextNode = nextNode(nextNode, false);                } else {                    nextNode = nextNode(nextNode, true);                }            }               fForward = true; //REVIST: should direction be set forward before null check?                        // nothing in the list. return null.            if (nextNode == null) return null;                         // does node pass the filters and whatToShow?            accepted = acceptNode(nextNode);            if (accepted) {                // if so, then the node is the current node.                fCurrentNode = nextNode;                return fCurrentNode;            } else                 continue accepted_loop;                    } // while (!accepted) {                // no nodes, or no accepted nodes.        return null;                }        /** Return the previous Node in the Iterator. The node is the next node in      *  _backwards_ depth-first order which also passes the filter, and whatToShow.      */    public Node               previousNode() {            	if( fDetach) {    		throw new DOMException(    		DOMException.INVALID_STATE_ERR,                 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));        }         // if the root is null, or the current node is null, return null.        if (fRoot == null || fCurrentNode == null) return null;               Node previousNode = fCurrentNode;        boolean accepted = false;                accepted_loop:        while (!accepted) {                        if (fForward && previousNode != null) {                //repeat last node.                previousNode = fCurrentNode;            } else {                 // get previous node in backwards depth first order.                previousNode = previousNode(previousNode);            }                        // we are going backwards            fForward = false;                        // if the new previous node is null, we're at head or past the root,            // so return null.             if (previousNode == null) return null;                        // check if node passes filters and whatToShow.            accepted = acceptNode(previousNode);            if (accepted) {                // if accepted, update the current node, and return it.                fCurrentNode = previousNode;                return fCurrentNode;            } else                 continue accepted_loop;        }        // there are no nodes?        return null;    }                    /** The node is accepted if it passes the whatToShow and the filter. */    boolean acceptNode(Node node) {                        if (fNodeFilter == null) {                        return ( fWhatToShow & (1 << node.getNodeType()-1)) != 0 ;        } else {            return ((fWhatToShow & (1 << node.getNodeType()-1)) != 0 )                 && fNodeFilter.acceptNode(node) == NodeFilter.FILTER_ACCEPT;        }    }         /** Return node, if matches or any parent if matches. */    Node matchNodeOrParent(Node node) {        // Additions and removals in the underlying data structure may occur        // before any iterations, and in this case the reference_node is null.        if (fCurrentNode == null) return null;                // check if the removed node is an _ancestor_ of the         // reference node        for (Node n = fCurrentNode; n != fRoot; n = n.getParentNode()) {            if (node == n) return n;        }        return null;    }        /** The method nextNode(Node, boolean) returns the next node      *  from the actual DOM tree.     *      *  The boolean visitChildren determines whether to visit the children.     *  The result is the nextNode.     */    Node nextNode(Node node, boolean visitChildren) {                    if (node == null) return fRoot;        Node result;        // only check children if we visit children.        if (visitChildren) {            //if hasChildren, return 1st child.            if (node.hasChildNodes()) {                result = node.getFirstChild();                return result;            }        }                    if (node == fRoot) { //if Root has no kids            return null;        }        // if hasSibling, return sibling        result = node.getNextSibling();        if (result != null) return result;                                // return parent's 1st sibling.        Node parent = node.getParentNode();        while (parent != null && parent != fRoot) {            result = parent.getNextSibling();            if (result != null) {                return result;            } else {                parent = parent.getParentNode();            }                                    } // while (parent != null && parent != fRoot) {                // end of list, return null        return null;                }        /** The method previousNode(Node) returns the previous node      *  from the actual DOM tree.     */    Node previousNode(Node node) {                Node result;                // if we're at the root, return null.        if (node == fRoot) return null;                // get sibling        result = node.getPreviousSibling();        if (result == null) {            //if 1st sibling, return parent            result = node.getParentNode();            return result;        }                // if sibling has children, keep getting last child of child.        if (result.hasChildNodes()            && !(!fEntityReferenceExpansion                && result != null                && result.getNodeType() == Node.ENTITY_REFERENCE_NODE))                {            while (result.hasChildNodes()) {                result = result.getLastChild();            }        }                              return result;    }        /** Fix-up the iterator on a remove. Called by DOM or otherwise,     *  before an actual DOM remove.        */    public void removeNode(Node node) {                // Implementation note: Fix-up means setting the current node properly        // after a remove.                if (node == null) return;                Node deleted = matchNodeOrParent(node);                if (deleted == null) return;                if (fForward) {            fCurrentNode = previousNode(deleted);        } else        // if (!fForward)         {            Node next = nextNode(deleted, false);            if (next!=null) {                // normal case: there _are_ nodes following this in the iterator.                fCurrentNode = next;            } else {                // the last node in the iterator is to be removed,                 // so we set the current node to be the previous one.                fCurrentNode = previousNode(deleted);                fForward = true;            }                        }            }        public void               detach() {        fDetach = true;        fDocument.removeNodeIterator(this);    }    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?