Newer
Older
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
Boris Kolpackov
committed
*
Boris Kolpackov
committed
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id$
*/
#include "DOMCasts.hpp"
#include "DOMNodeImpl.hpp"
#include "DOMNodeVector.hpp"
#include "DOMAttrMapImpl.hpp"
#include "DOMElementImpl.hpp"
Alberto Massari
committed
#include <xercesc/dom/DOMAttr.hpp>
#include <xercesc/dom/DOMException.hpp>
DOMAttrMapImpl::DOMAttrMapImpl(DOMNode *ownerNod)
{
Alberto Massari
committed
this->fOwnerNode=ownerNod;
this->fNodes = 0;
hasDefaults(false);
}
Alberto Massari
committed
DOMAttrMapImpl::DOMAttrMapImpl(DOMNode *ownerNod, const DOMAttrMapImpl *defaults)
{
Alberto Massari
committed
this->fOwnerNode=ownerNod;
this->fNodes = 0;
hasDefaults(false);
if (defaults != 0)
{
if (defaults->getLength() > 0)
{
hasDefaults(true);
cloneContent(defaults);
}
}
}
DOMAttrMapImpl::~DOMAttrMapImpl()
{
}
Alberto Massari
committed
void DOMAttrMapImpl::cloneContent(const DOMAttrMapImpl *srcmap)
{
if ((srcmap != 0) && (srcmap->fNodes != 0))
{
if (fNodes != 0)
fNodes->reset();
else
{
Boris Kolpackov
committed
XMLSize_t size = srcmap->fNodes->size();
Alberto Massari
committed
if(size > 0) {
DOMDocumentImpl *doc = (DOMDocumentImpl*)fOwnerNode->getOwnerDocument();
Alberto Massari
committed
fNodes = new (doc) DOMNodeVector(doc, size);
}
}
Boris Kolpackov
committed
for (XMLSize_t i = 0; i < srcmap->fNodes->size(); i++)
Alberto Massari
committed
{
DOMNode *n = srcmap->fNodes->elementAt(i);
DOMNode *clone = n->cloneNode(true);
castToNodeImpl(clone)->isSpecified(castToNodeImpl(n)->isSpecified());
castToNodeImpl(clone)->fOwnerNode = fOwnerNode;
castToNodeImpl(clone)->isOwned(true);
fNodes->addElement(clone);
}
}
}
DOMAttrMapImpl *DOMAttrMapImpl::cloneAttrMap(DOMNode *ownerNode_p)
{
DOMAttrMapImpl *newmap = new (castToNodeImpl(ownerNode_p)->getOwnerDocument()) DOMAttrMapImpl(ownerNode_p);
newmap->cloneContent(this);
// newmap->attrDefaults = this->attrDefaults; // revisit
return newmap;
}
Alberto Massari
committed
void DOMAttrMapImpl::setReadOnly(bool readOnl, bool deep)
{
// this->fReadOnly=readOnl;
if(deep && fNodes!=0)
{
Boris Kolpackov
committed
XMLSize_t sz = fNodes->size();
for (XMLSize_t i=0; i<sz; ++i) {
Alberto Massari
committed
castToNodeImpl(fNodes->elementAt(i))->setReadOnly(readOnl, deep);
}
}
}
bool DOMAttrMapImpl::readOnly() {
return castToNodeImpl(fOwnerNode)->isReadOnly();
}
int DOMAttrMapImpl::findNamePoint(const XMLCh *name) const
{
// Binary search
Alberto Massari
committed
if(fNodes!=0)
{
int first=0,last=(int)fNodes->size()-1;
Alberto Massari
committed
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
while(first<=last)
{
i=(first+last)/2;
int test = XMLString::compareString(name, fNodes->elementAt(i)->getNodeName());
if(test==0)
return i; // Name found
else if(test<0)
last=i-1;
else
first=i+1;
}
if(first>i) i=first;
}
/********************
// Linear search
int i = 0;
if (fNodes != 0)
for (i = 0; i < fNodes.size(); ++i)
{
int test = name.compareTo(((NodeImpl *) (fNodes.elementAt(i))).getNodeName());
if (test == 0)
return i;
else
if (test < 0)
{
break; // Found insertpoint
}
}
*******************/
return -1 - i; // not-found has to be encoded.
}
DOMNode * DOMAttrMapImpl::getNamedItem(const XMLCh *name) const
{
int i=findNamePoint(name);
return (i<0) ? 0 : fNodes->elementAt(i);
}
DOMNode *DOMAttrMapImpl::setNamedItem(DOMNode *arg)
{
if (arg->getNodeType() != DOMNode::ATTRIBUTE_NODE)
throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
DOMDocument *doc = fOwnerNode->getOwnerDocument();
DOMNodeImpl *argImpl = castToNodeImpl(arg);
if(argImpl->getOwnerDocument() != doc)
throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
if (this->readOnly())
throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode))
throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
argImpl->fOwnerNode = fOwnerNode;
argImpl->isOwned(true);
int i=findNamePoint(arg->getNodeName());
DOMNode * previous=0;
if(i>=0)
{
previous = fNodes->elementAt(i);
fNodes->setElementAt(arg,i);
}
else
{
i=-1-i; // Insert point (may be end of list)
if(0==fNodes)
{
fNodes=new ((DOMDocumentImpl*)doc) DOMNodeVector(doc);
Alberto Massari
committed
}
fNodes->insertElementAt(arg,i);
}
if (previous != 0) {
Boris Kolpackov
committed
castToNodeImpl(previous)->fOwnerNode = doc;
Alberto Massari
committed
castToNodeImpl(previous)->isOwned(false);
}
return previous;
}
//Introduced in DOM Level 2
int DOMAttrMapImpl::findNamePoint(const XMLCh *namespaceURI,
const XMLCh *localName) const
{
if (fNodes == 0)
return -1;
// This is a linear search through the same fNodes Vector.
// The Vector is sorted on the DOM Level 1 nodename.
// The DOM Level 2 NS keys are namespaceURI and Localname,
// so we must linear search thru it.
// In addition, to get this to work with fNodes without any namespace
// (namespaceURI and localNames are both 0) we then use the nodeName
// as a secondary key.
David N Bertoni
committed
const XMLSize_t len = fNodes -> size();
for (XMLSize_t i = 0; i < len; ++i) {
Alberto Massari
committed
DOMNode *node = fNodes -> elementAt(i);
const XMLCh * nNamespaceURI = node->getNamespaceURI();
const XMLCh * nLocalName = node->getLocalName();
if (!XMLString::equals(nNamespaceURI, namespaceURI)) //URI not match
continue;
else {
if (XMLString::equals(localName, nLocalName)
||
(nLocalName == 0 && XMLString::equals(localName, node->getNodeName())))
David N Bertoni
committed
return (int)i;
Alberto Massari
committed
}
}
return -1; //not found
}
DOMNode *DOMAttrMapImpl::getNamedItemNS(const XMLCh *namespaceURI,
const XMLCh *localName) const
{
int i = findNamePoint(namespaceURI, localName);
return i < 0 ? 0 : fNodes -> elementAt(i);
}
DOMNode *DOMAttrMapImpl::setNamedItemNS(DOMNode* arg)
{
if (arg->getNodeType() != DOMNode::ATTRIBUTE_NODE)
throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
DOMDocument *doc = fOwnerNode->getOwnerDocument();
DOMNodeImpl *argImpl = castToNodeImpl(arg);
if (argImpl->getOwnerDocument() != doc)
throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
if (this->readOnly())
throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
if (argImpl->isOwned())
throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
argImpl->fOwnerNode = fOwnerNode;
argImpl->isOwned(true);
int i=findNamePoint(arg->getNamespaceURI(), arg->getLocalName());
DOMNode *previous=0;
if(i>=0) {
previous = fNodes->elementAt(i);
fNodes->setElementAt(arg,i);
} else {
i=findNamePoint(arg->getNodeName()); // Insert point (may be end of list)
if (i<0)
i = -1 - i;
if(0==fNodes)
fNodes=new ((DOMDocumentImpl*)doc) DOMNodeVector(doc);
Alberto Massari
committed
fNodes->insertElementAt(arg,i);
}
if (previous != 0) {
Boris Kolpackov
committed
castToNodeImpl(previous)->fOwnerNode = doc;
Alberto Massari
committed
castToNodeImpl(previous)->isOwned(false);
}
return previous;
}
DOMNode *DOMAttrMapImpl::removeNamedItem(const XMLCh *name)
{
Alberto Massari
committed
if (this->readOnly())
throw DOMException(
DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
int i=findNamePoint(name);
DOMNode *removed = 0;
if(i<0)
throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
removed = fNodes->elementAt(i);
fNodes->removeElementAt(i);
castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument();
castToNodeImpl(removed)->isOwned(false);
// Replace it if it had a default value
// (DOM spec level 1 - Element Interface)
if (hasDefaults() && (removed != 0))
{
DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes();
DOMAttr* attr = (DOMAttr*)(defAttrs->getNamedItem(name));
if (attr != 0)
{
DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true);
setNamedItem(newAttr);
}
}
}
DOMNode *DOMAttrMapImpl::removeNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName)
{
Alberto Massari
committed
if (this->readOnly())
throw DOMException(
DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
int i = findNamePoint(namespaceURI, localName);
if (i < 0)
throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
DOMNode * removed = fNodes -> elementAt(i);
fNodes -> removeElementAt(i); //remove n from nodes
castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument();
castToNodeImpl(removed)->isOwned(false);
// Replace it if it had a default value
// (DOM spec level 2 - Element Interface)
if (hasDefaults() && (removed != 0))
{
DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes();
DOMAttr* attr = (DOMAttr*)(defAttrs->getNamedItemNS(namespaceURI, localName));
if (attr != 0)
{
DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true);
setNamedItemNS(newAttr);
}
}
}
// remove the name using index
// avoid calling findNamePoint again if the index is already known
Boris Kolpackov
committed
DOMNode * DOMAttrMapImpl::removeNamedItemAt(XMLSize_t index)
Alberto Massari
committed
if (this->readOnly())
throw DOMException(
DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
DOMNode *removed = item(index);
if(!removed)
throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
fNodes->removeElementAt(index);
castToNodeImpl(removed)->fOwnerNode = fOwnerNode->getOwnerDocument();
castToNodeImpl(removed)->isOwned(false);
// Replace it if it had a default value
// (DOM spec level 1 - Element Interface)
if (hasDefaults() && (removed != 0))
{
DOMAttrMapImpl* defAttrs = ((DOMElementImpl*)fOwnerNode)->getDefaultAttributes();
const XMLCh* localName = removed->getLocalName();
DOMAttr* attr = 0;
if (localName)
attr = (DOMAttr*)(defAttrs->getNamedItemNS(removed->getNamespaceURI(), localName));
else
attr = (DOMAttr*)(defAttrs->getNamedItem(((DOMAttr*)removed)->getName()));
if (attr != 0)
{
DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true);
setNamedItem(newAttr);
}
}
return removed;
}
/**
* Get this AttributeMap in sync with the given "defaults" map.
* @param defaults The default attributes map to sync with.
*/
void DOMAttrMapImpl::reconcileDefaultAttributes(const DOMAttrMapImpl* defaults) {
// remove any existing default
XMLSize_t nsize = getLength();
for (XMLSize_t i = nsize; i > 0; i--) {
DOMAttr* attr = (DOMAttr*)item(i-1);
}
}
hasDefaults(false);
// add the new defaults
if (defaults) {
hasDefaults(true);
if (nsize == 0) {
cloneContent(defaults);
}
else {
XMLSize_t dsize = defaults->getLength();
for (XMLSize_t n = 0; n < dsize; n++) {
DOMAttr* attr = (DOMAttr*)defaults->item(n);
DOMAttr* newAttr = (DOMAttr*)attr->cloneNode(true);
setNamedItemNS(newAttr);
DOMAttrImpl* newAttrImpl = (DOMAttrImpl*) newAttr;
newAttrImpl->setSpecified(false);
}
}
}
} // reconcileDefaults()
/**
* Move specified attributes from the given map to this one
*/
void DOMAttrMapImpl::moveSpecifiedAttributes(DOMAttrMapImpl* srcmap) {
XMLSize_t nsize = srcmap->getLength();
for (XMLSize_t i = nsize; i > 0; i--) {
DOMAttr* attr = (DOMAttr*)srcmap->item(i-1);
srcmap->removeNamedItemAt(i-1);
}
if (attr->getLocalName())
setNamedItemNS(attr);
else
setNamedItem(attr);
}
} // moveSpecifiedAttributes(AttributeMap):void
Boris Kolpackov
committed
XMLSize_t DOMAttrMapImpl::getLength() const
Alberto Massari
committed
{
return (fNodes != 0) ? fNodes->size() : 0;
}
Boris Kolpackov
committed
DOMNode * DOMAttrMapImpl::item(XMLSize_t index) const
Alberto Massari
committed
{
return (fNodes != 0 && index < fNodes->size()) ?
fNodes->elementAt(index) : 0;
}
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
void DOMAttrMapImpl::setNamedItemFast(DOMNode *arg)
{
DOMNodeImpl *argImpl = castToNodeImpl(arg);
argImpl->fOwnerNode = fOwnerNode;
argImpl->isOwned(true);
int i = findNamePoint(arg->getNodeName());
if(i >= 0)
fNodes->setElementAt(arg, i);
else
{
i= -1 -i;
fNodes->insertElementAt(arg, i);
}
}
void DOMAttrMapImpl::setNamedItemNSFast(DOMNode* arg)
{
DOMNodeImpl *argImpl = castToNodeImpl(arg);
argImpl->fOwnerNode = fOwnerNode;
argImpl->isOwned(true);
int i=findNamePoint(arg->getNamespaceURI(), arg->getLocalName());
if(i >= 0)
{
fNodes->setElementAt(arg,i);
}
else
{
i = findNamePoint(arg->getNodeName());
if (i < 0)
i = -1 - i;
fNodes->insertElementAt(arg,i);
}
}
void DOMAttrMapImpl::reserve (XMLSize_t n)
{
if (fNodes == 0)
{
DOMDocumentImpl* doc = (DOMDocumentImpl*)fOwnerNode->getOwnerDocument();
fNodes = new (doc) DOMNodeVector(doc, n);
}
}
Alberto Massari
committed