GME  13
DOMAttrMapImpl.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 /*
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