IDNodeIteratorImpl.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:12k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 2001, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Log: IDNodeIteratorImpl.cpp,v $
  58.  * Revision 1.3  2001/06/04 20:11:52  tng
  59.  * IDOM: Complete IDNodeIterator, IDTreeWalker, IDNodeFilter.
  60.  *
  61.  * Revision 1.2  2001/05/11 13:25:45  tng
  62.  * Copyright update.
  63.  *
  64.  * Revision 1.1.1.1  2001/04/03 00:14:25  andyh
  65.  * IDOM
  66.  *
  67.  */
  68. // IDNodeIteratorImpl.cpp: implementation of the IDNodeIteratorImpl class.
  69. //
  70. //////////////////////////////////////////////////////////////////////
  71. #include "IDNodeIteratorImpl.hpp"
  72. #include "IDOM_Document.hpp"
  73. #include "IDOM_DOMException.hpp"
  74. #include "IDDocumentImpl.hpp"
  75. //////////////////////////////////////////////////////////////////////
  76. // Construction/Destruction
  77. //////////////////////////////////////////////////////////////////////
  78. IDNodeIteratorImpl::IDNodeIteratorImpl ()
  79. : fDetached(false),
  80.     fNodeFilter(0)
  81. {
  82. }
  83. IDNodeIteratorImpl::~IDNodeIteratorImpl ()
  84. {
  85. fDetached = false;
  86. }
  87. void IDNodeIteratorImpl::detach ()
  88. {
  89. fDetached = true;
  90. }
  91. IDNodeIteratorImpl::IDNodeIteratorImpl (
  92.                                     IDOM_Node* root,
  93.                                     unsigned long whatToShow,
  94.                                     IDOM_NodeFilter* nodeFilter,
  95.                                     bool expandEntityRef)
  96. :   fDetached(false),
  97.     fRoot(root),
  98.     fCurrentNode(0),
  99.     fWhatToShow(whatToShow),
  100.     fNodeFilter(nodeFilter),
  101.     fForward(true),
  102.     fExpandEntityReferences(expandEntityRef)
  103. {
  104. }
  105. IDNodeIteratorImpl::IDNodeIteratorImpl ( const IDNodeIteratorImpl& toCopy)
  106.     :   fDetached(toCopy.fDetached),
  107.     fRoot(toCopy.fRoot),
  108.     fCurrentNode(toCopy.fCurrentNode),
  109.     fWhatToShow(toCopy.fWhatToShow),
  110.     fNodeFilter(toCopy.fNodeFilter),
  111.     fForward(toCopy.fForward),
  112.     fExpandEntityReferences(toCopy.fExpandEntityReferences)
  113. {
  114. }
  115. IDNodeIteratorImpl& IDNodeIteratorImpl::operator= (const IDNodeIteratorImpl& other) {
  116.     fRoot                   = other.fRoot;
  117.     fCurrentNode            = other.fRoot;
  118.     fWhatToShow             = other.fWhatToShow;
  119.     fNodeFilter             = other.fNodeFilter;
  120.     fForward                = other.fForward;
  121.     fDetached               = other.fDetached;
  122.     fExpandEntityReferences = other.fExpandEntityReferences;
  123.     return *this;
  124. }
  125. // Implementation Note: Note that the iterator looks at whatToShow
  126. // and filter values at each call, and therefore one _could_ add
  127. // setters for these values and alter them while iterating!
  128. /** Return the whatToShow value */
  129. unsigned long IDNodeIteratorImpl::getWhatToShow () {
  130.     return fWhatToShow;
  131. }
  132. /** Return the filter */
  133. IDOM_NodeFilter* IDNodeIteratorImpl::getFilter () {
  134.     return fNodeFilter;
  135. }
  136. /** Get the expandEntity reference flag. */
  137. bool IDNodeIteratorImpl::getExpandEntityReferences()
  138. {
  139.     return fExpandEntityReferences;
  140. }
  141. /** Return the next IDOM_Node* in the Iterator. The node is the next node in
  142.  *  depth-first order which also passes the filter, and whatToShow.
  143.  *  A 0 return means either that
  144.  */
  145. IDOM_Node* IDNodeIteratorImpl::nextNode () {
  146. if (fDetached)
  147. throw IDOM_DOMException(IDOM_DOMException::INVALID_STATE_ERR, 0);
  148.     // if root is 0 there is no next node->
  149.     if (!fRoot)
  150. return 0;
  151.     IDOM_Node* aNextNode = fCurrentNode;
  152.     bool accepted = false; // the next node has not been accepted.
  153.     while (!accepted) {
  154.         // if last direction is not forward, repeat node->
  155.         if (!fForward && (aNextNode != 0)) {
  156.             //System.out.println("nextNode():!fForward:"+fCurrentNode.getNodeName());
  157.             aNextNode = fCurrentNode;
  158.         } else {
  159.         // else get the next node via depth-first
  160.             aNextNode = nextNode(aNextNode, true);
  161.         }
  162.         fForward = true; //REVIST: should direction be set forward before 0 check?
  163.         // nothing in the list. return 0.
  164.         if (!aNextNode) return 0;
  165.         // does node pass the filters and whatToShow?
  166.         accepted = acceptNode(aNextNode);
  167.         if (accepted) {
  168.             // if so, then the node is the current node->
  169.             fCurrentNode = aNextNode;
  170.             return fCurrentNode;
  171.         }
  172.     }
  173.     // no nodes, or no accepted nodes.
  174.     return 0;
  175. }
  176. /** Return the previous Node in the Iterator. The node is the next node in
  177.  *  _backwards_ depth-first order which also passes the filter, and whatToShow.
  178.  */
  179. IDOM_Node* IDNodeIteratorImpl::previousNode () {
  180. if (fDetached)
  181. throw IDOM_DOMException(IDOM_DOMException::INVALID_STATE_ERR, 0);
  182.     // if the root is 0, or the current node is 0, return 0.
  183.     if (!fRoot || !fCurrentNode) return 0;
  184.     IDOM_Node* aPreviousNode = fCurrentNode;
  185.     bool accepted = false;
  186.     while (!accepted) {
  187.         if (fForward && (aPreviousNode != 0)) {
  188.             //repeat last node->
  189.             aPreviousNode = fCurrentNode;
  190.         } else {
  191.             // get previous node in backwards depth first order.
  192.             aPreviousNode = previousNode(aPreviousNode);
  193.         }
  194.         // we are going backwards
  195.         fForward = false;
  196.         // if the new previous node is 0, we're at head or past the root,
  197.         // so return 0.
  198.         if (!aPreviousNode) return 0;
  199.         // check if node passes filters and whatToShow.
  200.         accepted = acceptNode(aPreviousNode);
  201.         if (accepted) {
  202.             // if accepted, update the current node, and return it.
  203.             fCurrentNode = aPreviousNode;
  204.             return fCurrentNode;
  205.         }
  206.     }
  207.     // there are no nodes?
  208.     return 0;
  209. }
  210. /** The node is accepted if it passes the whatToShow and the filter. */
  211. bool IDNodeIteratorImpl::acceptNode (IDOM_Node* node) {
  212. if (fDetached)
  213. throw IDOM_DOMException(IDOM_DOMException::INVALID_STATE_ERR, 0);
  214.     if (fNodeFilter == 0) {
  215.         return ((fWhatToShow & (1 << (node->getNodeType() - 1))) != 0);
  216.     } else {
  217.         return ((fWhatToShow & (1 << (node->getNodeType() - 1))) != 0)
  218.             && fNodeFilter->acceptNode(node) == IDOM_NodeFilter::FILTER_ACCEPT;
  219.     }
  220. }
  221. /** Return node, if matches or any parent if matches. */
  222. IDOM_Node* IDNodeIteratorImpl::matchNodeOrParent (IDOM_Node* node) {
  223.     for (IDOM_Node* n = node; n != fRoot; n = n->getParentNode()) {
  224.         if (node == n) return n;
  225.     }
  226.     return 0;
  227. }
  228. /** The method nextNode(IDOM_Node, bool) returns the next node
  229.  *  from the actual DOM tree.
  230.  *
  231.  *  The bool visitChildren determines whether to visit the children.
  232.  *  The result is the nextNode.
  233.  */
  234. IDOM_Node* IDNodeIteratorImpl::nextNode (IDOM_Node* node, bool visitChildren) {
  235. if (fDetached)
  236. throw IDOM_DOMException(IDOM_DOMException::INVALID_STATE_ERR, 0);
  237.     if (!node) return fRoot;
  238.     IDOM_Node* result = 0;
  239.     // only check children if we visit children.
  240.     if (visitChildren) {
  241.         //if hasChildren, return 1st child.
  242.         if (node->hasChildNodes()) {
  243.             result = node->getFirstChild();
  244.             return result;
  245.         }
  246.     }
  247.     // if hasSibling, return sibling
  248.     if (node != fRoot) {
  249.         result = node->getNextSibling();
  250.         if (result != 0) return result;
  251.         // return parent's 1st sibling.
  252.         IDOM_Node* parent = node->getParentNode();
  253.         while ((parent != 0) && parent != fRoot) {
  254.             result = parent->getNextSibling();
  255.             if (result != 0) {
  256.                 return result;
  257.             } else {
  258.                 parent = parent->getParentNode();
  259.             }
  260.         } // while (parent != 0 && parent != fRoot) {
  261.     }
  262.     // end of list, return 0
  263.     return 0;
  264. }
  265. /** The method previousNode(IDOM_Node) returns the previous node
  266.  *  from the actual DOM tree.
  267.  */
  268. IDOM_Node* IDNodeIteratorImpl::previousNode (IDOM_Node* node) {
  269. if (fDetached)
  270. throw IDOM_DOMException(IDOM_DOMException::INVALID_STATE_ERR, 0);
  271.     IDOM_Node* result = 0;
  272.     // if we're at the root, return 0.
  273.     if (node == fRoot)
  274. return 0;
  275.     // get sibling
  276.     result = node->getPreviousSibling();
  277.     if (!result) {
  278.         //if 1st sibling, return parent
  279.         result = node->getParentNode();
  280.         return result;
  281.     }
  282.     // if sibling has children, keep getting last child of child.
  283.     if (result->hasChildNodes()) {
  284.         while (result->hasChildNodes()) {
  285.             result = result->getLastChild();
  286.         }
  287.     }
  288.     return result;
  289. }
  290. /** Fix-up the iterator on a remove. Called by DOM or otherwise,
  291.  *  before an actual DOM remove.
  292.  */
  293. void IDNodeIteratorImpl::removeNode (IDOM_Node* node) {
  294. if (fDetached)
  295. throw IDOM_DOMException(IDOM_DOMException::INVALID_STATE_ERR, 0);
  296.     // Implementation note: Fix-up means setting the current node properly
  297.     // after a remove.
  298.     if (!node) return;
  299.     IDOM_Node* deleted = matchNodeOrParent(node);
  300.     if (!deleted) return;
  301.     if (fForward) {
  302.         fCurrentNode = previousNode(deleted);
  303.     } else
  304.     // if (!fForward)
  305.     {
  306.         IDOM_Node* next = nextNode(deleted, false);
  307.         if (next != 0) {
  308.             // normal case: there _are_ nodes following this in the iterator.
  309.             fCurrentNode = next;
  310.         } else {
  311.             // the last node in the iterator is to be removed,
  312.             // so we set the current node to be the previous one.
  313.             fCurrentNode = previousNode(deleted);
  314.             fForward = true;
  315.         }
  316.     }
  317. }