You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by rp...@locus.apache.org on 2000/01/26 03:18:24 UTC

cvs commit: xml-xerces/java/src/org/apache/xerces/dom NodeIteratorImpl.java TreeWalkerImpl.java Makefile

rpfeiffe    00/01/25 18:18:24

  Modified:    java/src/org/apache/xerces/dom Makefile
  Added:       java/src/org/apache/xerces/dom NodeIteratorImpl.java
                        TreeWalkerImpl.java
  Log:
  The NodeIteratorImpl.java and the TreeWalkerImpl.java are
  being moved from the dom.traversal package/dir up to the dom
  package/dir.
  
  Revision  Changes    Path
  1.5       +3 -3      xml-xerces/java/src/org/apache/xerces/dom/Makefile
  
  Index: Makefile
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/Makefile,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Makefile	2000/01/21 22:21:03	1.4
  +++ Makefile	2000/01/26 02:18:24	1.5
  @@ -46,15 +46,16 @@
   	NamedNodeMapImpl.class\
   	NodeContainer.class\
   	NodeImpl.class\
  +	NodeIteratorImpl.class\
   	NotationImpl.class\
   	ProcessingInstructionImpl.class\
  -	TextImpl.class
  +	TextImpl.class\
  +	TreeWalkerImpl.class
   
   all: dirs compile
   
   dirs:
   	${MAKE} -C events
  -	${MAKE} -C traversal
   
   compile: ${TARGETS}
   
  @@ -70,5 +71,4 @@
   clean:
   	${RM} *.class
   	${MAKE} -C events clean
  -	${MAKE} -C traversal clean
   
  
  
  
  1.1                  xml-xerces/java/src/org/apache/xerces/dom/NodeIteratorImpl.java
  
  Index: NodeIteratorImpl.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.apache.org.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.xerces.dom;
  
  import org.w3c.dom.*;
  import org.w3c.dom.traversal.*;
  import org.apache.xerces.dom.DocumentImpl;
  import org.apache.xerces.dom.DOMExceptionImpl;
  
  /** 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.
   */
  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;
      }
      
      // 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 DOMExceptionImpl(
      			DOMExceptionImpl.INVALID_STATE_ERR, 
      		    "INVALID_STATE_ERR");
          }
          
          // 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 DOMExceptionImpl(
      			DOMExceptionImpl.INVALID_STATE_ERR, 
      		    "INVALID_STATE_ERR");
          }
   
          // 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) {
          for (Node n = node; 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 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);
      }
      
  }
  
  
  
  1.1                  xml-xerces/java/src/org/apache/xerces/dom/TreeWalkerImpl.java
  
  Index: TreeWalkerImpl.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.apache.org.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.xerces.dom;
  
  import org.w3c.dom.*;
  import org.w3c.dom.traversal.*;
  
  /** This class implements the TreeWalker interface. */
  public class TreeWalkerImpl implements TreeWalker {
      
      //
      // Data
      //
      
      /** When TRUE, the children of entites references are returned in the iterator. */
      private boolean fEntityReferenceExpansion = false;
      /** The whatToShow mask. */
      int fWhatToShow = NodeFilter.SHOW_ALL;
      /** The NodeFilter reference. */
      NodeFilter fNodeFilter;
      /** The current Node. */
      Node fCurrentNode;
      /** The root Node. */
      Node fRoot;
      
      //
      // Implementation Note: No state is kept except the data above
      // (fWhatToShow, fNodeFilter, fCurrentNode, fRoot) such that 
      // setters could be created for these data values and the 
      // implementation will still work.
      
      
      // 
      // Constructor
      //
      
      /** Public constructor */
      public TreeWalkerImpl(Node root, 
                            int whatToShow, 
                            NodeFilter nodeFilter,
                            boolean entityReferenceExpansion) {
          fCurrentNode = root;
          fRoot = root;
          fWhatToShow = whatToShow;
          fNodeFilter = nodeFilter;
          fEntityReferenceExpansion = entityReferenceExpansion;
      }
      
      /** Return the whatToShow value */
      public int                getWhatToShow() {
          return fWhatToShow;
      }
  
      /** Return the NodeFilter */
      public NodeFilter         getFilter() {
          return fNodeFilter;
      }
      
      /** Return whether children entity references are included in the iterator. */
      public boolean            getExpandEntityReferences() {
          return fEntityReferenceExpansion;
      }
              
      /** Return the current Node. */
      public Node               getCurrentNode() {
          return fCurrentNode;
      }
      /** Return the current Node. */
      public void               setCurrentNode(Node node) {
          fCurrentNode = node;
      }
      
      /** Return the parent Node from the current node, 
       *  after applying filter, whatToshow.
       *  If result is not null, set the current Node.
       */
      public Node               parentNode() {
  
          if (fCurrentNode == null) return null;
                  
          Node node = getParentNode(fCurrentNode);
          if (node !=null) {
              fCurrentNode = node;
          }
          return node;
          
      }
  
      /** Return the first child Node from the current node, 
       *  after applying filter, whatToshow.
       *  If result is not null, set the current Node.
       */
      public Node               firstChild() {
          
          if (fCurrentNode == null) return null;
                  
          Node node = getFirstChild(fCurrentNode);
          if (node !=null) {
              fCurrentNode = node;
          }
          return node;
      }
      /** Return the last child Node from the current node, 
       *  after applying filter, whatToshow.
       *  If result is not null, set the current Node.
       */
      public Node               lastChild() {
  
          if (fCurrentNode == null) return null;
                  
          Node node = getLastChild(fCurrentNode);
          if (node !=null) {
              fCurrentNode = node;
          }
          return node;
      }
      
      /** Return the previous sibling Node from the current node, 
       *  after applying filter, whatToshow.
       *  If result is not null, set the current Node.
       */
      public Node               previousSibling() {
  
          if (fCurrentNode == null) return null;
                  
          Node node = getPreviousSibling(fCurrentNode);
          if (node !=null) {
              fCurrentNode = node;
          }
          return node;
      }
      
      /** Return the next sibling Node from the current node, 
       *  after applying filter, whatToshow.
       *  If result is not null, set the current Node.
       */
      public Node               nextSibling(){
          if (fCurrentNode == null) return null;
                  
          Node node = getNextSibling(fCurrentNode);
          if (node !=null) {
              fCurrentNode = node;
          }
          return node;
      }
      
      /** Return the previous Node from the current node, 
       *  after applying filter, whatToshow.
       *  If result is not null, set the current Node.
       */
      public Node               previousNode() {
          Node result;
          
          if (fCurrentNode == null) return null;
          
          // get sibling
          result = getPreviousSibling(fCurrentNode);
          if (result == null) {
              result = getParentNode(fCurrentNode);
              if (result != null) {
                  fCurrentNode = result;
                  return fCurrentNode;
              } 
              return null;
          }
          
          // get the lastChild of result.
          Node lastChild  = getLastChild(result);
          
          Node prev = lastChild ;
          while (lastChild != null) {
            prev = lastChild ;
            lastChild = getLastChild(prev) ;
          }
  
          lastChild = prev ;
          
          // if there is a lastChild which passes filters return it.
          if (lastChild != null) {
              fCurrentNode = lastChild;
              return fCurrentNode;
          } 
          
          // otherwise return the previous sibling.
          if (result != null) {
              fCurrentNode = result;
              return fCurrentNode;
          }
          
          // otherwise return null.
          return null;
      }
      
      /** Return the next Node from the current node, 
       *  after applying filter, whatToshow.
       *  If result is not null, set the current Node.
       */
      public Node               nextNode() {
          
          if (fCurrentNode == null) return null;
          
          Node result = getFirstChild(fCurrentNode);
          
          if (result != null) {
              fCurrentNode = result;
              return result;
          }
          
          result = getNextSibling(fCurrentNode);
          
          if (result != null) {
              fCurrentNode = result;
              return result;
          }
                  
          // return parent's 1st sibling.
          Node parent = getParentNode(fCurrentNode);
          while (parent != null) {
              result = getNextSibling(parent);
              if (result != null) {
                  fCurrentNode = result;
                  return result;
              } else {
                  parent = getParentNode(parent);
              }
          }
          
          // end , return null
          return null;
      }
      
      /** Internal function.
       *  Return the parent Node, from the input node
       *  after applying filter, whatToshow.
       *  The current node is not consulted or set.
       */
      Node getParentNode(Node node) {
          
          if (node == null || node == fRoot) return null;
          
          Node newNode = node.getParentNode();
          if (newNode == null)  return null; 
                          
          int accept = acceptNode(newNode);
          
          if (accept == NodeFilter.FILTER_ACCEPT)
              return newNode;
          else 
          //if (accept == NodeFilter.SKIP_NODE) // and REJECT too.
          {
              return getParentNode(newNode);
          }
          
          
      }
      
      /** Internal function.
       *  Return the nextSibling Node, from the input node
       *  after applying filter, whatToshow.
       *  The current node is not consulted or set.
       */
      Node getNextSibling(Node node) {
          
          if (node == null || node == fRoot) return null;
          
          Node newNode = node.getNextSibling();
          if (newNode == null) {
                  
              newNode = node.getParentNode();
                  
              if (newNode == null || node == fRoot)  return null; 
                  
              int parentAccept = acceptNode(newNode);
                  
              if (parentAccept==NodeFilter.FILTER_SKIP) {
                  return getNextSibling(newNode);
              }
                  
              return null;
          }
          
          int accept = acceptNode(newNode);
          
          if (accept == NodeFilter.FILTER_ACCEPT)
              return newNode;
          else 
          if (accept == NodeFilter.FILTER_SKIP) {
              Node fChild =  getFirstChild(newNode);
              if (fChild == null) {
                  return getNextSibling(newNode);
              }
              return fChild;
          }
          else 
          //if (accept == NodeFilter.REJECT_NODE) 
          {
              return getNextSibling(newNode);
          }
          
      } // getNextSibling(Node node) {
      
      /** Internal function.
       *  Return the previous sibling Node, from the input node
       *  after applying filter, whatToshow.
       *  The current node is not consulted or set.
       */
      Node getPreviousSibling(Node node) {
          
          if (node == null || node == fRoot) return null;
          
          Node newNode = node.getPreviousSibling();
          if (newNode == null) {
                  
              newNode = node.getParentNode();
              if (newNode == null || node == fRoot)  return null; 
                  
              int parentAccept = acceptNode(newNode);
                  
              if (parentAccept==NodeFilter.FILTER_SKIP) {
                  return getPreviousSibling(newNode);
              }
              
              return null;
          }
          
          int accept = acceptNode(newNode);
          
          if (accept == NodeFilter.FILTER_ACCEPT)
              return newNode;
          else 
          if (accept == NodeFilter.FILTER_SKIP) {
              Node fChild =  getLastChild(newNode);
              if (fChild == null) {
                  return getPreviousSibling(newNode);
              }
              return fChild;
          }
          else 
          //if (accept == NodeFilter.REJECT_NODE) 
          {
              return getPreviousSibling(newNode);
          }
          
      } // getPreviousSibling(Node node) {
      
      /** Internal function.
       *  Return the first child Node, from the input node
       *  after applying filter, whatToshow.
       *  The current node is not consulted or set.
       */
      Node getFirstChild(Node node) {
          
          if (node == null) return null;
          
          if ( !fEntityReferenceExpansion
               && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
              return null;
     
          Node newNode = node.getFirstChild();
          if (newNode == null)  return null;
          
          int accept = acceptNode(newNode);
          
          if (accept == NodeFilter.FILTER_ACCEPT)
              return newNode;
          else 
          if (accept == NodeFilter.FILTER_SKIP
              && newNode.hasChildNodes()) 
          {
              return getFirstChild(newNode);
          }
          else 
          //if (accept == NodeFilter.REJECT_NODE) 
          {
              return getNextSibling(newNode);
          }
          
          
      }
     
      /** Internal function.
       *  Return the last child Node, from the input node
       *  after applying filter, whatToshow.
       *  The current node is not consulted or set.
       */
      Node getLastChild(Node node) {
          
          if (node == null) return null;
          
          if ( !fEntityReferenceExpansion
               && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
              return null;
              
          Node newNode = node.getLastChild();
          if (newNode == null)  return null; 
          
          int accept = acceptNode(newNode);
          
          if (accept == NodeFilter.FILTER_ACCEPT)
              return newNode;
          else 
          if (accept == NodeFilter.FILTER_SKIP
              && newNode.hasChildNodes()) 
          {
              return getLastChild(newNode);
          }
          else 
          //if (accept == NodeFilter.REJECT_NODE) 
          {
              return getPreviousSibling(newNode);
          }
          
          
      }
      
      /** Internal function. 
       *  The node whatToShow and the filter are combined into one result. */
      short acceptNode(Node node) {
          /***
           7.1.2.4. Filters and whatToShow flags 
  
           Iterator and TreeWalker apply whatToShow flags before applying Filters. If a node is rejected by the
           active whatToShow flags, a Filter will not be called to evaluate that node. When a node is rejected by
           the active whatToShow flags, children of that node will still be considered, and Filters may be called to
           evaluate them.
           ***/
                  
          if (fNodeFilter == null) {
              if ( ( fWhatToShow & (1 << node.getNodeType()-1)) != 0) {
                  return NodeFilter.FILTER_ACCEPT;
              } else {
                  return NodeFilter.FILTER_SKIP;
              }
          } else {
              if ((fWhatToShow & (1 << node.getNodeType()-1)) != 0 ) {
                  return fNodeFilter.acceptNode(node);
              } else {
                  // What to show has failed. See above excerpt from spec.
                  // Equivalent to FILTER_SKIP.
                  return NodeFilter.FILTER_SKIP;
              }
          }
      } 
  }