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

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-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) 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.  * $Id: NamedNodeMapImpl.cpp,v 1.23 2001/12/07 01:11:50 tng Exp $
  58.  */
  59. #include "NamedNodeMapImpl.hpp"
  60. #include "NodeVector.hpp"
  61. #include "AttrImpl.hpp"
  62. #include "DOM_DOMException.hpp"
  63. #include "DocumentImpl.hpp"
  64. int        NamedNodeMapImpl::gLiveNamedNodeMaps  = 0;
  65. int        NamedNodeMapImpl::gTotalNamedNodeMaps = 0;
  66. NamedNodeMapImpl::NamedNodeMapImpl(NodeImpl *ownerNod)
  67. {
  68.     this->ownerNode=ownerNod;
  69.     this->nodes = null;
  70.     this->readOnly = false;
  71.     this->refCount = 1;
  72.     gLiveNamedNodeMaps++;
  73.     gTotalNamedNodeMaps++;
  74. };
  75. NamedNodeMapImpl::~NamedNodeMapImpl()
  76. {
  77.     if (nodes)
  78.     {
  79.         // It is the responsibility of whoever was using the named node
  80.         // map to do any cleanup on the nodes contained in the map
  81.         //  before deleting it.
  82.         delete nodes;
  83.         nodes = 0;
  84.     }
  85.     gLiveNamedNodeMaps--;
  86. };
  87. void NamedNodeMapImpl::addRef(NamedNodeMapImpl *This)
  88. {
  89.     if (This)
  90.         ++This->refCount;
  91. };
  92. NamedNodeMapImpl *NamedNodeMapImpl::cloneMap(NodeImpl *ownerNod)
  93. {
  94.     NamedNodeMapImpl *newmap = new NamedNodeMapImpl(ownerNod);
  95.     if (nodes != null)
  96.     {
  97.         newmap->nodes = new NodeVector(nodes->size());
  98.         for (unsigned int i = 0; i < nodes->size(); ++i)
  99.         {
  100.             NodeImpl *n = nodes->elementAt(i)->cloneNode(true);
  101. n->isSpecified(nodes->elementAt(i)->isSpecified());
  102.             n->ownerNode = ownerNod;
  103.             n->isOwned(true);
  104.             newmap->nodes->addElement(n);
  105.         }
  106.     }
  107.     return newmap;
  108. };
  109. //
  110. //  removeAll - This function removes all elements from a named node map.
  111. //              It is called from the destructors for Elements and DocumentTypes,
  112. //              to remove the contents when the owning Element or DocType goes
  113. //              away.  The empty NamedNodeMap may persist if the user code
  114. //              has a reference to it.
  115. //
  116. //              AH Revist - the empty map should be made read-only, since
  117. //              adding it was logically part of the [Element, DocumentType]
  118. //              that has been deleted, and adding anything new to it would
  119. //              be meaningless, and almost certainly an error.
  120. //
  121. void NamedNodeMapImpl::removeAll()
  122. {
  123.     if (nodes)
  124.     {
  125.         for (int i=nodes->size()-1; i>=0; i--)
  126.         {
  127.             NodeImpl *n = nodes->elementAt(i);
  128.             n->ownerNode = ownerNode->getOwnerDocument();
  129.             n->isOwned(false);
  130.             if (n->nodeRefCount == 0)
  131.                 NodeImpl::deleteIf(n);
  132.         }
  133.         delete nodes;
  134.         nodes = null;
  135.     }
  136. }
  137. int NamedNodeMapImpl::findNamePoint(const DOMString &name)
  138. {
  139.     // Binary search
  140.     int i=0;
  141.     if(nodes!=null)
  142.     {
  143.         int first=0,last=nodes->size()-1;
  144.         while(first<=last)
  145.         {
  146.             i=(first+last)/2;
  147.             int test = name.compareString(nodes->elementAt(i)->getNodeName());
  148.             if(test==0)
  149.                 return i; // Name found
  150.             else if(test<0)
  151.                 last=i-1;
  152.             else
  153.                 first=i+1;
  154.         }
  155.         if(first>i) i=first;
  156.     }
  157.     /********************
  158.     // Linear search
  159.     int i = 0;
  160.     if (nodes != null)
  161.     for (i = 0; i < nodes.size(); ++i)
  162.     {
  163.     int test = name.compareTo(((NodeImpl *) (nodes.elementAt(i))).getNodeName());
  164.     if (test == 0)
  165.     return i;
  166.     else
  167.     if (test < 0)
  168.     {
  169.     break; // Found insertpoint
  170.     }
  171.     }
  172.     *******************/
  173.     return -1 - i; // not-found has to be encoded.
  174. };
  175. unsigned int NamedNodeMapImpl::getLength()
  176. {
  177.     return (nodes != null) ? nodes->size() : 0;
  178. };
  179. NodeImpl * NamedNodeMapImpl::getNamedItem(const DOMString &name)
  180. {
  181.     int i=findNamePoint(name);
  182.     return (i<0) ? null : (NodeImpl *)(nodes->elementAt(i));
  183. };
  184. NodeImpl * NamedNodeMapImpl::item(unsigned int index)
  185. {
  186.     return (nodes != null && index < nodes->size()) ?
  187.         (NodeImpl *) (nodes->elementAt(index)) : null;
  188. };
  189. //
  190. // removeNamedItem() - Remove the named item, and return it.
  191. //                      The caller must arrange for deletion of the
  192. //                      returned item if its refcount has gone to zero -
  193. //                      we can't do it here because the caller would
  194. //                      never see the returned node.
  195. //
  196. NodeImpl * NamedNodeMapImpl::removeNamedItem(const DOMString &name)
  197. {
  198.     if (readOnly)
  199.         throw DOM_DOMException(
  200.             DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null);
  201.     int i=findNamePoint(name);
  202.     NodeImpl *n = null;
  203.     if(i<0)
  204.         throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
  205.     n = (NodeImpl *) (nodes->elementAt(i));
  206.     nodes->removeElementAt(i);
  207.     n->ownerNode = ownerNode->getOwnerDocument();
  208.     n->isOwned(false);
  209.     return n;
  210. };
  211. void NamedNodeMapImpl::removeRef(NamedNodeMapImpl *This)
  212. {
  213.     if (This && --This->refCount == 0)
  214.         delete This;
  215. };
  216. //
  217. // setNamedItem()  Put the item into the NamedNodeList by name.
  218. //                  If an item with the same name already was
  219. //                  in the list, replace it.  Return the old
  220. //                  item, if there was one.
  221. //                  Caller is responsible for arranging for
  222. //                  deletion of the old item if its ref count is
  223. //                  zero.
  224. //
  225. NodeImpl * NamedNodeMapImpl::setNamedItem(NodeImpl * arg)
  226. {
  227.     if(arg->getOwnerDocument() != ownerNode->getOwnerDocument())
  228.         throw DOM_DOMException(DOM_DOMException::WRONG_DOCUMENT_ERR,null);
  229.     if (readOnly)
  230.         throw DOM_DOMException(DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null);
  231.     if (arg->isOwned())
  232.         throw DOM_DOMException(DOM_DOMException::INUSE_ATTRIBUTE_ERR,null);
  233.     arg->ownerNode = ownerNode;
  234.     arg->isOwned(true);
  235.     int i=findNamePoint(arg->getNodeName());
  236.     NodeImpl * previous=null;
  237.     if(i>=0)
  238.     {
  239.         previous = nodes->elementAt(i);
  240.         nodes->setElementAt(arg,i);
  241.     }
  242.     else
  243.     {
  244.         i=-1-i; // Insert point (may be end of list)
  245.         if(null==nodes)
  246.             nodes=new NodeVector();
  247.         nodes->insertElementAt(arg,i);
  248.     }
  249.     if (previous != null) {
  250.         previous->ownerNode = ownerNode->getOwnerDocument();
  251.         previous->isOwned(false);
  252.     }
  253.     return previous;
  254. };
  255. void NamedNodeMapImpl::setReadOnly(bool readOnl, bool deep)
  256. {
  257.     this->readOnly=readOnl;
  258.     if(deep && nodes!=null)
  259.     {
  260.         //Enumeration e=nodes->elements();
  261.         //while(e->hasMoreElements())
  262.         //      ((NodeImpl)e->nextElement())->setReadOnly(readOnl,deep);
  263.         int sz = nodes->size();
  264.         for (int i=0; i<sz; ++i) {
  265.             nodes->elementAt(i)->setReadOnly(readOnl, deep);
  266.         }
  267.     }
  268. };
  269. //Introduced in DOM Level 2
  270. int NamedNodeMapImpl::findNamePoint(const DOMString &namespaceURI,
  271. const DOMString &localName)
  272. {
  273.     if (nodes == null)
  274. return -1;
  275.     // This is a linear search through the same nodes Vector.
  276.     // The Vector is sorted on the DOM Level 1 nodename.
  277.     // The DOM Level 2 NS keys are namespaceURI and Localname,
  278.     // so we must linear search thru it.
  279.     // In addition, to get this to work with nodes without any namespace
  280.     // (namespaceURI and localNames are both null) we then use the nodeName
  281.     // as a secondary key.
  282.     int i, len = nodes -> size();
  283.     for (i = 0; i < len; ++i) {
  284. NodeImpl *node = nodes -> elementAt(i);
  285. if (! node -> getNamespaceURI().equals(namespaceURI)) //URI not match
  286.     continue;
  287.         DOMString nNamespaceURI = node->getNamespaceURI();
  288.         DOMString nLocalName = node->getLocalName();
  289.         if (namespaceURI == null) {
  290.             if (nNamespaceURI == null
  291.                 &&
  292.                 (localName.equals(nLocalName)
  293.                  ||
  294.                  (nLocalName == null && localName.equals(node->getNodeName()))))
  295.                 return i;
  296.         } else {
  297.             if (namespaceURI.equals(nNamespaceURI)
  298.                 &&
  299.                 localName.equals(nLocalName))
  300.                 return i;
  301.         }
  302.     }
  303.     return -1; //not found
  304. }
  305. NodeImpl *NamedNodeMapImpl::getNamedItemNS(const DOMString &namespaceURI,
  306. const DOMString &localName)
  307. {
  308.     int i = findNamePoint(namespaceURI, localName);
  309.     return i < 0 ? null : nodes -> elementAt(i);
  310. }
  311. //
  312. // setNamedItemNS()  Put the item into the NamedNodeList by name.
  313. //                  If an item with the same name already was
  314. //                  in the list, replace it.  Return the old
  315. //                  item, if there was one.
  316. //                  Caller is responsible for arranging for
  317. //                  deletion of the old item if its ref count is
  318. //                  zero.
  319. //
  320. NodeImpl * NamedNodeMapImpl::setNamedItemNS(NodeImpl *arg)
  321. {
  322.     if (arg->getOwnerDocument() != ownerNode->getOwnerDocument())
  323.         throw DOM_DOMException(DOM_DOMException::WRONG_DOCUMENT_ERR,null);
  324.     if (readOnly)
  325.         throw DOM_DOMException(DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null);
  326.     if (arg->isOwned())
  327.         throw DOM_DOMException(DOM_DOMException::INUSE_ATTRIBUTE_ERR,null);
  328.     arg->ownerNode = ownerNode;
  329.     arg->isOwned(true);
  330.     int i=findNamePoint(arg->getNamespaceURI(), arg->getLocalName());
  331.     NodeImpl *previous=null;
  332.     if(i>=0) {
  333.         previous = nodes->elementAt(i);
  334.         nodes->setElementAt(arg,i);
  335.     } else {
  336.         i=findNamePoint(arg->getNodeName()); // Insert point (may be end of list)
  337.         if (i<0)
  338.           i = -1 - i;
  339.         if(null==nodes)
  340.             nodes=new NodeVector();
  341.         nodes->insertElementAt(arg,i);
  342.     }
  343.     if (previous != null) {
  344.         previous->ownerNode = ownerNode->getOwnerDocument();
  345.         previous->isOwned(false);
  346.     }
  347.     return previous;
  348. };
  349. // removeNamedItemNS() - Remove the named item, and return it.
  350. //                      The caller must arrange for deletion of the
  351. //                      returned item if its refcount has gone to zero -
  352. //                      we can't do it here because the caller would
  353. //                      never see the returned node.
  354. NodeImpl *NamedNodeMapImpl::removeNamedItemNS(const DOMString &namespaceURI,
  355. const DOMString &localName)
  356. {
  357.     if (readOnly)
  358.         throw DOM_DOMException(
  359.         DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null);
  360.     int i = findNamePoint(namespaceURI, localName);
  361.     if (i < 0)
  362.         throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
  363.     NodeImpl * n = nodes -> elementAt(i);
  364.     nodes -> removeElementAt(i); //remove n from nodes
  365.     n->ownerNode = ownerNode->getOwnerDocument();
  366.     n->isOwned(false);
  367.     return n;
  368. }
  369. /**
  370.  * NON-DOM
  371.  * set the ownerDocument of this node, its children, and its attributes
  372.  */
  373. void NamedNodeMapImpl::setOwnerDocument(DocumentImpl *doc) {
  374.     if (nodes != null) {
  375.         for (unsigned int i = 0; i < nodes->size(); i++) {
  376.             item(i)->setOwnerDocument(doc);
  377.         }
  378.     }
  379. }
  380. void NamedNodeMapImpl::cloneContent(NamedNodeMapImpl *srcmap) {
  381.    if ((srcmap != null) && (srcmap->nodes != null) && (srcmap->nodes->size() > 0))
  382. {
  383. if (nodes != null)
  384. delete nodes;
  385. nodes = new NodeVector(srcmap->nodes->size());
  386. for (unsigned int i = 0; i < srcmap->nodes->size(); i++)
  387. {
  388. NodeImpl *n = srcmap->nodes->elementAt(i);
  389.   NodeImpl *clone = n->cloneNode(true);
  390. clone->isSpecified(n->isSpecified());
  391. clone->ownerNode = ownerNode;
  392. clone->isOwned(true);
  393. nodes->addElement(clone);
  394. // n = null;
  395. // clone = null;
  396. }
  397. }
  398. }