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

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: DeepNodeListImpl.cpp,v $
  58.  * Revision 1.8  2001/10/25 21:47:14  peiyongz
  59.  * Replace XMLDeleterFor with XMLRegisterCleanup
  60.  *
  61.  * Revision 1.7  2001/10/18 18:01:29  tng
  62.  * [Bug 1699] Redirect "delete this" to a temp ptr to bypass AIX xlC v5 optimization memory leak problem.
  63.  *
  64.  * Revision 1.6  2000/04/27 02:52:42  lehors
  65.  * global reorganization similar to what I've done in Java,
  66.  * nodes now are much smaller.
  67.  * The main changes are:
  68.  * renamed NodeContainer to ParentNode,
  69.  * introduced ChildNode and ChildAndParentNode,
  70.  * all the boolean attributes have been changed to bit flags,
  71.  * ownerDocument is no longer an attribute of NodeImpl, only Parent nodes have
  72.  * it, leave nodes rely on their parent to get it, or get it from ownerNode when
  73.  * they do not have a parent,
  74.  * parent Nodes no longer have a direct pointer to the last child
  75.  * instead the last child is stored as the previous sibling of
  76.  * the first child.
  77.  * I also added support for importing a DocumentType as it's done in Java,
  78.  * and got the importNode mechanism back in sync with Java as well.
  79.  *
  80.  * Here are the most significant changes in size:
  81.  * ElementImpl 52 -> 48
  82.  * TextImpl    44 -> 32
  83.  * AttrImpl    52 -> 36
  84.  *
  85.  * Revision 1.5  2000/03/02 19:53:59  roddey
  86.  * This checkin includes many changes done while waiting for the
  87.  * 1.1.0 code to be finished. I can't list them all here, but a list is
  88.  * available elsewhere.
  89.  *
  90.  * Revision 1.4  2000/02/06 07:47:31  rahulj
  91.  * Year 2K copyright swat.
  92.  *
  93.  * Revision 1.3  2000/02/04 01:49:30  aruna1
  94.  * TreeWalker and NodeIterator changes
  95.  *
  96.  * Revision 1.2  2000/01/22 01:38:29  andyh
  97.  * Remove compiler warnings in DOM impl classes
  98.  *
  99.  * Revision 1.1.1.1  1999/11/09 01:08:42  twl
  100.  * Initial checkin
  101.  *
  102.  * Revision 1.3  1999/11/08 20:44:23  rahul
  103.  * Swat for adding in Product name and CVS comment log variable.
  104.  *
  105.  */
  106. #include "DeepNodeListImpl.hpp"
  107. #include "NodeVector.hpp"
  108. #include "NodeImpl.hpp"
  109. #include "ElementImpl.hpp"
  110. #include "DStringPool.hpp"
  111. #include <limits.h>
  112. static DOMString *kAstr = 0;
  113. static XMLRegisterCleanup kAstrCleanup;
  114. DeepNodeListImpl::DeepNodeListImpl(NodeImpl *rootNod, const DOMString &tagNam)
  115. {
  116.     changes = 0;
  117.     this->rootNode = rootNod;
  118.     this->tagName = tagNam;
  119.     nodes=new NodeVector();
  120.     matchAll = tagName.equals(DStringPool::getStaticString("*"
  121.                                                          , &kAstr
  122.                                                          , reinitDeepNodeListImpl
  123.                                                          , kAstrCleanup));
  124.     this->namespaceURI = null; //DOM Level 2
  125.     this->matchAllURI = false; //DOM Level 2
  126.     this->matchURIandTagname = false; //DOM Level 2
  127. };
  128. //DOM Level 2
  129. DeepNodeListImpl::DeepNodeListImpl(NodeImpl *rootNod,
  130.     const DOMString &fNamespaceURI, const DOMString &localName)
  131. {
  132.     changes = 0;
  133.     this->rootNode = rootNod;
  134.     this->tagName = localName;
  135.     nodes=new NodeVector();
  136.     matchAll = tagName.equals(DStringPool::getStaticString("*"
  137.                                                          , &kAstr
  138.                                                          , reinitDeepNodeListImpl
  139.                                                          , kAstrCleanup));
  140.     this->namespaceURI = fNamespaceURI;
  141.     this->matchAllURI = fNamespaceURI.equals(DStringPool::getStaticString("*"
  142.                                                                         , &kAstr
  143.                                                                         , reinitDeepNodeListImpl
  144.                                                                         , kAstrCleanup));
  145.                                                                         
  146.     this->matchURIandTagname = true;
  147. };
  148. DeepNodeListImpl::~DeepNodeListImpl()
  149. {
  150.     delete nodes;
  151. };
  152. unsigned int DeepNodeListImpl::getLength()
  153. {
  154.     // Preload all matching elements. (Stops when we run out of subtree!)
  155.     item(INT_MAX);
  156.     return nodes->size();
  157. };
  158. // Start from the first child and count forward, 0-based. index>length-1
  159. // should return null.
  160. //
  161. // Attempts to do only work actually requested, cache work already
  162. // done, and to flush that cache when the tree has changed.
  163. //
  164. // LIMITATION: ????? Unable to tell relevant tree-changes from
  165. // irrelevant ones.  Doing so in a really useful manner would seem
  166. // to involve a tree-walk in its own right, or maintaining our data
  167. // in a parallel tree.
  168. NodeImpl *DeepNodeListImpl::item(unsigned int index)
  169. {
  170.     NodeImpl *thisNode;
  171.     if(rootNode->changes() != changes)
  172.     {
  173.         nodes->reset();     // Tree changed. Do it all from scratch!
  174.         changes = rootNode->changes();
  175.     }
  176.     if(index< nodes->size())      // In the cache
  177.         return nodes->elementAt((int) index);
  178.     else                        // Not yet seen
  179.     {
  180.         if(nodes->size()==0)     // Pick up where we left off
  181.             thisNode=rootNode; // (Which may be the beginning)
  182.         else
  183.             thisNode=nodes->lastElement();
  184.         while(thisNode!=null && index >= nodes->size() && thisNode!=null)
  185.         {
  186.             thisNode=nextMatchingElementAfter(thisNode);
  187.             if(thisNode!=null)
  188.                 nodes->addElement(thisNode);
  189.         }
  190.         return thisNode;           // Either what we want, or null (not avail.)
  191.     }
  192. };
  193. /* Iterative tree-walker. When you have a Parent link, there's often no
  194. need to resort to recursion. NOTE THAT only Element nodes are matched
  195. since we're specifically supporting getElementsByTagName().
  196. */
  197. NodeImpl *DeepNodeListImpl::nextMatchingElementAfter(NodeImpl *current)
  198. {
  199.     NodeImpl *next;
  200.     while (current != null)
  201.     {
  202.         // Look down to first child.
  203.         if (current->hasChildNodes())
  204.         {
  205.             current = current->getFirstChild();
  206.         }
  207.         // Look right to sibling (but not from root!)
  208.         else
  209.         {
  210.             if (current != rootNode && null != (next = current->getNextSibling()))
  211.             {
  212.                 current = next;
  213.             }
  214.             // Look up and right (but not past root!)
  215.             else
  216.             {
  217.                 next = null;
  218.                 for (; current != rootNode; // Stop when we return to starting point
  219.                 current = current->getParentNode())
  220.                 {
  221.                     next = current->getNextSibling();
  222.                     if (next != null)
  223.                         break;
  224.                 }
  225.                 current = next;
  226.             }
  227.         }
  228.         // Have we found an Element with the right tagName?
  229.         // ("*" matches anything.)
  230.         if (current != null && current != rootNode && current->isElementImpl()) {
  231.     if (!matchURIandTagname) { //DOM Level 1
  232. if (matchAll || ((ElementImpl *)current)->getTagName().equals(tagName))
  233.     return current;
  234.     } else { //DOM Level 2
  235. if (!matchAllURI && !(current -> getNamespaceURI().equals(namespaceURI)))
  236.     continue;
  237. if (matchAll || current -> getLocalName().equals(tagName))
  238.     return current;
  239.     }
  240. }
  241.         // Otherwise continue walking the tree
  242.     }
  243.     // Fell out of tree-walk; no more instances found
  244.     return null;
  245. };
  246. //
  247. //  unreferenced()      The RefCountedImpl base class calls back to this function
  248. //                      when the ref count goes to zero.
  249. //
  250. //
  251. void DeepNodeListImpl::unreferenced()
  252. {
  253. //    delete this;
  254.       DeepNodeListImpl* ptr = this;
  255.       delete ptr;
  256. };
  257. // -----------------------------------------------------------------------
  258. //  Notification that lazy data has been deleted
  259. // -----------------------------------------------------------------------
  260. void DeepNodeListImpl::reinitDeepNodeListImpl() {
  261. delete kAstr;
  262. kAstr = 0;
  263. }