GME
13
|
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