Newer
Older
/*
* Copyright 2001-2002,2004 The Apache Software Foundation.
*
* Licensed 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 <xercesc/dom/DOMAttr.hpp>
#include <xercesc/dom/DOMException.hpp>
#include <xercesc/framework/XMLBuffer.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include "DOMNodeVector.hpp"
#include "DOMNamedNodeMapImpl.hpp"
#include "DOMCasts.hpp"
#include "DOMDocumentImpl.hpp"
#include "DOMNodeImpl.hpp"
DOMNamedNodeMapImpl::DOMNamedNodeMapImpl(DOMNode *ownerNod)
{
Alberto Massari
committed
fOwnerNode=ownerNod;
memset(fBuckets,0,MAP_SIZE*sizeof(DOMNodeVector*));
David Abram Cargill
committed
}
DOMNamedNodeMapImpl::~DOMNamedNodeMapImpl()
{
David Abram Cargill
committed
}
Alberto Massari
committed
bool DOMNamedNodeMapImpl::readOnly()
{
return castToNodeImpl(fOwnerNode)->isReadOnly();
}
DOMNamedNodeMapImpl *DOMNamedNodeMapImpl::cloneMap(DOMNode *ownerNod)
{
DOMDocumentImpl *doc = (DOMDocumentImpl *)(castToNodeImpl(ownerNod)->getOwnerDocument());
DOMNamedNodeMapImpl *newmap = new (doc) DOMNamedNodeMapImpl(ownerNod);
Alberto Massari
committed
for(int index=0;index<MAP_SIZE;index++)
if (fBuckets[index] != 0) {
XMLSize_t size=fBuckets[index]->size();
newmap->fBuckets[index] = new (doc) DOMNodeVector(doc, size);
for (XMLSize_t i = 0; i < size; ++i) {
DOMNode *s = fBuckets[index]->elementAt(i);
DOMNode *n = s->cloneNode(true);
castToNodeImpl(n)->isSpecified(castToNodeImpl(s)->isSpecified());
castToNodeImpl(n)->fOwnerNode = ownerNod;
castToNodeImpl(n)->isOwned(true);
newmap->fBuckets[index]->addElement(n);
}
}
return newmap;
David Abram Cargill
committed
}
Alberto Massari
committed
XMLSize_t DOMNamedNodeMapImpl::getLength() const
{
Alberto Massari
committed
XMLSize_t count=0;
for(int index=0;index<MAP_SIZE;index++)
count+=(fBuckets[index]==0?0:fBuckets[index]->size());
return count;
}
Alberto Massari
committed
DOMNode * DOMNamedNodeMapImpl::item(XMLSize_t index) const
{
Alberto Massari
committed
XMLSize_t count=0;
for(XMLSize_t i=0;i<MAP_SIZE;i++) {
if(fBuckets[i]==0)
continue;
XMLSize_t thisBucket=fBuckets[i]->size();
if(index>=count && index<(count+thisBucket))
return fBuckets[i]->elementAt(index-count);
Alberto Massari
committed
count+=thisBucket;
Alberto Massari
committed
return NULL;
David Abram Cargill
committed
}
DOMNode * DOMNamedNodeMapImpl::getNamedItem(const XMLCh *name) const
{
Alberto Massari
committed
unsigned int hash=XMLString::hash(name,MAP_SIZE);
if(fBuckets[hash]==0)
return 0;
Alberto Massari
committed
int i = 0;
int size = fBuckets[hash]->size();
for (i = 0; i < size; ++i) {
DOMNode *n=fBuckets[hash]->elementAt(i);
if(XMLString::equals(name,n->getNodeName()))
return n;
}
Alberto Massari
committed
return 0;
David Abram Cargill
committed
}
//
// removeNamedItem() - Remove the named item, and return it.
// The caller can release the
// returned item if it's not used
// we can't do it here because the caller would
// never see the returned node.
//
DOMNode * DOMNamedNodeMapImpl::removeNamedItem(const XMLCh *name)
{
if (this->readOnly())
throw DOMException(
DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
unsigned int hash=XMLString::hash(name,MAP_SIZE);
if(fBuckets[hash]==0)
throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
int i = 0;
int size = fBuckets[hash]->size();
for (i = 0; i < size; ++i) {
DOMNode *n=fBuckets[hash]->elementAt(i);
if(XMLString::equals(name,n->getNodeName())) {
fBuckets[hash]->removeElementAt(i);
castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
castToNodeImpl(n)->isOwned(false);
return n;
}
}
throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
return 0;
David Abram Cargill
committed
}
//
// setNamedItem() Put the item into the NamedNodeList by name.
// If an item with the same name already was
// in the list, replace it. Return the old
// item, if there was one.
// Caller is responsible for arranging for
// deletion of the old item if its ref count is
// zero.
//
DOMNode * DOMNamedNodeMapImpl::setNamedItem(DOMNode * arg)
{
DOMDocument *doc = fOwnerNode->getOwnerDocument();
DOMNodeImpl *argImpl = castToNodeImpl(arg);
if(argImpl->getOwnerDocument() != doc)
throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
if (this->readOnly())
throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode))
throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);
argImpl->fOwnerNode = fOwnerNode;
argImpl->isOwned(true);
Alberto Massari
committed
const XMLCh* name=arg->getNodeName();
unsigned int hash=XMLString::hash(name,MAP_SIZE);
if(fBuckets[hash]==0)
fBuckets[hash] = new (doc) DOMNodeVector(doc, 3);
int i = 0;
int size = fBuckets[hash]->size();
for (i = 0; i < size; ++i) {
DOMNode *n=fBuckets[hash]->elementAt(i);
if(XMLString::equals(name,n->getNodeName())) {
fBuckets[hash]->setElementAt(arg,i);
castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
castToNodeImpl(n)->isOwned(false);
return n;
}
}
Alberto Massari
committed
fBuckets[hash]->addElement(arg);
return 0;
David Abram Cargill
committed
}
void DOMNamedNodeMapImpl::setReadOnly(bool readOnl, bool deep)
{
// this->fReadOnly=readOnl;
Alberto Massari
committed
if(deep) {
for (int index = 0; index < MAP_SIZE; index++) {
if(fBuckets[index]==0)
continue;
int sz = fBuckets[index]->size();
for (int i=0; i<sz; ++i)
castToNodeImpl(fBuckets[index]->elementAt(i))->setReadOnly(readOnl, deep);
}
}
David Abram Cargill
committed
}
//Introduced in DOM Level 2
Alberto Massari
committed
DOMNode *DOMNamedNodeMapImpl::getNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName) const
{
Alberto Massari
committed
// the map is indexed using the full name of nodes; to search given a namespace and a local name
// we have to do a linear search
for (int index = 0; index < MAP_SIZE; index++) {
if(fBuckets[index]==0)
Alberto Massari
committed
int i = 0;
int size = fBuckets[index]->size();
for (i = 0; i < size; ++i) {
DOMNode *n=fBuckets[index]->elementAt(i);
const XMLCh * nNamespaceURI = n->getNamespaceURI();
const XMLCh * nLocalName = n->getLocalName();
if (!XMLString::equals(nNamespaceURI, namespaceURI)) //URI not match
continue;
else {
if (XMLString::equals(localName, nLocalName)
||
(nLocalName == 0 && XMLString::equals(localName, n->getNodeName())))
return n;
}
}
}
Alberto Massari
committed
return 0;
}
//
// setNamedItemNS() Put the item into the NamedNodeList by name.
// If an item with the same name already was
// in the list, replace it. Return the old
// item, if there was one.
// Caller is responsible for arranging for
// deletion of the old item if its ref count is
// zero.
//
DOMNode * DOMNamedNodeMapImpl::setNamedItemNS(DOMNode *arg)
{
DOMDocument *doc = fOwnerNode->getOwnerDocument();
DOMNodeImpl *argImpl = castToNodeImpl(arg);
if (argImpl->getOwnerDocument() != doc)
throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
if (this->readOnly())
throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
if (argImpl->isOwned())
throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);
argImpl->fOwnerNode = fOwnerNode;
argImpl->isOwned(true);
Alberto Massari
committed
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
const XMLCh* namespaceURI=arg->getNamespaceURI();
const XMLCh* localName=arg->getLocalName();
// the map is indexed using the full name of nodes; to search given a namespace and a local name
// we have to do a linear search
for (int index = 0; index < MAP_SIZE; index++) {
if(fBuckets[index]==0)
continue;
int i = 0;
int size = fBuckets[index]->size();
for (i = 0; i < size; ++i) {
DOMNode *n=fBuckets[index]->elementAt(i);
const XMLCh * nNamespaceURI = n->getNamespaceURI();
const XMLCh * nLocalName = n->getLocalName();
if (!XMLString::equals(nNamespaceURI, namespaceURI)) //URI not match
continue;
else {
if (XMLString::equals(localName, nLocalName)
||
(nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) {
fBuckets[index]->setElementAt(arg,i);
castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
castToNodeImpl(n)->isOwned(false);
return n;
}
}
}
}
// if not found, add it using the full name as key
return setNamedItem(arg);
David Abram Cargill
committed
}
// removeNamedItemNS() - Remove the named item, and return it.
// The caller can release the
// returned item if it's not used
// we can't do it here because the caller would
// never see the returned node.
DOMNode *DOMNamedNodeMapImpl::removeNamedItemNS(const XMLCh *namespaceURI,
const XMLCh *localName)
{
if (this->readOnly())
throw DOMException(
DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
// the map is indexed using the full name of nodes; to search given a namespace and a local name
// we have to do a linear search
for (int index = 0; index < MAP_SIZE; index++) {
if(fBuckets[index]==0)
continue;
Alberto Massari
committed
int i = 0;
int size = fBuckets[index]->size();
for (i = 0; i < size; ++i) {
DOMNode *n=fBuckets[index]->elementAt(i);
const XMLCh * nNamespaceURI = n->getNamespaceURI();
const XMLCh * nLocalName = n->getLocalName();
if (!XMLString::equals(nNamespaceURI, namespaceURI)) //URI not match
continue;
else {
if (XMLString::equals(localName, nLocalName)
||
(nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) {
fBuckets[index]->removeElementAt(i);
castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument();
castToNodeImpl(n)->isOwned(false);
return n;
}
Tinny Ng
committed
}
}
throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
Alberto Massari
committed
return 0;
David Abram Cargill
committed
}