GME  13
DOMAttrNSImpl.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  * $Id: DOMAttrNSImpl.cpp 901107 2010-01-20 08:45:02Z borisk $
00020  */
00021 
00022 #include <xercesc/util/XMLUniDefs.hpp>
00023 #include "DOMAttrNSImpl.hpp"
00024 #include "DOMDocumentImpl.hpp"
00025 #include <xercesc/dom/DOMDocument.hpp>
00026 #include <xercesc/dom/DOMElement.hpp>
00027 #include <xercesc/dom/DOMException.hpp>
00028 
00029 #include "assert.h"
00030 
00031 XERCES_CPP_NAMESPACE_BEGIN
00032 
00033 DOMAttrNSImpl::DOMAttrNSImpl(DOMDocument *ownerDoc, const XMLCh *nam) :
00034 DOMAttrImpl(ownerDoc, nam)
00035 {
00036     this->fNamespaceURI=0;      //DOM Level 2
00037     this->fLocalName=0;       //DOM Level 2
00038     this->fPrefix=0;
00039 }
00040 
00041 //Introduced in DOM Level 2
00042 DOMAttrNSImpl::DOMAttrNSImpl(DOMDocument *ownerDoc,
00043                            const XMLCh *namespaceURI,
00044                            const XMLCh *qualifiedName) :
00045 DOMAttrImpl(ownerDoc, qualifiedName)
00046 {
00047     setName(namespaceURI, qualifiedName);
00048 }
00049 
00050 DOMAttrNSImpl::
00051 DOMAttrNSImpl(DOMDocument *ownerDoc,
00052               const XMLCh *namespaceURI,
00053               const XMLCh *prefix,
00054               const XMLCh *localName,
00055               const XMLCh *qualifiedName)
00056     : DOMAttrImpl(ownerDoc, qualifiedName)
00057 {
00058   DOMDocumentImpl* docImpl = (DOMDocumentImpl*)fParent.fOwnerDocument;
00059 
00060   if (prefix == 0 || *prefix == 0)
00061   {
00062     fPrefix = 0;
00063     fLocalName = fName;
00064   }
00065   else
00066   {
00067     fPrefix = docImpl->getPooledString(prefix);
00068     fLocalName = docImpl->getPooledString(localName);
00069   }
00070 
00071   // DOM Level 3: namespace URI is never empty string.
00072   //
00073   const XMLCh * URI = DOMNodeImpl::mapPrefix
00074     (
00075       fPrefix,
00076       (!namespaceURI || !*namespaceURI) ? 0 : namespaceURI,
00077       DOMNode::ATTRIBUTE_NODE
00078     );
00079   this -> fNamespaceURI = (URI == 0) ? 0 : docImpl->getPooledString(URI);
00080 }
00081 
00082 DOMAttrNSImpl::DOMAttrNSImpl(const DOMAttrNSImpl &other, bool deep) :
00083 DOMAttrImpl(other, deep)
00084 {
00085     this->fNamespaceURI = other.fNamespaceURI;  //DOM Level 2
00086     this->fLocalName = other.fLocalName;          //DOM Level 2
00087     this->fPrefix = other.fPrefix;
00088 }
00089 
00090 DOMNode * DOMAttrNSImpl::cloneNode(bool deep) const
00091 {
00092     DOMNode* newNode = new (fParent.fOwnerDocument, DOMMemoryManager::ATTR_NS_OBJECT) DOMAttrNSImpl(*this, deep);
00093     fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
00094     return newNode;
00095 }
00096 
00097 const XMLCh * DOMAttrNSImpl::getNamespaceURI() const
00098 {
00099     return fNamespaceURI;
00100 }
00101 
00102 const XMLCh * DOMAttrNSImpl::getPrefix() const
00103 {
00104     return fPrefix;
00105 }
00106 
00107 const XMLCh * DOMAttrNSImpl::getLocalName() const
00108 {
00109     return fLocalName;
00110 }
00111 
00112 void DOMAttrNSImpl::setPrefix(const XMLCh *prefix)
00113 {
00114     const XMLCh * xmlns = DOMNodeImpl::getXmlnsString();
00115 
00116     if (fNode.isReadOnly())
00117         throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00118     if (fNamespaceURI == 0 || fNamespaceURI[0] == chNull || XMLString::equals(fLocalName, xmlns))
00119         throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
00120 
00121     if (prefix == 0 || prefix[0] == chNull) {
00122         fName = fLocalName;
00123         fPrefix = 0;
00124         return;
00125     }
00126 
00127     DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument;
00128 
00129     if (!doc->isXMLName(prefix))
00130         throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, GetDOMNodeMemoryManager);
00131 
00132     const XMLCh * xml = DOMNodeImpl::getXmlString();
00133     const XMLCh * xmlURI = DOMNodeImpl::getXmlURIString();
00134     const XMLCh * xmlnsURI = DOMNodeImpl::getXmlnsURIString();
00135 
00136     if ((XMLString::equals(prefix, xml) &&
00137          !XMLString::equals(fNamespaceURI, xmlURI))
00138         || (XMLString::equals(prefix, xmlns) &&
00139             !XMLString::equals(fNamespaceURI, xmlnsURI)))
00140         throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
00141 
00142     if (XMLString::indexOf(prefix, chColon) != -1) {
00143         throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
00144     }
00145 
00146     this-> fPrefix = doc->getPooledString(prefix);
00147 
00148     XMLSize_t prefixLen = XMLString::stringLen(prefix);
00149     XMLSize_t newQualifiedNameLen = prefixLen+1+XMLString::stringLen(fLocalName);
00150     XMLCh* newName;
00151     XMLCh temp[256];
00152     if (newQualifiedNameLen >= 255)
00153         newName = (XMLCh*) doc->getMemoryManager()->allocate
00154         (
00155             newQualifiedNameLen * sizeof(XMLCh)
00156         );//new XMLCh[newQualifiedNameLen];
00157     else
00158         newName = temp;
00159 
00160     // newName = prefix + chColon + fLocalName;
00161     XMLString::copyString(newName, prefix);
00162     newName[prefixLen] = chColon;
00163     XMLString::copyString(&newName[prefixLen+1], fLocalName);
00164 
00165     fName = doc->getPooledString(newName);
00166 
00167     if (newQualifiedNameLen >= 255)
00168       doc->getMemoryManager()->deallocate(newName);//delete[] newName;
00169 
00170 }
00171 
00172 void DOMAttrNSImpl::release()
00173 {
00174     if (fNode.isOwned() && !fNode.isToBeReleased())
00175         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
00176 
00177     DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument;
00178     if (doc) {
00179         fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
00180         fParent.release();
00181         doc->release(this, DOMMemoryManager::ATTR_NS_OBJECT);
00182     }
00183     else {
00184         // shouldn't reach here
00185         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
00186     }
00187 }
00188 
00189 
00190 DOMNode* DOMAttrNSImpl::rename(const XMLCh* namespaceURI, const XMLCh* name)
00191 {
00192     DOMElement* el = getOwnerElement();
00193     if (el)
00194         el->removeAttributeNode(this);
00195 
00196     setName(namespaceURI, name);
00197 
00198     if (el)
00199         el->setAttributeNodeNS(this);
00200 
00201     return this;
00202 }
00203 
00204 void DOMAttrNSImpl::setName(const XMLCh* namespaceURI, const XMLCh* qualifiedName)
00205 {
00206     DOMDocumentImpl* ownerDoc = (DOMDocumentImpl *)fParent.fOwnerDocument;
00207     const XMLCh * xmlns = DOMNodeImpl::getXmlnsString();
00208     const XMLCh * xmlnsURI = DOMNodeImpl::getXmlnsURIString();
00209     this->fName = ownerDoc->getPooledString(qualifiedName);
00210 
00211     int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName);
00212     if (index < 0)
00213         throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
00214 
00215     bool xmlnsAlone = false;    //true if attribute name is "xmlns"
00216     if (index == 0)
00217     {   //qualifiedName contains no ':'
00218         if (XMLString::equals(this->fName, xmlns)) {
00219             if (!XMLString::equals(namespaceURI, xmlnsURI))
00220                 throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
00221             xmlnsAlone = true;
00222         }
00223         fPrefix = 0;
00224         fLocalName = fName;
00225     }
00226     else
00227     {
00228         fPrefix = ownerDoc->getPooledNString(fName, index);
00229         fLocalName = ownerDoc->getPooledString(fName+index+1);
00230 
00231         // Before we carry on, we should check if the prefix or localName are valid XMLName
00232         if (!ownerDoc->isXMLName(fPrefix) || !ownerDoc->isXMLName(fLocalName))
00233             throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
00234     }
00235 
00236     // DOM Level 3: namespace URI is never empty string.
00237     const XMLCh * URI = xmlnsAlone ? xmlnsURI
00238         : DOMNodeImpl::mapPrefix
00239           (
00240               fPrefix,
00241               (!namespaceURI || !*namespaceURI) ? 0 : namespaceURI,
00242               DOMNode::ATTRIBUTE_NODE
00243           );
00244     this -> fNamespaceURI = (URI == 0) ? 0 : ownerDoc->getPooledString(URI);
00245 }
00246 
00247 XERCES_CPP_NAMESPACE_END