source: icXML/icXML-devel/src/xercesc/dom/impl/DOMAttrMapImpl.cpp @ 2777

Last change on this file since 2777 was 2777, checked in by cameron, 7 years ago

Set up to use xercesc/icxercesc root-relative paths for all includes

File size: 14.5 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
19/*
20 * $Id: DOMAttrMapImpl.cpp 678709 2008-07-22 10:56:56Z borisk $
21 */
22
23#include <xercesc/dom/impl/DOMCasts.hpp>
24#include <icxercesc/dom/impl/DOMNodeImpl.hpp>
25#include <xercesc/dom/impl/DOMNodeVector.hpp>
26#include <xercesc/dom/impl/DOMAttrMapImpl.hpp>
27#include <xercesc/dom/impl/DOMAttrImpl.hpp>
28#include <xercesc/dom/impl/DOMElementImpl.hpp>
29
30#include <xercesc/dom/DOMAttr.hpp>
31#include <xercesc/dom/DOMException.hpp>
32
33XERCES_CPP_NAMESPACE_BEGIN
34
35DOMAttrMapImpl::DOMAttrMapImpl(DOMNode *ownerNod)
36{
37    this->fOwnerNode=ownerNod;
38    this->fNodes = 0;
39        hasDefaults(false);
40}
41
42DOMAttrMapImpl::DOMAttrMapImpl(DOMNode *ownerNod, const DOMAttrMapImpl *defaults)
43{
44    this->fOwnerNode=ownerNod;
45    this->fNodes = 0;
46        hasDefaults(false);
47        if (defaults != 0)
48        {
49                if (defaults->getLength() > 0)
50                {
51                        hasDefaults(true);
52                        cloneContent(defaults);
53                }
54        }
55}
56
57DOMAttrMapImpl::~DOMAttrMapImpl()
58{
59}
60
61void DOMAttrMapImpl::cloneContent(const DOMAttrMapImpl *srcmap)
62{
63    if ((srcmap != 0) && (srcmap->fNodes != 0))
64    {
65        if (fNodes != 0)
66            fNodes->reset();
67        else
68        {
69            XMLSize_t size = srcmap->fNodes->size();
70            if(size > 0) {
71                DOMDocumentImpl *doc = (DOMDocumentImpl*)fOwnerNode->getOwnerDocument();
72                fNodes = new (doc) DOMNodeVector(doc, size);
73            }
74        }
75
76        for (XMLSize_t i = 0; i < srcmap->fNodes->size(); i++)
77        {
78            DOMNode *n = srcmap->fNodes->elementAt(i);
79            DOMNode *clone = n->cloneNode(true);
80            castToNodeImpl(clone)->isSpecified(castToNodeImpl(n)->isSpecified());
81            castToNodeImpl(clone)->fOwnerNode = fOwnerNode;
82            castToNodeImpl(clone)->isOwned(true);
83            fNodes->addElement(clone);
84        }
85    }
86}
87
88DOMAttrMapImpl *DOMAttrMapImpl::cloneAttrMap(DOMNode *ownerNode_p)
89{
90        DOMAttrMapImpl *newmap = new (castToNodeImpl(ownerNode_p)->getOwnerDocument()) DOMAttrMapImpl(ownerNode_p);
91        newmap->cloneContent(this);
92        // newmap->attrDefaults = this->attrDefaults;  // revisit
93        return newmap;
94}
95
96void DOMAttrMapImpl::setReadOnly(bool readOnl, bool deep)
97{
98    // this->fReadOnly=readOnl;
99    if(deep && fNodes!=0)
100    {
101        XMLSize_t sz = fNodes->size();
102        for (XMLSize_t i=0; i<sz; ++i) {
103            castToNodeImpl(fNodes->elementAt(i))->setReadOnly(readOnl, deep);
104        }
105    }
106}
107
108bool DOMAttrMapImpl::readOnly() {
109    return castToNodeImpl(fOwnerNode)->isReadOnly();
110}
111
112int DOMAttrMapImpl::findNamePoint(const XMLCh *name) const
113{
114    // Binary search
115    int i=0;
116    if(fNodes!=0)
117    {
118        int first=0,last=(int)fNodes->size()-1;
119
120        while(first<=last)
121        {
122            i=(first+last)/2;
123            int test = XMLString::compareString(name, fNodes->elementAt(i)->getNodeName());
124            if(test==0)
125                return i; // Name found
126            else if(test<0)
127                last=i-1;
128            else
129                first=i+1;
130        }
131        if(first>i) i=first;
132    }
133    /********************
134    // Linear search
135    int i = 0;
136    if (fNodes != 0)
137    for (i = 0; i < fNodes.size(); ++i)
138    {
139    int test = name.compareTo(((NodeImpl *) (fNodes.elementAt(i))).getNodeName());
140    if (test == 0)
141    return i;
142    else
143    if (test < 0)
144    {
145    break; // Found insertpoint
146    }
147    }
148
149    *******************/
150    return -1 - i; // not-found has to be encoded.
151}
152
153DOMNode * DOMAttrMapImpl::getNamedItem(const XMLCh *name) const
154{
155    int i=findNamePoint(name);
156    return (i<0) ? 0 : fNodes->elementAt(i);
157}
158
159DOMNode *DOMAttrMapImpl::setNamedItem(DOMNode *arg)
160{
161    if (arg->getNodeType() != DOMNode::ATTRIBUTE_NODE)
162        throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNamedNodeMapMemoryManager);
163
164    DOMDocument *doc = fOwnerNode->getOwnerDocument();
165    DOMNodeImpl *argImpl = castToNodeImpl(arg);
166    if(argImpl->getOwnerDocument() != doc)
167        throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNamedNodeMapMemoryManager);
168    if (this->readOnly())
169        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
170    if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode))
171        throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);
172
173    argImpl->fOwnerNode = fOwnerNode;
174    argImpl->isOwned(true);
175    int i=findNamePoint(arg->getNodeName());
176    DOMNode * previous=0;
177    if(i>=0)
178    {
179        previous = fNodes->elementAt(i);
180        fNodes->setElementAt(arg,i);
181    }
182    else
183    {
184        i=-1-i; // Insert point (may be end of list)
185        if(0==fNodes)
186        {
187            fNodes=new ((DOMDocumentImpl*)doc) DOMNodeVector(doc);
188        }
189        fNodes->insertElementAt(arg,i);
190    }
191    if (previous != 0) {
192        castToNodeImpl(previous)->fOwnerNode = doc;
193        castToNodeImpl(previous)->isOwned(false);
194    }
195
196    return previous;
197}
198
199//Introduced in DOM Level 2
200
201int DOMAttrMapImpl::findNamePoint(const XMLCh *namespaceURI,
202        const XMLCh *localName) const
203{
204    if (fNodes == 0)
205        return -1;
206    // This is a linear search through the same fNodes Vector.
207    // The Vector is sorted on the DOM Level 1 nodename.
208    // The DOM Level 2 NS keys are namespaceURI and Localname,
209    // so we must linear search thru it.
210    // In addition, to get this to work with fNodes without any namespace
211    // (namespaceURI and localNames are both 0) we then use the nodeName
212    // as a secondary key.
213    const XMLSize_t len = fNodes -> size();
214    for (XMLSize_t i = 0; i < len; ++i) {
215        DOMNode *node = fNodes -> elementAt(i);
216        const XMLCh * nNamespaceURI = node->getNamespaceURI();
217        const XMLCh * nLocalName = node->getLocalName();
218        if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
219            continue;
220        else {
221            if (XMLString::equals(localName, nLocalName)
222                ||
223                (nLocalName == 0 && XMLString::equals(localName, node->getNodeName())))
224                return (int)i;
225        }
226    }
227    return -1;  //not found
228}
229
230DOMNode *DOMAttrMapImpl::getNamedItemNS(const XMLCh *namespaceURI,
231        const XMLCh *localName) const
232{
233    int i = findNamePoint(namespaceURI, localName);
234    return i < 0 ? 0 : fNodes -> elementAt(i);
235}
236
237DOMNode *DOMAttrMapImpl::setNamedItemNS(DOMNode* arg)
238{
239    if (arg->getNodeType() != DOMNode::ATTRIBUTE_NODE)
240        throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNamedNodeMapMemoryManager);
241
242    DOMDocument *doc = fOwnerNode->getOwnerDocument();
243    DOMNodeImpl *argImpl = castToNodeImpl(arg);
244    if (argImpl->getOwnerDocument() != doc)
245        throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
246    if (this->readOnly())
247        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
248    if (argImpl->isOwned())
249        throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);
250
251    argImpl->fOwnerNode = fOwnerNode;
252    argImpl->isOwned(true);
253    int i=findNamePoint(arg->getNamespaceURI(), arg->getLocalName());
254    DOMNode *previous=0;
255    if(i>=0) {
256        previous = fNodes->elementAt(i);
257        fNodes->setElementAt(arg,i);
258    } else {
259        i=findNamePoint(arg->getNodeName()); // Insert point (may be end of list)
260        if (i<0)
261          i = -1 - i;
262        if(0==fNodes)
263            fNodes=new ((DOMDocumentImpl*)doc) DOMNodeVector(doc);
264        fNodes->insertElementAt(arg,i);
265    }
266    if (previous != 0) {
267        castToNodeImpl(previous)->fOwnerNode = doc;
268        castToNodeImpl(previous)->isOwned(false);
269    }
270
271    return previous;
272}
273
274DOMNode *DOMAttrMapImpl::removeNamedItem(const XMLCh *name)
275{
276    if (this->readOnly())
277        throw DOMException(
278            DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
279    int i=findNamePoint(name);
280    DOMNode *removed = 0;
281
282    if(i<0)
283        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
284
285    removed = fNodes->elementAt(i);
286    fNodes->removeElementAt(i);
287    castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument();
288    castToNodeImpl(removed)->isOwned(false);
289
290    // Replace it if it had a default value
291    // (DOM spec level 1 - Element Interface)
292    if (hasDefaults() && (removed != 0))
293    {
294        DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes();
295        DOMAttr* attr = (DOMAttr*)(defAttrs->getNamedItem(name));
296        if (attr != 0)
297        {
298            DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true);
299            setNamedItem(newAttr);
300        }
301    }
302
303    return removed;
304}
305
306DOMNode *DOMAttrMapImpl::removeNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName)
307{
308    if (this->readOnly())
309        throw DOMException(
310        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
311    int i = findNamePoint(namespaceURI, localName);
312    if (i < 0)
313        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
314
315    DOMNode * removed = fNodes -> elementAt(i);
316    fNodes -> removeElementAt(i);       //remove n from nodes
317    castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument();
318    castToNodeImpl(removed)->isOwned(false);
319
320    // Replace it if it had a default value
321    // (DOM spec level 2 - Element Interface)
322
323    if (hasDefaults() && (removed != 0))
324    {
325        DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes();
326        DOMAttr* attr = (DOMAttr*)(defAttrs->getNamedItemNS(namespaceURI, localName));
327        if (attr != 0)
328        {
329            DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true);
330            setNamedItemNS(newAttr);
331        }
332    }
333
334    return removed;
335}
336
337// remove the name using index
338// avoid calling findNamePoint again if the index is already known
339DOMNode * DOMAttrMapImpl::removeNamedItemAt(XMLSize_t index)
340{
341    if (this->readOnly())
342        throw DOMException(
343            DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
344
345    DOMNode *removed = item(index);
346    if(!removed)
347        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
348
349    fNodes->removeElementAt(index);
350    castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument();
351    castToNodeImpl(removed)->isOwned(false);
352
353    // Replace it if it had a default value
354    // (DOM spec level 1 - Element Interface)
355    if (hasDefaults() && (removed != 0))
356    {
357        DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes();
358
359        const XMLCh* localName = removed->getLocalName();
360        DOMAttr* attr = 0;
361        if (localName)
362            attr = (DOMAttr*)(defAttrs->getNamedItemNS(removed->getNamespaceURI(), localName));
363        else
364            attr = (DOMAttr*)(defAttrs->getNamedItem(((DOMAttr*)removed)->getName()));
365
366        if (attr != 0)
367        {
368            DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true);
369            setNamedItem(newAttr);
370        }
371    }
372
373    return removed;
374}
375
376/**
377 * Get this AttributeMap in sync with the given "defaults" map.
378 * @param defaults The default attributes map to sync with.
379 */
380void DOMAttrMapImpl::reconcileDefaultAttributes(const DOMAttrMapImpl* defaults) {
381
382    // remove any existing default
383    XMLSize_t nsize = getLength();
384    for (XMLSize_t i = nsize; i > 0; i--) {
385        DOMAttr* attr = (DOMAttr*)item(i-1);
386        if (!attr->getSpecified()) {
387            removeNamedItemAt(i-1);
388        }
389    }
390
391    hasDefaults(false);
392
393    // add the new defaults
394    if (defaults) {
395        hasDefaults(true);
396
397        if (nsize == 0) {
398            cloneContent(defaults);
399        }
400        else {
401            XMLSize_t dsize = defaults->getLength();
402            for (XMLSize_t n = 0; n < dsize; n++) {
403                DOMAttr* attr = (DOMAttr*)defaults->item(n);
404
405                DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true);
406                setNamedItemNS(newAttr);
407                DOMAttrImpl* newAttrImpl = (DOMAttrImpl*) newAttr;
408                newAttrImpl->setSpecified(false);
409            }
410        }
411    }
412} // reconcileDefaults()
413
414
415/**
416 * Move specified attributes from the given map to this one
417 */
418void DOMAttrMapImpl::moveSpecifiedAttributes(DOMAttrMapImpl* srcmap) {
419    XMLSize_t nsize = srcmap->getLength();
420
421    for (XMLSize_t i = nsize; i > 0; i--) {
422        DOMAttr* attr = (DOMAttr*)srcmap->item(i-1);
423        if (attr->getSpecified()) {
424            srcmap->removeNamedItemAt(i-1);
425        }
426
427        if (attr->getLocalName())
428            setNamedItemNS(attr);
429        else
430            setNamedItem(attr);
431    }
432} // moveSpecifiedAttributes(AttributeMap):void
433
434XMLSize_t DOMAttrMapImpl::getLength() const
435{
436    return (fNodes != 0) ? fNodes->size() : 0;
437}
438
439DOMNode * DOMAttrMapImpl::item(XMLSize_t index) const
440{
441    return (fNodes != 0 && index < fNodes->size()) ?
442        fNodes->elementAt(index) : 0;
443}
444
445void DOMAttrMapImpl::setNamedItemFast(DOMNode *arg)
446{
447    DOMNodeImpl *argImpl = castToNodeImpl(arg);
448
449    argImpl->fOwnerNode = fOwnerNode;
450    argImpl->isOwned(true);
451    int i = findNamePoint(arg->getNodeName());
452
453    if(i >= 0)
454      fNodes->setElementAt(arg, i);
455    else
456    {
457      i= -1 -i;
458      fNodes->insertElementAt(arg, i);
459    }
460}
461
462void DOMAttrMapImpl::setNamedItemNSFast(DOMNode* arg)
463{
464    DOMNodeImpl *argImpl = castToNodeImpl(arg);
465
466    argImpl->fOwnerNode = fOwnerNode;
467    argImpl->isOwned(true);
468    int i=findNamePoint(arg->getNamespaceURI(), arg->getLocalName());
469
470    if(i >= 0)
471    {
472        fNodes->setElementAt(arg,i);
473    }
474    else
475    {
476        i = findNamePoint(arg->getNodeName());
477
478        if (i < 0)
479          i = -1 - i;
480
481        fNodes->insertElementAt(arg,i);
482    }
483}
484
485void DOMAttrMapImpl::reserve (XMLSize_t n)
486{
487  if (fNodes == 0)
488  {
489    DOMDocumentImpl* doc = (DOMDocumentImpl*)fOwnerNode->getOwnerDocument();
490    fNodes = new (doc) DOMNodeVector(doc, n);
491  }
492}
493
494XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.