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