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 /* 00020 * $Id: DOMAttrMapImpl.cpp 678709 2008-07-22 10:56:56Z borisk $ 00021 */ 00022 00023 #include "DOMCasts.hpp" 00024 #include "DOMNodeImpl.hpp" 00025 #include "DOMNodeVector.hpp" 00026 #include "DOMAttrMapImpl.hpp" 00027 #include "DOMAttrImpl.hpp" 00028 #include "DOMElementImpl.hpp" 00029 00030 #include <xercesc/dom/DOMAttr.hpp> 00031 #include <xercesc/dom/DOMException.hpp> 00032 00033 XERCES_CPP_NAMESPACE_BEGIN 00034 00035 DOMAttrMapImpl::DOMAttrMapImpl(DOMNode *ownerNod) 00036 { 00037 this->fOwnerNode=ownerNod; 00038 this->fNodes = 0; 00039 hasDefaults(false); 00040 } 00041 00042 DOMAttrMapImpl::DOMAttrMapImpl(DOMNode *ownerNod, const DOMAttrMapImpl *defaults) 00043 { 00044 this->fOwnerNode=ownerNod; 00045 this->fNodes = 0; 00046 hasDefaults(false); 00047 if (defaults != 0) 00048 { 00049 if (defaults->getLength() > 0) 00050 { 00051 hasDefaults(true); 00052 cloneContent(defaults); 00053 } 00054 } 00055 } 00056 00057 DOMAttrMapImpl::~DOMAttrMapImpl() 00058 { 00059 } 00060 00061 void DOMAttrMapImpl::cloneContent(const DOMAttrMapImpl *srcmap) 00062 { 00063 if ((srcmap != 0) && (srcmap->fNodes != 0)) 00064 { 00065 if (fNodes != 0) 00066 fNodes->reset(); 00067 else 00068 { 00069 XMLSize_t size = srcmap->fNodes->size(); 00070 if(size > 0) { 00071 DOMDocumentImpl *doc = (DOMDocumentImpl*)fOwnerNode->getOwnerDocument(); 00072 fNodes = new (doc) DOMNodeVector(doc, size); 00073 } 00074 } 00075 00076 for (XMLSize_t i = 0; i < srcmap->fNodes->size(); i++) 00077 { 00078 DOMNode *n = srcmap->fNodes->elementAt(i); 00079 DOMNode *clone = n->cloneNode(true); 00080 castToNodeImpl(clone)->isSpecified(castToNodeImpl(n)->isSpecified()); 00081 castToNodeImpl(clone)->fOwnerNode = fOwnerNode; 00082 castToNodeImpl(clone)->isOwned(true); 00083 fNodes->addElement(clone); 00084 } 00085 } 00086 } 00087 00088 DOMAttrMapImpl *DOMAttrMapImpl::cloneAttrMap(DOMNode *ownerNode_p) 00089 { 00090 DOMAttrMapImpl *newmap = new (castToNodeImpl(ownerNode_p)->getOwnerDocument()) DOMAttrMapImpl(ownerNode_p); 00091 newmap->cloneContent(this); 00092 // newmap->attrDefaults = this->attrDefaults; // revisit 00093 return newmap; 00094 } 00095 00096 void DOMAttrMapImpl::setReadOnly(bool readOnl, bool deep) 00097 { 00098 // this->fReadOnly=readOnl; 00099 if(deep && fNodes!=0) 00100 { 00101 XMLSize_t sz = fNodes->size(); 00102 for (XMLSize_t i=0; i<sz; ++i) { 00103 castToNodeImpl(fNodes->elementAt(i))->setReadOnly(readOnl, deep); 00104 } 00105 } 00106 } 00107 00108 bool DOMAttrMapImpl::readOnly() { 00109 return castToNodeImpl(fOwnerNode)->isReadOnly(); 00110 } 00111 00112 int DOMAttrMapImpl::findNamePoint(const XMLCh *name) const 00113 { 00114 // Binary search 00115 int i=0; 00116 if(fNodes!=0) 00117 { 00118 int first=0,last=(int)fNodes->size()-1; 00119 00120 while(first<=last) 00121 { 00122 i=(first+last)/2; 00123 int test = XMLString::compareString(name, fNodes->elementAt(i)->getNodeName()); 00124 if(test==0) 00125 return i; // Name found 00126 else if(test<0) 00127 last=i-1; 00128 else 00129 first=i+1; 00130 } 00131 if(first>i) i=first; 00132 } 00133 /******************** 00134 // Linear search 00135 int i = 0; 00136 if (fNodes != 0) 00137 for (i = 0; i < fNodes.size(); ++i) 00138 { 00139 int test = name.compareTo(((NodeImpl *) (fNodes.elementAt(i))).getNodeName()); 00140 if (test == 0) 00141 return i; 00142 else 00143 if (test < 0) 00144 { 00145 break; // Found insertpoint 00146 } 00147 } 00148 00149 *******************/ 00150 return -1 - i; // not-found has to be encoded. 00151 } 00152 00153 DOMNode * DOMAttrMapImpl::getNamedItem(const XMLCh *name) const 00154 { 00155 int i=findNamePoint(name); 00156 return (i<0) ? 0 : fNodes->elementAt(i); 00157 } 00158 00159 DOMNode *DOMAttrMapImpl::setNamedItem(DOMNode *arg) 00160 { 00161 if (arg->getNodeType() != DOMNode::ATTRIBUTE_NODE) 00162 throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNamedNodeMapMemoryManager); 00163 00164 DOMDocument *doc = fOwnerNode->getOwnerDocument(); 00165 DOMNodeImpl *argImpl = castToNodeImpl(arg); 00166 if(argImpl->getOwnerDocument() != doc) 00167 throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNamedNodeMapMemoryManager); 00168 if (this->readOnly()) 00169 throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); 00170 if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode)) 00171 throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager); 00172 00173 argImpl->fOwnerNode = fOwnerNode; 00174 argImpl->isOwned(true); 00175 int i=findNamePoint(arg->getNodeName()); 00176 DOMNode * previous=0; 00177 if(i>=0) 00178 { 00179 previous = fNodes->elementAt(i); 00180 fNodes->setElementAt(arg,i); 00181 } 00182 else 00183 { 00184 i=-1-i; // Insert point (may be end of list) 00185 if(0==fNodes) 00186 { 00187 fNodes=new ((DOMDocumentImpl*)doc) DOMNodeVector(doc); 00188 } 00189 fNodes->insertElementAt(arg,i); 00190 } 00191 if (previous != 0) { 00192 castToNodeImpl(previous)->fOwnerNode = doc; 00193 castToNodeImpl(previous)->isOwned(false); 00194 } 00195 00196 return previous; 00197 } 00198 00199 //Introduced in DOM Level 2 00200 00201 int DOMAttrMapImpl::findNamePoint(const XMLCh *namespaceURI, 00202 const XMLCh *localName) const 00203 { 00204 if (fNodes == 0) 00205 return -1; 00206 // This is a linear search through the same fNodes Vector. 00207 // The Vector is sorted on the DOM Level 1 nodename. 00208 // The DOM Level 2 NS keys are namespaceURI and Localname, 00209 // so we must linear search thru it. 00210 // In addition, to get this to work with fNodes without any namespace 00211 // (namespaceURI and localNames are both 0) we then use the nodeName 00212 // as a secondary key. 00213 const XMLSize_t len = fNodes -> size(); 00214 for (XMLSize_t i = 0; i < len; ++i) { 00215 DOMNode *node = fNodes -> elementAt(i); 00216 const XMLCh * nNamespaceURI = node->getNamespaceURI(); 00217 const XMLCh * nLocalName = node->getLocalName(); 00218 if (!XMLString::equals(nNamespaceURI, namespaceURI)) //URI not match 00219 continue; 00220 else { 00221 if (XMLString::equals(localName, nLocalName) 00222 || 00223 (nLocalName == 0 && XMLString::equals(localName, node->getNodeName()))) 00224 return (int)i; 00225 } 00226 } 00227 return -1; //not found 00228 } 00229 00230 DOMNode *DOMAttrMapImpl::getNamedItemNS(const XMLCh *namespaceURI, 00231 const XMLCh *localName) const 00232 { 00233 int i = findNamePoint(namespaceURI, localName); 00234 return i < 0 ? 0 : fNodes -> elementAt(i); 00235 } 00236 00237 DOMNode *DOMAttrMapImpl::setNamedItemNS(DOMNode* arg) 00238 { 00239 if (arg->getNodeType() != DOMNode::ATTRIBUTE_NODE) 00240 throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNamedNodeMapMemoryManager); 00241 00242 DOMDocument *doc = fOwnerNode->getOwnerDocument(); 00243 DOMNodeImpl *argImpl = castToNodeImpl(arg); 00244 if (argImpl->getOwnerDocument() != doc) 00245 throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager); 00246 if (this->readOnly()) 00247 throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); 00248 if (argImpl->isOwned()) 00249 throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager); 00250 00251 argImpl->fOwnerNode = fOwnerNode; 00252 argImpl->isOwned(true); 00253 int i=findNamePoint(arg->getNamespaceURI(), arg->getLocalName()); 00254 DOMNode *previous=0; 00255 if(i>=0) { 00256 previous = fNodes->elementAt(i); 00257 fNodes->setElementAt(arg,i); 00258 } else { 00259 i=findNamePoint(arg->getNodeName()); // Insert point (may be end of list) 00260 if (i<0) 00261 i = -1 - i; 00262 if(0==fNodes) 00263 fNodes=new ((DOMDocumentImpl*)doc) DOMNodeVector(doc); 00264 fNodes->insertElementAt(arg,i); 00265 } 00266 if (previous != 0) { 00267 castToNodeImpl(previous)->fOwnerNode = doc; 00268 castToNodeImpl(previous)->isOwned(false); 00269 } 00270 00271 return previous; 00272 } 00273 00274 DOMNode *DOMAttrMapImpl::removeNamedItem(const XMLCh *name) 00275 { 00276 if (this->readOnly()) 00277 throw DOMException( 00278 DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); 00279 int i=findNamePoint(name); 00280 DOMNode *removed = 0; 00281 00282 if(i<0) 00283 throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); 00284 00285 removed = fNodes->elementAt(i); 00286 fNodes->removeElementAt(i); 00287 castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument(); 00288 castToNodeImpl(removed)->isOwned(false); 00289 00290 // Replace it if it had a default value 00291 // (DOM spec level 1 - Element Interface) 00292 if (hasDefaults() && (removed != 0)) 00293 { 00294 DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes(); 00295 DOMAttr* attr = (DOMAttr*)(defAttrs->getNamedItem(name)); 00296 if (attr != 0) 00297 { 00298 DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true); 00299 setNamedItem(newAttr); 00300 } 00301 } 00302 00303 return removed; 00304 } 00305 00306 DOMNode *DOMAttrMapImpl::removeNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName) 00307 { 00308 if (this->readOnly()) 00309 throw DOMException( 00310 DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); 00311 int i = findNamePoint(namespaceURI, localName); 00312 if (i < 0) 00313 throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); 00314 00315 DOMNode * removed = fNodes -> elementAt(i); 00316 fNodes -> removeElementAt(i); //remove n from nodes 00317 castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument(); 00318 castToNodeImpl(removed)->isOwned(false); 00319 00320 // Replace it if it had a default value 00321 // (DOM spec level 2 - Element Interface) 00322 00323 if (hasDefaults() && (removed != 0)) 00324 { 00325 DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes(); 00326 DOMAttr* attr = (DOMAttr*)(defAttrs->getNamedItemNS(namespaceURI, localName)); 00327 if (attr != 0) 00328 { 00329 DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true); 00330 setNamedItemNS(newAttr); 00331 } 00332 } 00333 00334 return removed; 00335 } 00336 00337 // remove the name using index 00338 // avoid calling findNamePoint again if the index is already known 00339 DOMNode * DOMAttrMapImpl::removeNamedItemAt(XMLSize_t index) 00340 { 00341 if (this->readOnly()) 00342 throw DOMException( 00343 DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); 00344 00345 DOMNode *removed = item(index); 00346 if(!removed) 00347 throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); 00348 00349 fNodes->removeElementAt(index); 00350 castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument(); 00351 castToNodeImpl(removed)->isOwned(false); 00352 00353 // Replace it if it had a default value 00354 // (DOM spec level 1 - Element Interface) 00355 if (hasDefaults() && (removed != 0)) 00356 { 00357 DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes(); 00358 00359 const XMLCh* localName = removed->getLocalName(); 00360 DOMAttr* attr = 0; 00361 if (localName) 00362 attr = (DOMAttr*)(defAttrs->getNamedItemNS(removed->getNamespaceURI(), localName)); 00363 else 00364 attr = (DOMAttr*)(defAttrs->getNamedItem(((DOMAttr*)removed)->getName())); 00365 00366 if (attr != 0) 00367 { 00368 DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true); 00369 setNamedItem(newAttr); 00370 } 00371 } 00372 00373 return removed; 00374 } 00375 00380 void DOMAttrMapImpl::reconcileDefaultAttributes(const DOMAttrMapImpl* defaults) { 00381 00382 // remove any existing default 00383 XMLSize_t nsize = getLength(); 00384 for (XMLSize_t i = nsize; i > 0; i--) { 00385 DOMAttr* attr = (DOMAttr*)item(i-1); 00386 if (!attr->getSpecified()) { 00387 removeNamedItemAt(i-1); 00388 } 00389 } 00390 00391 hasDefaults(false); 00392 00393 // add the new defaults 00394 if (defaults) { 00395 hasDefaults(true); 00396 00397 if (nsize == 0) { 00398 cloneContent(defaults); 00399 } 00400 else { 00401 XMLSize_t dsize = defaults->getLength(); 00402 for (XMLSize_t n = 0; n < dsize; n++) { 00403 DOMAttr* attr = (DOMAttr*)defaults->item(n); 00404 00405 DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true); 00406 setNamedItemNS(newAttr); 00407 DOMAttrImpl* newAttrImpl = (DOMAttrImpl*) newAttr; 00408 newAttrImpl->setSpecified(false); 00409 } 00410 } 00411 } 00412 } // reconcileDefaults() 00413 00414 00418 void DOMAttrMapImpl::moveSpecifiedAttributes(DOMAttrMapImpl* srcmap) { 00419 XMLSize_t nsize = srcmap->getLength(); 00420 00421 for (XMLSize_t i = nsize; i > 0; i--) { 00422 DOMAttr* attr = (DOMAttr*)srcmap->item(i-1); 00423 if (attr->getSpecified()) { 00424 srcmap->removeNamedItemAt(i-1); 00425 } 00426 00427 if (attr->getLocalName()) 00428 setNamedItemNS(attr); 00429 else 00430 setNamedItem(attr); 00431 } 00432 } // moveSpecifiedAttributes(AttributeMap):void 00433 00434 XMLSize_t DOMAttrMapImpl::getLength() const 00435 { 00436 return (fNodes != 0) ? fNodes->size() : 0; 00437 } 00438 00439 DOMNode * DOMAttrMapImpl::item(XMLSize_t index) const 00440 { 00441 return (fNodes != 0 && index < fNodes->size()) ? 00442 fNodes->elementAt(index) : 0; 00443 } 00444 00445 void DOMAttrMapImpl::setNamedItemFast(DOMNode *arg) 00446 { 00447 DOMNodeImpl *argImpl = castToNodeImpl(arg); 00448 00449 argImpl->fOwnerNode = fOwnerNode; 00450 argImpl->isOwned(true); 00451 int i = findNamePoint(arg->getNodeName()); 00452 00453 if(i >= 0) 00454 fNodes->setElementAt(arg, i); 00455 else 00456 { 00457 i= -1 -i; 00458 fNodes->insertElementAt(arg, i); 00459 } 00460 } 00461 00462 void DOMAttrMapImpl::setNamedItemNSFast(DOMNode* arg) 00463 { 00464 DOMNodeImpl *argImpl = castToNodeImpl(arg); 00465 00466 argImpl->fOwnerNode = fOwnerNode; 00467 argImpl->isOwned(true); 00468 int i=findNamePoint(arg->getNamespaceURI(), arg->getLocalName()); 00469 00470 if(i >= 0) 00471 { 00472 fNodes->setElementAt(arg,i); 00473 } 00474 else 00475 { 00476 i = findNamePoint(arg->getNodeName()); 00477 00478 if (i < 0) 00479 i = -1 - i; 00480 00481 fNodes->insertElementAt(arg,i); 00482 } 00483 } 00484 00485 void DOMAttrMapImpl::reserve (XMLSize_t n) 00486 { 00487 if (fNodes == 0) 00488 { 00489 DOMDocumentImpl* doc = (DOMDocumentImpl*)fOwnerNode->getOwnerDocument(); 00490 fNodes = new (doc) DOMNodeVector(doc, n); 00491 } 00492 } 00493 00494 XERCES_CPP_NAMESPACE_END