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

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2000 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) 1999, 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: TreeWalkerImpl.cpp,v $
  58.  * Revision 1.9  2001/10/18 18:01:29  tng
  59.  * [Bug 1699] Redirect "delete this" to a temp ptr to bypass AIX xlC v5 optimization memory leak problem.
  60.  *
  61.  * Revision 1.8  2000/08/08 01:00:36  aruna1
  62.  * detach functionality removed from TreeWalker
  63.  *
  64.  * Revision 1.7  2000/03/28 23:22:17  aruna1
  65.  * Modified return statements in functions  to avoid warnings on HP.
  66.  *
  67.  * Revision 1.6  2000/03/02 19:54:05  roddey
  68.  * This checkin includes many changes done while waiting for the
  69.  * 1.1.0 code to be finished. I can't list them all here, but a list is
  70.  * available elsewhere.
  71.  *
  72.  * Revision 1.5  2000/02/06 07:47:34  rahulj
  73.  * Year 2K copyright swat.
  74.  *
  75.  * Revision 1.4  2000/02/04 01:49:25  aruna1
  76.  * TreeWalker and NodeIterator changes
  77.  *
  78.  * Revision 1.3  1999/11/30 21:16:26  roddey
  79.  * Changes to add the transcode() method to DOMString, which returns a transcoded
  80.  * version (to local code page) of the DOM string contents. And I changed all of the
  81.  * exception 'throw by pointer' to 'throw by value' style.
  82.  *
  83.  * Revision 1.2  1999/11/23 01:48:17  rahulj
  84.  * Changed 0L to 0. CC under HPUX is happy now.
  85.  *
  86.  * Revision 1.1.1.1  1999/11/09 01:09:20  twl
  87.  * Initial checkin
  88.  *
  89.  * Revision 1.2  1999/11/08 20:44:33  rahul
  90.  * Swat for adding in Product name and CVS comment log variable.
  91.  *
  92.  */
  93. #include "TreeWalkerImpl.hpp"
  94. #include "DOM_Document.hpp"
  95. #include "DOM_DOMException.hpp"
  96. #include "DocumentImpl.hpp"
  97. /** constructor */
  98. TreeWalkerImpl::TreeWalkerImpl (
  99.                                 DOM_Node root,
  100.                                 unsigned long whatToShow,
  101.                                 DOM_NodeFilter* nodeFilter,
  102.                                 bool expandEntityRef)
  103. :   fCurrentNode(root),
  104.     fRoot(root),
  105.     fWhatToShow(whatToShow),
  106.     fNodeFilter(nodeFilter),
  107.     fExpandEntityReferences(expandEntityRef)
  108. {
  109. }
  110. TreeWalkerImpl::TreeWalkerImpl (const TreeWalkerImpl& twi)
  111. : fCurrentNode(twi.fCurrentNode),
  112.     fRoot(twi.fRoot),
  113.     fWhatToShow(twi.fWhatToShow),
  114.     fNodeFilter(twi.fNodeFilter),
  115.     fExpandEntityReferences(twi.fExpandEntityReferences)
  116. {
  117. }
  118. TreeWalkerImpl& TreeWalkerImpl::operator= (const TreeWalkerImpl& twi) {
  119.     if (this != &twi)
  120.     {
  121.         fCurrentNode            = twi.fCurrentNode;
  122.         fRoot                   = twi.fRoot;
  123.         fWhatToShow             = twi.fWhatToShow;
  124.         fNodeFilter             = twi.fNodeFilter;
  125. fExpandEntityReferences = twi.fExpandEntityReferences;
  126.     }
  127.     return *this;
  128. }
  129. void TreeWalkerImpl::unreferenced()
  130. {
  131.     DOM_Document doc = fRoot.getOwnerDocument();
  132.     DocumentImpl* impl;
  133.     if (! doc.isNull()) {
  134.         impl = (DocumentImpl *) doc.fImpl;
  135.     }
  136.     else
  137.         impl = (DocumentImpl *) fRoot.fImpl;
  138.     if (impl->treeWalkers != 0L) {
  139.         int i;
  140.         int sz = impl->treeWalkers->size();
  141.         for (i = 0; i < sz; i++)
  142.             if (impl->treeWalkers->elementAt(i) == this) {
  143.                 impl->treeWalkers->removeElementAt(i);
  144.                 break;
  145.             }
  146.     }
  147. //    delete this;
  148.     TreeWalkerImpl* ptr = this;
  149.     delete ptr;
  150. }
  151. /** Return the whatToShow value */
  152. unsigned long TreeWalkerImpl::getWhatToShow () {
  153.     return fWhatToShow;
  154. }
  155. /** Return the NodeFilter */
  156. DOM_NodeFilter* TreeWalkerImpl::getFilter () {
  157.     return fNodeFilter;
  158. }
  159. /** Get the expandEntity reference flag. */
  160. bool TreeWalkerImpl::getExpandEntityReferences() {
  161.     return fExpandEntityReferences;
  162. }
  163. /** Return the current Node. */
  164. DOM_Node TreeWalkerImpl::getCurrentNode () {
  165.     return fCurrentNode;
  166. }
  167. /** Return the current Node. */
  168. void TreeWalkerImpl::setCurrentNode (DOM_Node node) {
  169.     fCurrentNode = node;
  170. }
  171. /** Return the parent Node from the current node,
  172.  *  after applying filter, whatToshow.
  173.  *  If result is not null, set the current Node.
  174.  */
  175. DOM_Node TreeWalkerImpl::parentNode () {
  176. DOM_Node result;
  177.     if (fCurrentNode.isNull()) return result;
  178.     DOM_Node node = getParentNode(fCurrentNode);
  179.     if (node != 0) {
  180.         fCurrentNode = node;
  181.     }
  182.     return node;
  183. }
  184. /** Return the first child Node from the current node,
  185.  *  after applying filter, whatToshow.
  186.  *  If result is not null, set the current Node.
  187.  */
  188. DOM_Node TreeWalkerImpl::firstChild () {
  189. DOM_Node result;
  190.     if (fCurrentNode.isNull()) return result;
  191.     DOM_Node node = getFirstChild(fCurrentNode);
  192.     if (! node.isNull()) {
  193.         fCurrentNode = node;
  194.     }
  195.     return node;
  196. }
  197. /** Return the last child Node from the current node,
  198.  *  after applying filter, whatToshow.
  199.  *  If result is not null, set the current Node.
  200.  */
  201. DOM_Node TreeWalkerImpl::lastChild () {
  202.     DOM_Node result;
  203.     if (fCurrentNode.isNull()) return result;
  204.     DOM_Node node = getLastChild(fCurrentNode);
  205.     if (! node.isNull()) {
  206.         fCurrentNode = node;
  207.     }
  208.     return node;
  209. }
  210. /** Return the previous sibling Node from the current node,
  211.  *  after applying filter, whatToshow.
  212.  *  If result is not null, set the current Node.
  213.  */
  214. DOM_Node TreeWalkerImpl::previousSibling () {
  215. DOM_Node result;
  216.     if (fCurrentNode.isNull()) return result;
  217.     DOM_Node node = getPreviousSibling(fCurrentNode);
  218.     if (! node.isNull()) {
  219.         fCurrentNode = node;
  220.     }
  221.     return node;
  222. }
  223. /** Return the next sibling Node from the current node,
  224.  *  after applying filter, whatToshow.
  225.  *  If result is not null, set the current Node.
  226.  */
  227. DOM_Node TreeWalkerImpl::nextSibling () {
  228. DOM_Node result;
  229.     if (fCurrentNode.isNull()) return result;
  230.     DOM_Node node = getNextSibling(fCurrentNode);
  231.     if (! node.isNull()) {
  232.         fCurrentNode = node;
  233.     }
  234.     return node;
  235. }
  236. /** Return the previous Node from the current node,
  237.  *  after applying filter, whatToshow.
  238.  *  If result is not null, set the current Node.
  239.  */
  240. DOM_Node TreeWalkerImpl::previousNode () {
  241.     DOM_Node result;
  242.     if (fCurrentNode.isNull()) return result;
  243.     // get sibling
  244.     result = getPreviousSibling(fCurrentNode);
  245.     if (result.isNull()) {
  246.         result = getParentNode(fCurrentNode);
  247.         if (! result.isNull()) {
  248.             fCurrentNode = result;
  249.             return fCurrentNode;
  250.         }
  251.         return result;
  252.     }
  253.     // get the lastChild of result.
  254.     DOM_Node lastChild  = getLastChild(result);
  255.     // if there is a lastChild which passes filters return it.
  256.     if (! lastChild.isNull()) {
  257.         fCurrentNode = lastChild;
  258.         return fCurrentNode;
  259.     }
  260.     // otherwise return the previous sibling.
  261.     if (! result.isNull()) {
  262.         fCurrentNode = result;
  263.         return fCurrentNode;
  264.     }
  265.     // otherwise return null.
  266.     return result;
  267. }
  268. /** Return the next Node from the current node,
  269.  *  after applying filter, whatToshow.
  270.  *  If result is not null, set the current Node.
  271.  */
  272. DOM_Node TreeWalkerImpl::nextNode () {
  273. DOM_Node result;
  274.     if (fCurrentNode.isNull()) return result;
  275.     result = getFirstChild(fCurrentNode);
  276.     if (! result.isNull()) {
  277.         fCurrentNode = result;
  278.         return result;
  279.     }
  280.     result = getNextSibling(fCurrentNode);
  281.     if (! result.isNull()) {
  282.         fCurrentNode = result;
  283.         return result;
  284.     }
  285.     // return parent's 1st sibling.
  286.     DOM_Node parent = getParentNode(fCurrentNode);
  287.     while (! parent.isNull()) {
  288.         result = getNextSibling(parent);
  289.         if (! result.isNull()) {
  290.             fCurrentNode = result;
  291.             return result;
  292.         } else {
  293.             parent = getParentNode(parent);
  294.         }
  295.     }
  296.     // end , return null
  297.     return result;
  298. }
  299. /** Internal function.
  300.  *  Return the parent Node, from the input node
  301.  *  after applying filter, whatToshow.
  302.  *  The current node is not consulted or set.
  303.  */
  304. DOM_Node TreeWalkerImpl::getParentNode (DOM_Node node) {
  305. DOM_Node result;
  306.     if (node.isNull() || node == fRoot) return result;
  307.     DOM_Node newNode = node.getParentNode();
  308.     if (newNode.isNull())  return result;
  309.     short accept = acceptNode(newNode);
  310.     if (accept == DOM_NodeFilter::FILTER_ACCEPT)
  311.         return newNode;
  312.     return getParentNode(newNode);
  313. }
  314. /** Internal function.
  315.  *  Return the nextSibling Node, from the input node
  316.  *  after applying filter, whatToshow.
  317.  *  The current node is not consulted or set.
  318.  */
  319. DOM_Node TreeWalkerImpl::getNextSibling (DOM_Node node) {
  320. DOM_Node result;
  321.     if (node.isNull() || node == fRoot) return result;
  322.     DOM_Node newNode = node.getNextSibling();
  323.     if (newNode.isNull()) {
  324.         newNode = node.getParentNode();
  325.         if (newNode.isNull() || node == fRoot)  return result;
  326.         short parentAccept = acceptNode(newNode);
  327.         if (parentAccept == DOM_NodeFilter::FILTER_SKIP) {
  328.             return getNextSibling(newNode);
  329.         }
  330.         return result;
  331.     }
  332.     short accept = acceptNode(newNode);
  333.     if (accept == DOM_NodeFilter::FILTER_ACCEPT)
  334.         return newNode;
  335.     else
  336.     if (accept == DOM_NodeFilter::FILTER_SKIP) {
  337.         DOM_Node fChild =  getFirstChild(newNode);
  338.         if (fChild.isNull()) {
  339.             return getNextSibling(newNode);
  340.         }
  341.         return fChild;
  342.     }
  343.     return getNextSibling(newNode);
  344. }
  345. /** Internal function.
  346.  *  Return the previous sibling Node, from the input node
  347.  *  after applying filter, whatToshow.
  348.  *  The current node is not consulted or set.
  349.  */
  350. DOM_Node TreeWalkerImpl::getPreviousSibling (DOM_Node node) {
  351. DOM_Node result;
  352.     if (node.isNull() || node == fRoot) return result;
  353.     DOM_Node newNode = node.getPreviousSibling();
  354.     if (newNode.isNull()) {
  355.         newNode = node.getParentNode();
  356.         if (newNode.isNull() || node == fRoot)  return result;
  357.         short parentAccept = acceptNode(newNode);
  358.         if (parentAccept == DOM_NodeFilter::FILTER_SKIP) {
  359.             return getPreviousSibling(newNode);
  360.         }
  361.         return result;
  362.     }
  363.     short accept = acceptNode(newNode);
  364.     if (accept == DOM_NodeFilter::FILTER_ACCEPT)
  365.         return newNode;
  366.     else
  367.     if (accept == DOM_NodeFilter::FILTER_SKIP) {
  368.         DOM_Node fChild =  getLastChild(newNode);
  369.         if (fChild.isNull()) {
  370.             return getPreviousSibling(newNode);
  371.         }
  372.         return fChild;
  373.     }
  374.     return getPreviousSibling(newNode);
  375. }
  376. /** Internal function.
  377.  *  Return the first child Node, from the input node
  378.  *  after applying filter, whatToshow.
  379.  *  The current node is not consulted or set.
  380.  */
  381. DOM_Node TreeWalkerImpl::getFirstChild (DOM_Node node) {
  382. DOM_Node result;
  383.     if (node.isNull()) return result;
  384.     DOM_Node newNode = node.getFirstChild();
  385.     if (newNode.isNull())  return result;
  386.     short accept = acceptNode(newNode);
  387.     if (accept == DOM_NodeFilter::FILTER_ACCEPT)
  388.         return newNode;
  389.     else
  390.     if (accept == DOM_NodeFilter::FILTER_SKIP
  391.         && newNode.hasChildNodes())
  392.     {
  393.         return getFirstChild(newNode);
  394.     }
  395.     return getNextSibling(newNode);
  396. }
  397. /** Internal function.
  398.  *  Return the last child Node, from the input node
  399.  *  after applying filter, whatToshow.
  400.  *  The current node is not consulted or set.
  401.  */
  402. DOM_Node TreeWalkerImpl::getLastChild (DOM_Node node) {
  403. DOM_Node result;
  404.     if (node.isNull()) return result;
  405.     DOM_Node newNode = node.getLastChild();
  406.     if (newNode.isNull())  return result;
  407.     short accept = acceptNode(newNode);
  408.     if (accept == DOM_NodeFilter::FILTER_ACCEPT)
  409.         return newNode;
  410.     else
  411.     if (accept == DOM_NodeFilter::FILTER_SKIP
  412.         && newNode.hasChildNodes())
  413.     {
  414.         return getLastChild(newNode);
  415.     }
  416.     return getPreviousSibling(newNode);
  417. }
  418. /** The node is accepted if it passes the whatToShow and the filter. */
  419. short TreeWalkerImpl::acceptNode (DOM_Node node) {
  420.     if (fNodeFilter == 0) {
  421.         if ( ( fWhatToShow & (1 << (node.getNodeType() - 1))) != 0)
  422.         {
  423.             return DOM_NodeFilter::FILTER_ACCEPT;
  424.         }
  425.         else
  426.         {
  427.             return DOM_NodeFilter::FILTER_SKIP;
  428.         }
  429.     } else {
  430.         // REVISIT: This logic is unclear from the spec!
  431.         if ((fWhatToShow & (1 << (node.getNodeType() - 1))) != 0 ) {
  432.             return fNodeFilter->acceptNode(node);
  433.         } else {
  434.             // what to show has failed!
  435.             if (fNodeFilter->acceptNode(node) == DOM_NodeFilter::FILTER_REJECT) {
  436.                 return DOM_NodeFilter::FILTER_REJECT;
  437.             } else {
  438.                 return DOM_NodeFilter::FILTER_SKIP;
  439.             }
  440.         }
  441.     }
  442. }