GME  13
DOMNamedNodeMapImpl.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: DOMNamedNodeMapImpl.cpp 678381 2008-07-21 10:15:01Z borisk $
00020  */
00021 
00022 
00023 #include <xercesc/dom/DOMAttr.hpp>
00024 #include <xercesc/dom/DOMException.hpp>
00025 #include <xercesc/framework/XMLBuffer.hpp>
00026 #include <xercesc/util/XMLUniDefs.hpp>
00027 
00028 #include "DOMNodeVector.hpp"
00029 #include "DOMNamedNodeMapImpl.hpp"
00030 #include "DOMCasts.hpp"
00031 #include "DOMDocumentImpl.hpp"
00032 #include "DOMNodeImpl.hpp"
00033 
00034 XERCES_CPP_NAMESPACE_BEGIN
00035 
00036 DOMNamedNodeMapImpl::DOMNamedNodeMapImpl(DOMNode *ownerNod)
00037 {
00038     fOwnerNode=ownerNod;
00039     memset(fBuckets,0,MAP_SIZE*sizeof(DOMNodeVector*));
00040 }
00041 
00042 DOMNamedNodeMapImpl::~DOMNamedNodeMapImpl()
00043 {
00044 }
00045 
00046 bool DOMNamedNodeMapImpl::readOnly()
00047 {
00048     return castToNodeImpl(fOwnerNode)->isReadOnly();
00049 }
00050 
00051 DOMNamedNodeMapImpl *DOMNamedNodeMapImpl::cloneMap(DOMNode *ownerNod)
00052 {
00053     DOMDocumentImpl *doc = (DOMDocumentImpl *)(castToNodeImpl(ownerNod)->getOwnerDocument());
00054     DOMNamedNodeMapImpl *newmap = new (doc) DOMNamedNodeMapImpl(ownerNod);
00055 
00056     for(XMLSize_t index=0;index<MAP_SIZE;index++)
00057         if (fBuckets[index] != 0) {
00058             XMLSize_t size=fBuckets[index]->size();
00059             newmap->fBuckets[index] = new (doc) DOMNodeVector(doc, size);
00060             for (XMLSize_t i = 0; i < size; ++i) {
00061                 DOMNode *s = fBuckets[index]->elementAt(i);
00062                 DOMNode *n = s->cloneNode(true);
00063                             castToNodeImpl(n)->isSpecified(castToNodeImpl(s)->isSpecified());
00064                 castToNodeImpl(n)->fOwnerNode = ownerNod;
00065                 castToNodeImpl(n)->isOwned(true);
00066                 newmap->fBuckets[index]->addElement(n);
00067             }
00068         }
00069 
00070     return newmap;
00071 }
00072 
00073 
00074 XMLSize_t DOMNamedNodeMapImpl::getLength() const
00075 {
00076     XMLSize_t count=0;
00077     for(XMLSize_t index=0;index<MAP_SIZE;index++)
00078         count+=(fBuckets[index]==0?0:fBuckets[index]->size());
00079     return count;
00080 }
00081 
00082 DOMNode * DOMNamedNodeMapImpl::item(XMLSize_t index) const
00083 {
00084     XMLSize_t count=0;
00085     for(XMLSize_t i=0;i<MAP_SIZE;i++) {
00086         if(fBuckets[i]==0)
00087             continue;
00088         XMLSize_t thisBucket=fBuckets[i]->size();
00089         if(index>=count && index<(count+thisBucket))
00090             return fBuckets[i]->elementAt(index-count);
00091         count+=thisBucket;
00092     }
00093     return NULL;
00094 }
00095 
00096 
00097 DOMNode * DOMNamedNodeMapImpl::getNamedItem(const XMLCh *name) const
00098 {
00099     XMLSize_t hash=XMLString::hash(name,MAP_SIZE);
00100     if(fBuckets[hash]==0)
00101         return 0;
00102 
00103     XMLSize_t i = 0;
00104     XMLSize_t size = fBuckets[hash]->size();
00105     for (i = 0; i < size; ++i) {
00106         DOMNode *n=fBuckets[hash]->elementAt(i);
00107         if(XMLString::equals(name,n->getNodeName()))
00108             return n;
00109     }
00110 
00111     return 0;
00112 }
00113 
00114 
00115 //
00116 // removeNamedItem() - Remove the named item, and return it.
00117 //                      The caller can release the
00118 //                      returned item if it's not used
00119 //                      we can't do it here because the caller would
00120 //                      never see the returned node.
00121 //
00122 DOMNode * DOMNamedNodeMapImpl::removeNamedItem(const XMLCh *name)
00123 {
00124     if (this->readOnly())
00125         throw DOMException(
00126             DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
00127 
00128     XMLSize_t hash=XMLString::hash(name,MAP_SIZE);
00129     if(fBuckets[hash]==0)
00130         throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
00131 
00132     DOMDocument *doc = fOwnerNode->getOwnerDocument();
00133 
00134     XMLSize_t i = 0;
00135     XMLSize_t size = fBuckets[hash]->size();
00136     for (i = 0; i < size; ++i) {
00137         DOMNode *n=fBuckets[hash]->elementAt(i);
00138         if(XMLString::equals(name,n->getNodeName())) {
00139             fBuckets[hash]->removeElementAt(i);
00140             castToNodeImpl(n)->fOwnerNode = doc;
00141             castToNodeImpl(n)->isOwned(false);
00142             return n;
00143         }
00144     }
00145 
00146     throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
00147     return 0;
00148 }
00149 
00150 
00151 
00152 //
00153 // setNamedItem()  Put the item into the NamedNodeList by name.
00154 //                  If an item with the same name already was
00155 //                  in the list, replace it.  Return the old
00156 //                  item, if there was one.
00157 //                  Caller is responsible for arranging for
00158 //                  deletion of the old item if its ref count is
00159 //                  zero.
00160 //
00161 DOMNode * DOMNamedNodeMapImpl::setNamedItem(DOMNode * arg)
00162 {
00163     DOMDocument *doc = fOwnerNode->getOwnerDocument();
00164     DOMNodeImpl *argImpl = castToNodeImpl(arg);
00165     if(argImpl->getOwnerDocument() != doc)
00166         throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
00167     if (this->readOnly())
00168         throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
00169     if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode))
00170         throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);
00171 
00172     argImpl->fOwnerNode = fOwnerNode;
00173     argImpl->isOwned(true);
00174 
00175     const XMLCh* name=arg->getNodeName();
00176     XMLSize_t hash=XMLString::hash(name,MAP_SIZE);
00177     if(fBuckets[hash]==0)
00178         fBuckets[hash] = new (doc) DOMNodeVector(doc, 3);
00179 
00180     XMLSize_t i = 0;
00181     XMLSize_t size = fBuckets[hash]->size();
00182     for (i = 0; i < size; ++i) {
00183         DOMNode *n=fBuckets[hash]->elementAt(i);
00184         if(XMLString::equals(name,n->getNodeName())) {
00185             fBuckets[hash]->setElementAt(arg,i);
00186             castToNodeImpl(n)->fOwnerNode = doc;
00187             castToNodeImpl(n)->isOwned(false);
00188             return n;
00189         }
00190     }
00191     fBuckets[hash]->addElement(arg);
00192     return 0;
00193 }
00194 
00195 
00196 void DOMNamedNodeMapImpl::setReadOnly(bool readOnl, bool deep)
00197 {
00198     // this->fReadOnly=readOnl;
00199     if(deep) {
00200         for (XMLSize_t index = 0; index < MAP_SIZE; index++) {
00201             if(fBuckets[index]==0)
00202                 continue;
00203             XMLSize_t sz = fBuckets[index]->size();
00204             for (XMLSize_t i=0; i<sz; ++i)
00205                 castToNodeImpl(fBuckets[index]->elementAt(i))->setReadOnly(readOnl, deep);
00206         }
00207     }
00208 }
00209 
00210 
00211 //Introduced in DOM Level 2
00212 
00213 DOMNode *DOMNamedNodeMapImpl::getNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName) const
00214 {
00215     // the map is indexed using the full name of nodes; to search given a namespace and a local name
00216     // we have to do a linear search
00217     for (XMLSize_t index = 0; index < MAP_SIZE; index++) {
00218         if(fBuckets[index]==0)
00219             continue;
00220 
00221         XMLSize_t i = 0;
00222         XMLSize_t size = fBuckets[index]->size();
00223         for (i = 0; i < size; ++i) {
00224             DOMNode *n=fBuckets[index]->elementAt(i);
00225             const XMLCh * nNamespaceURI = n->getNamespaceURI();
00226             const XMLCh * nLocalName = n->getLocalName();
00227             if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
00228                 continue;
00229             else {
00230                 if (XMLString::equals(localName, nLocalName)
00231                     ||
00232                     (nLocalName == 0 && XMLString::equals(localName, n->getNodeName())))
00233                     return n;
00234             }
00235         }
00236     }
00237     return 0;
00238 }
00239 
00240 
00241 //
00242 // setNamedItemNS()  Put the item into the NamedNodeList by name.
00243 //                  If an item with the same name already was
00244 //                  in the list, replace it.  Return the old
00245 //                  item, if there was one.
00246 //                  Caller is responsible for arranging for
00247 //                  deletion of the old item if its ref count is
00248 //                  zero.
00249 //
00250 DOMNode * DOMNamedNodeMapImpl::setNamedItemNS(DOMNode *arg)
00251 {
00252     DOMDocument *doc = fOwnerNode->getOwnerDocument();
00253     DOMNodeImpl *argImpl = castToNodeImpl(arg);
00254     if (argImpl->getOwnerDocument() != doc)
00255         throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
00256     if (this->readOnly())
00257         throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
00258     if (argImpl->isOwned())
00259         throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);
00260 
00261     argImpl->fOwnerNode = fOwnerNode;
00262     argImpl->isOwned(true);
00263 
00264     const XMLCh* namespaceURI=arg->getNamespaceURI();
00265     const XMLCh* localName=arg->getLocalName();
00266     // the map is indexed using the full name of nodes; to search given a namespace and a local name
00267     // we have to do a linear search
00268     for (XMLSize_t index = 0; index < MAP_SIZE; index++) {
00269         if(fBuckets[index]==0)
00270             continue;
00271 
00272         XMLSize_t i = 0;
00273         XMLSize_t size = fBuckets[index]->size();
00274         for (i = 0; i < size; ++i) {
00275             DOMNode *n=fBuckets[index]->elementAt(i);
00276             const XMLCh * nNamespaceURI = n->getNamespaceURI();
00277             const XMLCh * nLocalName = n->getLocalName();
00278             if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
00279                 continue;
00280             else {
00281                 if (XMLString::equals(localName, nLocalName)
00282                     ||
00283                     (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) {
00284                     fBuckets[index]->setElementAt(arg,i);
00285                     castToNodeImpl(n)->fOwnerNode = doc;
00286                     castToNodeImpl(n)->isOwned(false);
00287                     return n;
00288                 }
00289             }
00290         }
00291     }
00292     // if not found, add it using the full name as key
00293     return setNamedItem(arg);
00294 }
00295 
00296 
00297 // removeNamedItemNS() - Remove the named item, and return it.
00298 //                      The caller can release the
00299 //                      returned item if it's not used
00300 //                      we can't do it here because the caller would
00301 //                      never see the returned node.
00302 DOMNode *DOMNamedNodeMapImpl::removeNamedItemNS(const XMLCh *namespaceURI,
00303                                                  const XMLCh *localName)
00304 {
00305     if (this->readOnly())
00306         throw DOMException(
00307         DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
00308 
00309     // the map is indexed using the full name of nodes; to search given a namespace and a local name
00310     // we have to do a linear search
00311     for (XMLSize_t index = 0; index < MAP_SIZE; index++) {
00312         if(fBuckets[index]==0)
00313             continue;
00314 
00315         DOMDocument *doc = fOwnerNode->getOwnerDocument();
00316         XMLSize_t i = 0;
00317         XMLSize_t size = fBuckets[index]->size();
00318         for (i = 0; i < size; ++i) {
00319             DOMNode *n=fBuckets[index]->elementAt(i);
00320             const XMLCh * nNamespaceURI = n->getNamespaceURI();
00321             const XMLCh * nLocalName = n->getLocalName();
00322             if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
00323                 continue;
00324             else {
00325                 if (XMLString::equals(localName, nLocalName)
00326                     ||
00327                     (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) {
00328                     fBuckets[index]->removeElementAt(i);
00329                     castToNodeImpl(n)->fOwnerNode = doc;
00330                     castToNodeImpl(n)->isOwned(false);
00331                     return n;
00332                 }
00333             }
00334         }
00335     }
00336     throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
00337     return 0;
00338 }
00339 
00340 XERCES_CPP_NAMESPACE_END