GME  13
DOMAttrImpl.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: DOMAttrImpl.cpp 678709 2008-07-22 10:56:56Z borisk $
00020  */
00021 
00022 #include <xercesc/dom/DOMDocument.hpp>
00023 #include <xercesc/dom/DOMException.hpp>
00024 
00025 #include "DOMAttrImpl.hpp"
00026 #include "DOMStringPool.hpp"
00027 #include "DOMDocumentImpl.hpp"
00028 #include "DOMCasts.hpp"
00029 #include "DOMTypeInfoImpl.hpp"
00030 
00031 XERCES_CPP_NAMESPACE_BEGIN
00032 
00033 DOMAttrImpl::DOMAttrImpl(DOMDocument *ownerDoc, const XMLCh *aName)
00034     : fNode(ownerDoc), fParent (ownerDoc), fSchemaType(0)
00035 {
00036     DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc;
00037     fName = docImpl->getPooledString(aName);
00038     fNode.isSpecified(true);
00039 }
00040 
00041 DOMAttrImpl::DOMAttrImpl(const DOMAttrImpl &other, bool /*deep*/)
00042     : DOMAttr(other)
00043     , fNode(other.fNode)
00044     , fParent (other.fParent)
00045     , fName(other.fName)
00046     , fSchemaType(other.fSchemaType)
00047 {
00048     if (other.fNode.isSpecified())
00049         fNode.isSpecified(true);
00050     else
00051         fNode.isSpecified(false);
00052 
00053     if (other.fNode.isIdAttr())
00054     {
00055         fNode.isIdAttr(true);
00056         DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
00057         doc->getNodeIDMap()->add(this);
00058     }
00059 
00060     fParent.cloneChildren(&other);
00061 }
00062 
00063 
00064 DOMAttrImpl::~DOMAttrImpl() {
00065 }
00066 
00067 
00068 DOMNode * DOMAttrImpl::cloneNode(bool deep) const
00069 {
00070     DOMNode* newNode = new (fParent.fOwnerDocument, DOMDocumentImpl::ATTR_OBJECT) DOMAttrImpl(*this, deep);
00071     fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
00072     return newNode;
00073 }
00074 
00075 
00076 const XMLCh * DOMAttrImpl::getNodeName()  const{
00077     return fName;
00078 }
00079 
00080 DOMNode::NodeType DOMAttrImpl::getNodeType() const {
00081     return DOMNode::ATTRIBUTE_NODE;
00082 }
00083 
00084 
00085 const XMLCh * DOMAttrImpl::getName() const {
00086     return fName;
00087 }
00088 
00089 
00090 const XMLCh * DOMAttrImpl::getNodeValue() const
00091 {
00092     return getValue();
00093 }
00094 
00095 
00096 bool DOMAttrImpl::getSpecified() const
00097 {
00098     return fNode.isSpecified();
00099 }
00100 
00101 
00102 
00103 
00104 const XMLCh * DOMAttrImpl::getValue() const
00105 {
00106     if (fParent.fFirstChild == 0) {
00107         return XMLUni::fgZeroLenString; // return "";
00108     }
00109 
00110     // Simple case where attribute value is just a single text node
00111     DOMNode *node = castToChildImpl(fParent.fFirstChild)->nextSibling;
00112     if (node == 0 && fParent.fFirstChild->getNodeType() == DOMNode::TEXT_NODE) {
00113         return fParent.fFirstChild->getNodeValue();
00114     }
00115 
00116     //
00117     // Complicated case where attribute value is a DOM tree
00118     //
00119     // According to the spec, the child nodes of the Attr node may be either
00120     // Text or EntityReference nodes.
00121     //
00122     // The parser will not create such thing, this is for those created by users.
00123     //
00124     // In such case, we have to visit each child to retrieve the text
00125     //
00126 
00127     DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument;
00128 
00129     XMLBuffer buf(1023, doc->getMemoryManager());
00130     for (node = fParent.fFirstChild; node != 0; node = castToChildImpl(node)->nextSibling)
00131         getTextValue(node, buf);
00132 
00133     return doc->getPooledString(buf.getRawBuffer());
00134 }
00135 
00136 void DOMAttrImpl::getTextValue(DOMNode* node, XMLBuffer& buf) const
00137 {
00138     if (node->getNodeType() == DOMNode::TEXT_NODE)
00139         buf.append(node->getNodeValue());
00140     else if (node->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE)
00141     {
00142         for (node = node->getFirstChild(); node != 0; node = castToChildImpl(node)->nextSibling)
00143         {
00144             getTextValue(node, buf);
00145         }
00146     }
00147 
00148     return;
00149 }
00150 
00151 
00152 void DOMAttrImpl::setNodeValue(const XMLCh *val)
00153 {
00154     setValue(val);
00155 }
00156 
00157 
00158 
00159 void DOMAttrImpl::setSpecified(bool arg)
00160 {
00161     fNode.isSpecified(arg);
00162 }
00163 
00164 
00165 
00166 void DOMAttrImpl::setValue(const XMLCh *val)
00167 {
00168     if (fNode.isReadOnly())
00169     {
00170         throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00171     }
00172 
00173     //  If this attribute was of type ID and in the map, take it out,
00174     //    then put it back in with the new name.  For now, we don't worry
00175     //    about what happens if the new name conflicts
00176     //
00177     DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
00178     if (fNode.isIdAttr())
00179         doc->getNodeIDMap()->remove(this);
00180 
00181     DOMNode *kid;
00182     while ((kid = fParent.fFirstChild) != 0)         // Remove existing kids
00183     {
00184         DOMNode* node = removeChild(kid);
00185         if (node)
00186             node->release();
00187     }
00188 
00189     if (val != 0)              // Create and add the new one
00190         fParent.appendChildFast(doc->createTextNode(val));
00191     fNode.isSpecified(true);
00192     fParent.changed();
00193 
00194     if (fNode.isIdAttr())
00195         doc->getNodeIDMap()->add(this);
00196 
00197 }
00198 
00199 void DOMAttrImpl::setValueFast(const XMLCh *val)
00200 {
00201     if (val != 0)
00202       fParent.appendChildFast(fParent.fOwnerDocument->createTextNode(val));
00203 
00204     fNode.isSpecified (true);
00205 }
00206 
00207 
00208 
00209 //Introduced in DOM Level 2
00210 
00211 DOMElement *DOMAttrImpl::getOwnerElement() const
00212 {
00213     // if we have an owner, ownerNode is our ownerElement, otherwise it's
00214     // our ownerDocument and we don't have an ownerElement
00215     return (DOMElement *) (fNode.isOwned() ? fNode.fOwnerNode : 0);
00216 }
00217 
00218 
00219 //internal use by parser only
00220 void DOMAttrImpl::setOwnerElement(DOMElement *ownerElem)
00221 {
00222     fNode.fOwnerNode = ownerElem;
00223     // revisit.  Is this backwards?  isOwned(true)?
00224     fNode.isOwned(false);
00225 }
00226 
00227 
00228 //For DOM Level 3
00229 
00230 void DOMAttrImpl::release()
00231 {
00232     if (fNode.isOwned() && !fNode.isToBeReleased())
00233         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
00234 
00235     DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument;
00236     if (doc) {
00237         fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
00238         fParent.release();
00239         doc->release(this, DOMMemoryManager::ATTR_OBJECT);
00240     }
00241     else {
00242         // shouldn't reach here
00243         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
00244     }
00245 }
00246 
00247 
00248 bool DOMAttrImpl::isId() const {
00249     return fNode.isIdAttr();
00250 }
00251 
00252 
00253 DOMNode* DOMAttrImpl::rename(const XMLCh* namespaceURI, const XMLCh* name)
00254 {
00255     DOMElement* el = getOwnerElement();
00256     DOMDocumentImpl* doc = (DOMDocumentImpl*)fParent.fOwnerDocument;
00257 
00258     if (el)
00259         el->removeAttributeNode(this);
00260 
00261     if (!namespaceURI || !*namespaceURI) {
00262         fName = doc->getPooledString(name);
00263 
00264         if (el)
00265             el->setAttributeNode(this);
00266 
00267         // and fire user data NODE_RENAMED event
00268         castToNodeImpl(this)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, this);
00269 
00270         return this;
00271     }
00272     else {
00273 
00274         // create a new AttrNS
00275         DOMAttr* newAttr = doc->createAttributeNS(namespaceURI, name);
00276 
00277         // transfer the userData
00278         doc->transferUserData(castToNodeImpl(this), castToNodeImpl(newAttr));
00279 
00280         // move children to new node
00281         DOMNode* child = getFirstChild();
00282         while (child) {
00283             removeChild(child);
00284             newAttr->appendChild(child);
00285             child = getFirstChild();
00286         }
00287 
00288         // reattach attr to element
00289         if (el)
00290             el->setAttributeNodeNS(newAttr);
00291 
00292         // and fire user data NODE_RENAMED event
00293         castToNodeImpl(newAttr)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, newAttr);
00294 
00295         return newAttr;
00296     }
00297 }
00298 
00299 const DOMTypeInfo *DOMAttrImpl::getSchemaTypeInfo() const
00300 {
00301     if(!fSchemaType)
00302         return &DOMTypeInfoImpl::g_DtdNotValidatedAttribute;
00303 
00304     return fSchemaType;
00305 }
00306 
00307 
00308 void DOMAttrImpl::setSchemaTypeInfo(const DOMTypeInfoImpl* typeInfo)
00309 {
00310     fSchemaType = typeInfo;
00311 }
00312 
00313 bool DOMAttrImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
00314 {
00315     // check for '+DOMPSVITypeInfo'
00316     if(feature && *feature=='+' && XMLString::equals(feature+1, XMLUni::fgXercescInterfacePSVITypeInfo))
00317         return true;
00318     return fNode.isSupported (feature, version);
00319 }
00320 
00321 void* DOMAttrImpl::getFeature(const XMLCh* feature, const XMLCh* version) const
00322 {
00323     if(XMLString::equals(feature, XMLUni::fgXercescInterfacePSVITypeInfo))
00324         return (DOMPSVITypeInfo*)fSchemaType;
00325     return fNode.getFeature(feature, version);
00326 }
00327 
00328            DOMNode*         DOMAttrImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); }
00329            DOMNamedNodeMap* DOMAttrImpl::getAttributes() const                   {return fNode.getAttributes (); }
00330            DOMNodeList*     DOMAttrImpl::getChildNodes() const                   {return fParent.getChildNodes (); }
00331            DOMNode*         DOMAttrImpl::getFirstChild() const                   {return fParent.getFirstChild (); }
00332            DOMNode*         DOMAttrImpl::getLastChild() const                    {return fParent.getLastChild (); }
00333      const XMLCh*           DOMAttrImpl::getLocalName() const                    {return fNode.getLocalName (); }
00334      const XMLCh*           DOMAttrImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); }
00335            DOMNode*         DOMAttrImpl::getNextSibling() const                  {return fNode.getNextSibling (); }
00336            DOMDocument*     DOMAttrImpl::getOwnerDocument() const                {return fParent.fOwnerDocument; }
00337      const XMLCh*           DOMAttrImpl::getPrefix() const                       {return fNode.getPrefix (); }
00338            DOMNode*         DOMAttrImpl::getParentNode() const                   {return fNode.getParentNode (); }
00339            DOMNode*         DOMAttrImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); }
00340            bool             DOMAttrImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); }
00341            DOMNode*         DOMAttrImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
00342                                                                                  {return fParent.insertBefore (newChild, refChild); }
00343            void             DOMAttrImpl::normalize()                             {fParent.normalize (); }
00344            DOMNode*         DOMAttrImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); }
00345            DOMNode*         DOMAttrImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
00346                                                                                  {return fParent.replaceChild (newChild, oldChild); }
00347            void             DOMAttrImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); }
00348            bool             DOMAttrImpl::hasAttributes() const                   {return fNode.hasAttributes(); }
00349            bool             DOMAttrImpl::isSameNode(const DOMNode* other) const  {return fNode.isSameNode(other); }
00350            bool             DOMAttrImpl::isEqualNode(const DOMNode* arg) const   {return fParent.isEqualNode(arg); }
00351            void*            DOMAttrImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
00352                                                                                  {return fNode.setUserData(key, data, handler); }
00353            void*            DOMAttrImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); }
00354            const XMLCh*     DOMAttrImpl::getBaseURI() const                      {return fNode.getBaseURI(); }
00355            short            DOMAttrImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); }
00356            const XMLCh*     DOMAttrImpl::getTextContent() const                  {return fNode.getTextContent(); }
00357            void             DOMAttrImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
00358            const XMLCh*     DOMAttrImpl::lookupPrefix(const XMLCh* namespaceURI) const  {return fNode.lookupPrefix(namespaceURI); }
00359            bool             DOMAttrImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
00360            const XMLCh*     DOMAttrImpl::lookupNamespaceURI(const XMLCh* prefix) const  {return fNode.lookupNamespaceURI(prefix); }
00361 
00362 XERCES_CPP_NAMESPACE_END