GME  13
DOMNodeImpl.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: DOMNodeImpl.cpp 673428 2008-07-02 16:00:35Z amassari $
00020  */
00021 
00022 // This class doesn't support having any children, and implements the behavior
00023 // of an empty NodeList as far getChildNodes is concerned.
00024 // The ParentNode subclass overrides this behavior.
00025 
00026 
00027 #include "DOMCasts.hpp"
00028 
00029 #include "DOMDocumentTypeImpl.hpp"
00030 #include "DOMElementImpl.hpp"
00031 #include "DOMAttrImpl.hpp"
00032 
00033 #include <xercesc/dom/DOMImplementation.hpp>
00034 #include <xercesc/dom/DOMException.hpp>
00035 
00036 #include <xercesc/util/XMLUniDefs.hpp>
00037 #include <xercesc/util/PlatformUtils.hpp>
00038 #include <xercesc/util/XMLInitializer.hpp>
00039 #include <stdio.h>
00040 #include <assert.h>
00041 
00042 XERCES_CPP_NAMESPACE_BEGIN
00043 
00044 //Though DOMNodeImpl does not derivate from DOMNode, it shares
00045 //the same GetDOMNodeMemoryManager
00046 
00047 const unsigned short DOMNodeImpl::READONLY     = 0x1<<0;
00048 const unsigned short DOMNodeImpl::SYNCDATA     = 0x1<<1;
00049 const unsigned short DOMNodeImpl::SYNCCHILDREN = 0x1<<2;
00050 const unsigned short DOMNodeImpl::OWNED        = 0x1<<3;
00051 const unsigned short DOMNodeImpl::FIRSTCHILD   = 0x1<<4;
00052 const unsigned short DOMNodeImpl::SPECIFIED    = 0x1<<5;
00053 const unsigned short DOMNodeImpl::IGNORABLEWS  = 0x1<<6;
00054 const unsigned short DOMNodeImpl::SETVALUE     = 0x1<<7;
00055 const unsigned short DOMNodeImpl::ID_ATTR      = 0x1<<8;
00056 const unsigned short DOMNodeImpl::USERDATA     = 0x1<<9;
00057 const unsigned short DOMNodeImpl::LEAFNODETYPE = 0x1<<10;
00058 const unsigned short DOMNodeImpl::CHILDNODE    = 0x1<<11;
00059 const unsigned short DOMNodeImpl::TOBERELEASED = 0x1<<12;
00060 
00061 //
00062 //
00063 static DOMNodeListImpl *gEmptyNodeList = 0; // Singleton empty node list.
00064 
00065 void XMLInitializer::initializeDOMNodeListImpl()
00066 {
00067     gEmptyNodeList = new DOMNodeListImpl(0);
00068 }
00069 
00070 void XMLInitializer::terminateDOMNodeListImpl()
00071 {
00072     delete gEmptyNodeList;
00073     gEmptyNodeList = 0;
00074 }
00075 
00076 // -----------------------------------------------------------------------
00077 //  DOMNodeImpl Functions
00078 // -----------------------------------------------------------------------
00079 DOMNodeImpl::DOMNodeImpl(DOMNode *ownerNode)
00080 :  fOwnerNode(ownerNode)
00081 {
00082     this->flags = 0;
00083     // as long as we do not have any owner, fOwnerNode is our ownerDocument
00084 }
00085 
00086 // This only makes a shallow copy, cloneChildren must also be called for a
00087 // deep clone
00088 DOMNodeImpl::DOMNodeImpl(const DOMNodeImpl &other)
00089 {
00090     this->flags = other.flags;
00091     this->isReadOnly(false);
00092 
00093     // Need to break the association w/ original parent
00094     this->fOwnerNode = other.getOwnerDocument();
00095     this->isOwned(false);
00096 }
00097 
00098 
00099 
00100 DOMNodeImpl::~DOMNodeImpl() {
00101 }
00102 
00103 
00104 DOMNode * DOMNodeImpl::appendChild(DOMNode *)
00105 {
00106     // Only node types that don't allow children will use this default function.
00107     //   Others will go to DOMParentNode::appendChild.
00108     throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMNodeMemoryManager);
00109     return 0;
00110     //  return insertBefore(newChild, 0);
00111 }
00112 
00113 
00114 DOMNamedNodeMap * DOMNodeImpl::getAttributes() const {
00115     return 0;                   // overridden in ElementImpl
00116 }
00117 
00118 
00119 DOMNodeList *DOMNodeImpl::getChildNodes() const {
00120     return gEmptyNodeList;
00121 }
00122 
00123 
00124 
00125 DOMNode * DOMNodeImpl::getFirstChild() const {
00126     return 0;                   // overridden in ParentNode
00127 }
00128 
00129 
00130 DOMNode * DOMNodeImpl::getLastChild() const
00131 {
00132     return 0;                   // overridden in ParentNode
00133 }
00134 
00135 
00136 DOMNode * DOMNodeImpl::getNextSibling() const {
00137     return 0;                // overridden in ChildNode
00138 }
00139 
00140 
00141 const XMLCh * DOMNodeImpl::getNodeValue() const {
00142     return 0;                    // Overridden by anything that has a value
00143 }
00144 
00145 
00146 //
00147 //  Unlike the external getOwnerDocument, this one returns the owner document
00148 //     for document nodes as well as all of the other node types.
00149 //
00150 DOMDocument *DOMNodeImpl::getOwnerDocument() const
00151 {
00152     if (!this->isLeafNode())
00153     {
00154         DOMElementImpl *ep = (DOMElementImpl *)castToNode(this);
00155         return ep->fParent.fOwnerDocument;
00156     }
00157 
00158     //  Leaf node types - those that cannot have children, like Text.
00159     if (isOwned()) {
00160 
00161         DOMDocument* ownerDoc = fOwnerNode->getOwnerDocument();
00162 
00163         if (!ownerDoc) {
00164 
00165             assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE);
00166             return  (DOMDocument *)fOwnerNode;
00167         }
00168         else {
00169             return ownerDoc;
00170         }
00171     } else {
00172         assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE);
00173         return  (DOMDocument *)fOwnerNode;
00174     }
00175 }
00176 
00177 
00178 void DOMNodeImpl::setOwnerDocument(DOMDocument *doc) {
00179     // if we have an owner we rely on it to have it right
00180     // otherwise fOwnerNode is our ownerDocument
00181     if (!isOwned()) {
00182         // revisit.  Problem with storage for doctype nodes that were created
00183         //                on the system heap in advance of having a document.
00184         fOwnerNode = doc;
00185     }
00186 }
00187 
00188 DOMNode * DOMNodeImpl::getParentNode() const
00189 {
00190     return 0;                // overridden in ChildNode
00191 }
00192 
00193 
00194 DOMNode*  DOMNodeImpl::getPreviousSibling() const
00195 {
00196     return 0;                // overridden in ChildNode
00197 }
00198 
00199 bool DOMNodeImpl::hasChildNodes() const
00200 {
00201     return false;
00202 }
00203 
00204 
00205 
00206 DOMNode *DOMNodeImpl::insertBefore(DOMNode *, DOMNode *) {
00207     throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNodeMemoryManager);
00208     return 0;
00209 }
00210 
00211 
00212 DOMNode *DOMNodeImpl::removeChild(DOMNode *)
00213 {
00214     throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
00215     return 0;
00216 }
00217 
00218 
00219 DOMNode *DOMNodeImpl::replaceChild(DOMNode *, DOMNode *)
00220 {
00221     throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMNodeMemoryManager);
00222     return 0;
00223 }
00224 
00225 
00226 
00227 void DOMNodeImpl::setNodeValue(const XMLCh *)
00228 {
00229     // Default behavior is to do nothing, overridden in some subclasses
00230 }
00231 
00232 
00233 
00234 void DOMNodeImpl::setReadOnly(bool readOnl, bool deep)
00235 {
00236     this->isReadOnly(readOnl);
00237 
00238     if (deep) {
00239         for (DOMNode *mykid = castToNode(this)->getFirstChild();
00240             mykid != 0;
00241             mykid = mykid->getNextSibling()) {
00242 
00243             short kidNodeType = mykid->getNodeType();
00244 
00245             switch (kidNodeType) {
00246             case DOMNode::ENTITY_REFERENCE_NODE:
00247                 break;
00248             case DOMNode::ELEMENT_NODE:
00249                 ((DOMElementImpl*) mykid)->setReadOnly(readOnl, true);
00250                 break;
00251             case DOMNode::DOCUMENT_TYPE_NODE:
00252                ((DOMDocumentTypeImpl*) mykid)->setReadOnly(readOnl, true);
00253                break;
00254             default:
00255                 castToNodeImpl(mykid)->setReadOnly(readOnl, true);
00256                 break;
00257             }
00258         }
00259     }
00260 }
00261 
00262 
00263 //Introduced in DOM Level 2
00264 
00265 void DOMNodeImpl::normalize()
00266 {
00267     // does nothing by default, overridden by subclasses
00268 }
00269 
00270 
00271 bool DOMNodeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
00272 {
00273     return DOMImplementation::getImplementation()->hasFeature(feature, version);
00274 }
00275 
00276 const XMLCh *DOMNodeImpl::getNamespaceURI() const
00277 {
00278     return 0;
00279 }
00280 
00281 const XMLCh *DOMNodeImpl::getPrefix() const
00282 {
00283     return 0;
00284 }
00285 
00286 const XMLCh *DOMNodeImpl::getLocalName() const
00287 {
00288     return 0;
00289 }
00290 
00291 
00292 void DOMNodeImpl::setPrefix(const XMLCh *)
00293 {
00294     throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
00295 }
00296 
00297 
00298 bool DOMNodeImpl::hasAttributes() const {
00299     return 0;                   // overridden in ElementImpl
00300 }
00301 
00302 
00303 
00304 
00305 
00306 const XMLCh *DOMNodeImpl::getXmlString()      {return XMLUni::fgXMLString;}
00307 const XMLCh *DOMNodeImpl::getXmlURIString()   {return XMLUni::fgXMLURIName;}
00308 const XMLCh *DOMNodeImpl::getXmlnsString()    {return XMLUni::fgXMLNSString;}
00309 const XMLCh *DOMNodeImpl::getXmlnsURIString() {return XMLUni::fgXMLNSURIName;}
00310 
00311 //Return a URI mapped from the given prefix and namespaceURI as below
00312 //    prefix   namespaceURI    output
00313 //---------------------------------------------------
00314 //    "xml"     xmlURI          xmlURI
00315 //    "xml"     otherwise       NAMESPACE_ERR
00316 //    "xmlns"   xmlnsURI        xmlnsURI (nType = ATTRIBUTE_NODE only)
00317 //    "xmlns"   otherwise       NAMESPACE_ERR (nType = ATTRIBUTE_NODE only)
00318 //    != null   null or ""      NAMESPACE_ERR
00319 //    else      any             namesapceURI
00320 const XMLCh* DOMNodeImpl::mapPrefix(const XMLCh *prefix,
00321                                      const XMLCh *namespaceURI, short nType)
00322 {
00323     if (prefix == 0)
00324         return namespaceURI;
00325 
00326     if (XMLString::equals(prefix, XMLUni::fgXMLString))  {
00327         if (XMLString::equals(namespaceURI, XMLUni::fgXMLURIName))
00328             return XMLUni::fgXMLURIName;
00329         throw DOMException(DOMException::NAMESPACE_ERR, 0);
00330     } else if (nType == DOMNode::ATTRIBUTE_NODE && XMLString::equals(prefix, XMLUni::fgXMLNSString)) {
00331         if (XMLString::equals(namespaceURI, XMLUni::fgXMLNSURIName))
00332             return XMLUni::fgXMLNSURIName;
00333         throw DOMException(DOMException::NAMESPACE_ERR, 0);
00334     } else if (namespaceURI == 0 || *namespaceURI == 0)
00335         throw DOMException(DOMException::NAMESPACE_ERR, 0);
00336     return namespaceURI;
00337 }
00338 
00339 //Introduced in DOM Level 3
00340 void* DOMNodeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
00341 {
00342    if (!data && !hasUserData())
00343        return 0;
00344 
00345     hasUserData(true);
00346     return ((DOMDocumentImpl*)getOwnerDocument())->setUserData(this, key, data, handler);
00347 }
00348 
00349 void* DOMNodeImpl::getUserData(const XMLCh* key) const
00350 {
00351    if (hasUserData())
00352        return ((DOMDocumentImpl*)getOwnerDocument())->getUserData(this, key);
00353     return 0;
00354 }
00355 
00356 void DOMNodeImpl::callUserDataHandlers(DOMUserDataHandler::DOMOperationType operation,
00357                                        const DOMNode* src,
00358                                        DOMNode* dst) const
00359 {
00360     DOMDocumentImpl* doc=(DOMDocumentImpl*)getOwnerDocument();
00361     if (doc)
00362         doc->callUserDataHandlers(this, operation, src, dst);
00363 }
00364 
00365 bool DOMNodeImpl::isSameNode(const DOMNode* other) const
00366 {
00367     return (castToNode(this) == other);
00368 }
00369 
00370 bool DOMNodeImpl::isEqualNode(const DOMNode* arg) const
00371 {
00372     if (!arg)
00373         return false;
00374 
00375     if (isSameNode(arg)) {
00376         return true;
00377     }
00378 
00379     DOMNode* thisNode = castToNode(this);
00380 
00381     if (arg->getNodeType() != thisNode->getNodeType()) {
00382         return false;
00383     }
00384 
00385     // the compareString will check null string as well
00386     if (!XMLString::equals(thisNode->getNodeName(), arg->getNodeName())) {
00387         return false;
00388     }
00389 
00390     if (!XMLString::equals(thisNode->getLocalName(),arg->getLocalName())) {
00391         return false;
00392     }
00393 
00394     if (!XMLString::equals(thisNode->getNamespaceURI(), arg->getNamespaceURI())) {
00395         return false;
00396     }
00397 
00398     if (!XMLString::equals(thisNode->getPrefix(), arg->getPrefix())) {
00399         return false;
00400     }
00401 
00402     if (!XMLString::equals(thisNode->getNodeValue(), arg->getNodeValue())) {
00403         return false;
00404     }
00405 
00406     return true;
00407 }
00408 
00409 const XMLCh* DOMNodeImpl::lookupPrefix(const XMLCh* namespaceURI) const {
00410     // REVISIT: When Namespaces 1.1 comes out this may not be true
00411     // Prefix can't be bound to null namespace
00412     if (namespaceURI == 0) {
00413         return 0;
00414     }
00415 
00416     DOMNode *thisNode = castToNode(this);
00417 
00418     short type = thisNode->getNodeType();
00419 
00420     switch (type) {
00421     case DOMNode::ELEMENT_NODE: {
00422         return lookupPrefix(namespaceURI, (DOMElement*)thisNode);
00423     }
00424     case DOMNode::DOCUMENT_NODE:{
00425         return ((DOMDocument*)thisNode)->getDocumentElement()->lookupPrefix(namespaceURI);
00426     }
00427 
00428     case DOMNode::ENTITY_NODE :
00429     case DOMNode::NOTATION_NODE:
00430     case DOMNode::DOCUMENT_FRAGMENT_NODE:
00431     case DOMNode::DOCUMENT_TYPE_NODE:
00432         // type is unknown
00433         return 0;
00434     case DOMNode::ATTRIBUTE_NODE:{
00435         if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
00436             return fOwnerNode->lookupPrefix(namespaceURI);
00437         }
00438         return 0;
00439     }
00440     default:{
00441         DOMNode *ancestor = getElementAncestor(thisNode);
00442         if (ancestor != 0) {
00443             return ancestor->lookupPrefix(namespaceURI);
00444         }
00445         return 0;
00446     }
00447     }
00448 }
00449 
00450 
00451 DOMNode* DOMNodeImpl::getElementAncestor (const DOMNode* currentNode) const {
00452     DOMNode* parent = currentNode->getParentNode();
00453     while(parent != 0) {
00454         short type = parent->getNodeType();
00455         if (type == DOMNode::ELEMENT_NODE) {
00456             return parent;
00457         }
00458         parent=parent->getParentNode();
00459     }
00460     return 0;
00461 }
00462 
00463 
00464 const XMLCh* DOMNodeImpl::lookupPrefix(const XMLCh* const namespaceURI, DOMElement *originalElement) const {
00465     DOMNode *thisNode = castToNode(this);
00466 
00467     const XMLCh* ns = thisNode->getNamespaceURI();
00468     // REVISIT: if no prefix is available is it null or empty string, or
00469     //          could be both?
00470     const XMLCh* prefix = thisNode->getPrefix();
00471 
00472     if (ns != 0 && XMLString::equals(ns,namespaceURI) && prefix != 0) {
00473         const XMLCh* foundNamespace =  originalElement->lookupNamespaceURI(prefix);
00474         if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) {
00475             return prefix;
00476         }
00477     }
00478     if (thisNode->hasAttributes()) {
00479         DOMNamedNodeMap *nodeMap = thisNode->getAttributes();
00480 
00481         if(nodeMap != 0) {
00482             XMLSize_t length = nodeMap->getLength();
00483 
00484             for (XMLSize_t i = 0;i < length;i++) {
00485                 DOMNode *attr = nodeMap->item(i);
00486                 const XMLCh* attrPrefix = attr->getPrefix();
00487                 const XMLCh* value = attr->getNodeValue();
00488 
00489                 ns = attr->getNamespaceURI();
00490 
00491                 if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) {
00492                     // DOM Level 2 nodes
00493                     if ((attrPrefix != 0 && XMLString::equals(attrPrefix, XMLUni::fgXMLNSString)) &&
00494                         XMLString::equals(value, namespaceURI)) {
00495                         const XMLCh* localname= attr->getLocalName();
00496                         const XMLCh* foundNamespace = originalElement->lookupNamespaceURI(localname);
00497                         if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) {
00498                             return localname;
00499                         }
00500                     }
00501                 }
00502             }
00503         }
00504     }
00505     DOMNode *ancestor = getElementAncestor(thisNode);
00506     if (ancestor != 0) {
00507         return castToNodeImpl(ancestor)->lookupPrefix(namespaceURI, originalElement);
00508     }
00509     return 0;
00510 }
00511 
00512 const XMLCh* DOMNodeImpl::lookupNamespaceURI(const XMLCh* specifiedPrefix) const  {
00513     DOMNode *thisNode = castToNode(this);
00514 
00515     short type = thisNode->getNodeType();
00516     switch (type) {
00517     case DOMNode::ELEMENT_NODE : {
00518         const XMLCh* ns = thisNode->getNamespaceURI();
00519         const XMLCh* prefix = thisNode->getPrefix();
00520         if (ns != 0) {
00521             // REVISIT: is it possible that prefix is empty string?
00522             if (specifiedPrefix == 0 && prefix == specifiedPrefix) {
00523                 // looking for default namespace
00524                 return ns;
00525             } else if (prefix != 0 && XMLString::equals(prefix, specifiedPrefix)) {
00526                 // non default namespace
00527                 return ns;
00528             }
00529         }
00530         if (thisNode->hasAttributes()) {
00531             DOMNamedNodeMap *nodeMap = thisNode->getAttributes();
00532             if(nodeMap != 0) {
00533                 XMLSize_t length = nodeMap->getLength();
00534                 for (XMLSize_t i = 0;i < length;i++) {
00535                     DOMNode *attr = nodeMap->item(i);
00536                     const XMLCh *attrPrefix = attr->getPrefix();
00537                     const XMLCh *value = attr->getNodeValue();
00538                     ns = attr->getNamespaceURI();
00539 
00540                     if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) {
00541                         // at this point we are dealing with DOM Level 2 nodes only
00542                         if (specifiedPrefix == 0 &&
00543                             XMLString::equals(attr->getNodeName(), XMLUni::fgXMLNSString)) {
00544                             // default namespace
00545                             return value;
00546                         } else if (attrPrefix != 0 &&
00547                                    XMLString::equals(attrPrefix, XMLUni::fgXMLNSString) &&
00548                                    XMLString::equals(attr->getLocalName(), specifiedPrefix)) {
00549                             // non default namespace
00550                             return value;
00551                         }
00552                     }
00553                 }
00554             }
00555         }
00556         DOMNode *ancestor = getElementAncestor(thisNode);
00557         if (ancestor != 0) {
00558             return ancestor->lookupNamespaceURI(specifiedPrefix);
00559         }
00560         return 0;
00561     }
00562     case DOMNode::DOCUMENT_NODE : {
00563         return((DOMDocument*)thisNode)->getDocumentElement()->lookupNamespaceURI(specifiedPrefix);
00564     }
00565     case DOMNode::ENTITY_NODE :
00566     case DOMNode::NOTATION_NODE:
00567     case DOMNode::DOCUMENT_FRAGMENT_NODE:
00568     case DOMNode::DOCUMENT_TYPE_NODE:
00569         // type is unknown
00570         return 0;
00571     case DOMNode::ATTRIBUTE_NODE:{
00572         if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
00573             return fOwnerNode->lookupNamespaceURI(specifiedPrefix);
00574         }
00575         return 0;
00576     }
00577     default:{
00578         DOMNode *ancestor = getElementAncestor(castToNode(this));
00579         if (ancestor != 0) {
00580             return ancestor->lookupNamespaceURI(specifiedPrefix);
00581         }
00582         return 0;
00583     }
00584     }
00585 }
00586 
00587 
00588 const XMLCh*     DOMNodeImpl::getBaseURI() const{
00589     DOMNode *thisNode = castToNode(this);
00590     DOMNode* parent = thisNode->getParentNode();
00591     if (parent)
00592         return parent->getBaseURI();
00593     else
00594         return 0;
00595 }
00596 
00597 const DOMNode*   DOMNodeImpl::getTreeParentNode(const DOMNode* node) const {
00598     const DOMNode* parent=node->getParentNode();
00599     if(parent)
00600         return parent;
00601     short nodeType=node->getNodeType();
00602     switch(nodeType)
00603     {
00604     case DOMNode::ATTRIBUTE_NODE: return ((const DOMAttr*)node)->getOwnerElement();
00605     case DOMNode::NOTATION_NODE:
00606     case DOMNode::ENTITY_NODE:    return node->getOwnerDocument()->getDoctype();
00607     }
00608     return 0;
00609 }
00610 
00611 short            DOMNodeImpl::compareDocumentPosition(const DOMNode* other) const {
00612     DOMNode* thisNode = castToNode(this);
00613 
00614     // If the two nodes being compared are the same node, then no flags are set on the return.
00615     if (thisNode == other)
00616         return 0;
00617 
00618     //if this is a custom node, we don't really know what to do, just return
00619     //user should provide its own compareDocumentPosition logic, and shouldn't reach here
00620     if(thisNode->getNodeType() > 12) {
00621         return 0;
00622     }
00623 
00624     //if it is a custom node we must ask it for the order
00625     if(other->getNodeType() > 12) {
00626         return reverseTreeOrderBitPattern(other->compareDocumentPosition(thisNode));
00627     }
00628 
00629     // Otherwise, the order of two nodes is determined by looking for common containers --
00630     // containers which contain both. A node directly contains any child nodes.
00631     // A node also directly contains any other nodes attached to it such as attributes
00632     // contained in an element or entities and notations contained in a document type.
00633     // Nodes contained in contained nodes are also contained, but less-directly as
00634     // the number of intervening containers increases.
00635 
00636     // If one of the nodes being compared contains the other node, then the container precedes
00637     // the contained node, and reversely the contained node follows the container. For example,
00638     // when comparing an element against its own attribute or child, the element node precedes
00639     // its attribute node and its child node, which both follow it.
00640 
00641     const DOMNode* tmpNode;
00642     const DOMNode* myRoot = castToNode(this);
00643     int myDepth=0;
00644     while((tmpNode=getTreeParentNode(myRoot))!=0)
00645     {
00646         myRoot=tmpNode;
00647         if(myRoot==other)
00648             return DOMNode::DOCUMENT_POSITION_CONTAINS | DOMNode::DOCUMENT_POSITION_PRECEDING;
00649         myDepth++;
00650     }
00651 
00652     const DOMNode* hisRoot = other;
00653     int hisDepth=0;
00654     while((tmpNode=getTreeParentNode(hisRoot))!=0)
00655     {
00656         hisRoot=tmpNode;
00657         if(hisRoot==thisNode)
00658             return DOMNode::DOCUMENT_POSITION_CONTAINED_BY | DOMNode::DOCUMENT_POSITION_FOLLOWING;
00659         hisDepth++;
00660     }
00661 
00662     // If there is no common container node, then the order is based upon order between the
00663     // root container of each node that is in no container. In this case, the result is
00664     // disconnected and implementation-specific. This result is stable as long as these
00665     // outer-most containing nodes remain in memory and are not inserted into some other
00666     // containing node. This would be the case when the nodes belong to different documents
00667     // or fragments, and cloning the document or inserting a fragment might change the order.
00668 
00669     if(myRoot!=hisRoot)
00670         return DOMNode::DOCUMENT_POSITION_DISCONNECTED | DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
00671               (myRoot<hisRoot?DOMNode::DOCUMENT_POSITION_PRECEDING:DOMNode::DOCUMENT_POSITION_FOLLOWING);
00672 
00673     // If neither of the previous cases apply, then there exists a most-direct container common
00674     // to both nodes being compared. In this case, the order is determined based upon the two
00675     // determining nodes directly contained in this most-direct common container that either
00676     // are or contain the corresponding nodes being compared.
00677 
00678     // if the two depths are different, go to the same one
00679     myRoot = castToNode(this);
00680     hisRoot = other;
00681     if (myDepth > hisDepth) {
00682         for (int i= 0 ; i < myDepth - hisDepth; i++)
00683             myRoot = getTreeParentNode(myRoot);
00684     }
00685     else {
00686         for (int i = 0; i < hisDepth - myDepth; i++)
00687             hisRoot = getTreeParentNode(hisRoot);
00688     }
00689 
00690     // We now have nodes at the same depth in the tree.  Find a common ancestor.
00691     const DOMNode *myNodeP=myRoot;
00692         const DOMNode *hisNodeP=hisRoot;
00693     while(myRoot!=hisRoot)
00694     {
00695         myNodeP = myRoot;
00696         hisNodeP = hisRoot;
00697         myRoot = getTreeParentNode(myRoot);
00698         hisRoot = getTreeParentNode(hisRoot);
00699     }
00700 
00701     short myNodeType=myNodeP->getNodeType();
00702     short hisNodeType=hisNodeP->getNodeType();
00703     bool bMyNodeIsChild=(myNodeType!=DOMNode::ATTRIBUTE_NODE && myNodeType!=DOMNode::ENTITY_NODE && myNodeType!=DOMNode::NOTATION_NODE);
00704     bool bHisNodeIsChild=(hisNodeType!=DOMNode::ATTRIBUTE_NODE && hisNodeType!=DOMNode::ENTITY_NODE && hisNodeType!=DOMNode::NOTATION_NODE);
00705 
00706     // If these two determining nodes are both child nodes, then the natural DOM order of these
00707     // determining nodes within the containing node is returned as the order of the corresponding nodes.
00708     // This would be the case, for example, when comparing two child elements of the same element.
00709     if(bMyNodeIsChild && bHisNodeIsChild)
00710     {
00711         while(myNodeP != 0)
00712         {
00713             myNodeP = myNodeP->getNextSibling();
00714             if(myNodeP == hisNodeP)
00715                 return DOMNode::DOCUMENT_POSITION_FOLLOWING;
00716         }
00717         return DOMNode::DOCUMENT_POSITION_PRECEDING;
00718     }
00719 
00720     // If one of the two determining nodes is a child node and the other is not, then the corresponding
00721     // node of the child node follows the corresponding node of the non-child node. This would be the case,
00722     // for example, when comparing an attribute of an element with a child element of the same element.
00723     else if(!bMyNodeIsChild && bHisNodeIsChild)
00724         return DOMNode::DOCUMENT_POSITION_FOLLOWING;
00725     else if(bMyNodeIsChild && !bHisNodeIsChild)
00726         return DOMNode::DOCUMENT_POSITION_PRECEDING;
00727 
00728     else
00729     {
00730         // If neither of the two determining node is a child node and one determining node has a greater value
00731         // of nodeType than the other, then the corresponding node precedes the other. This would be the case,
00732         // for example, when comparing an entity of a document type against a notation of the same document type.
00733         if(myNodeType!=hisNodeType)
00734             return (myNodeType<hisNodeType)?DOMNode::DOCUMENT_POSITION_FOLLOWING:DOMNode::DOCUMENT_POSITION_PRECEDING;
00735 
00736         // If neither of the two determining node is a child node and nodeType is the same for both determining
00737         // nodes, then an implementation-dependent order between the determining nodes is returned. This order
00738         // is stable as long as no nodes of the same nodeType are inserted into or removed from the direct container.
00739         // This would be the case, for example, when comparing two attributes of the same element, and inserting
00740         // or removing additional attributes might change the order between existing attributes.
00741         return DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | ((myNodeP<hisNodeP)?DOMNode::DOCUMENT_POSITION_FOLLOWING:DOMNode::DOCUMENT_POSITION_PRECEDING);
00742     }
00743     // REVISIT:  shouldn't get here.   Should probably throw an
00744     // exception
00745     return 0;
00746 }
00747 
00748 short DOMNodeImpl::reverseTreeOrderBitPattern(short pattern) const {
00749 
00750     if(pattern & DOMNode::DOCUMENT_POSITION_PRECEDING) {
00751         pattern &= !DOMNode::DOCUMENT_POSITION_PRECEDING;
00752         pattern |= DOMNode::DOCUMENT_POSITION_FOLLOWING;
00753     }
00754     else if(pattern & DOMNode::DOCUMENT_POSITION_FOLLOWING) {
00755         pattern &= !DOMNode::DOCUMENT_POSITION_FOLLOWING;
00756         pattern |= DOMNode::DOCUMENT_POSITION_PRECEDING;
00757     }
00758 
00759     if(pattern & DOMNode::DOCUMENT_POSITION_CONTAINED_BY) {
00760         pattern &= !DOMNode::DOCUMENT_POSITION_CONTAINED_BY;
00761         pattern |= DOMNode::DOCUMENT_POSITION_CONTAINS;
00762     }
00763     else if(pattern & DOMNode::DOCUMENT_POSITION_CONTAINS) {
00764         pattern &= !DOMNode::DOCUMENT_POSITION_CONTAINS;
00765         pattern |= DOMNode::DOCUMENT_POSITION_CONTAINED_BY;
00766     }
00767 
00768     return pattern;
00769 }
00770 
00771 /***
00772  *
00773  *   Excerpt from http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/core.html#Node3-textContent
00774  *
00775  *   textContent of type DOMString, introduced in DOM Level 3
00776  *
00777  *   This attribute returns the text content of this node and its descendants. When it is defined
00778  *   to be null, setting it has no effect.
00779  *
00780  *   When set, any possible children this node may have are removed and replaced by a single Text node
00781  *   containing the string this attribute is set to.
00782  *
00783  *   On getting, no serialization is performed, the returned string does not contain any markup.
00784  *   No whitespace normalization is performed, the returned string does not contain the element content
00785  *   whitespaces Fundamental Interfaces.
00786  *
00787  *   Similarly, on setting, no parsing is performed either, the input string is taken as pure textual content.
00788  *
00789  *   The string returned is made of the text content of this node depending on its type,
00790  *   as defined below:
00791  *
00792  *       Node type                                           Content
00793  *   ====================       ========================================================================
00794  *     ELEMENT_NODE               concatenation of the textContent attribute value of every child node,
00795  *     ENTITY_NODE                            excluding COMMENT_NODE and PROCESSING_INSTRUCTION_NODE nodes.
00796  *     ENTITY_REFERENCE_NODE      This is the empty string if the node has no children.
00797  *     DOCUMENT_FRAGMENT_NODE
00798  *    --------------------------------------------------------------------------------------------------
00799  *     ATTRIBUTE_NODE
00800  *     TEXT_NODE
00801  *     CDATA_SECTION_NODE
00802  *     COMMENT_NODE,
00803  *     PROCESSING_INSTRUCTION_NODE   nodeValue
00804  *    --------------------------------------------------------------------------------------------------
00805  *     DOCUMENT_NODE,
00806  *     DOCUMENT_TYPE_NODE,
00807  *     NOTATION_NODE                 null
00808  *
00809  ***/
00810 
00811 const XMLCh*     DOMNodeImpl::getTextContent() const
00812 {
00813         XMLSize_t nBufferLength = 0;
00814 
00815         getTextContent(NULL, nBufferLength);
00816         XMLCh* pzBuffer = (XMLCh*)((DOMDocumentImpl*)getOwnerDocument())->allocate((nBufferLength+1) * sizeof(XMLCh));
00817         getTextContent(pzBuffer, nBufferLength);
00818         pzBuffer[nBufferLength] = 0;
00819 
00820         return pzBuffer;
00821 
00822 }
00823 
00824 const XMLCh*    DOMNodeImpl::getTextContent(XMLCh* pzBuffer, XMLSize_t& rnBufferLength) const
00825 {
00826         XMLSize_t nRemainingBuffer = rnBufferLength;
00827         rnBufferLength = 0;
00828 
00829         if (pzBuffer)
00830                 *pzBuffer = 0;
00831 
00832         DOMNode *thisNode = castToNode(this);
00833 
00834         switch (thisNode->getNodeType())
00835         {
00836         case DOMNode::ELEMENT_NODE:
00837     case DOMNode::ENTITY_NODE:
00838     case DOMNode::ENTITY_REFERENCE_NODE:
00839     case DOMNode::DOCUMENT_FRAGMENT_NODE:
00840     {
00841                 DOMNode* current = thisNode->getFirstChild();
00842 
00843                 while (current != NULL)
00844                 {
00845                         if (current->getNodeType() != DOMNode::COMMENT_NODE &&
00846                                 current->getNodeType() != DOMNode::PROCESSING_INSTRUCTION_NODE)
00847                         {
00848 
00849                                 if (pzBuffer)
00850                                 {
00851                                         XMLSize_t nContentLength = nRemainingBuffer;
00852                                         castToNodeImpl(current)->getTextContent(pzBuffer + rnBufferLength, nContentLength);
00853                                         rnBufferLength += nContentLength;
00854                                         nRemainingBuffer -= nContentLength;
00855                                 }
00856                                 else
00857                                 {
00858                                         XMLSize_t nContentLength = 0;
00859                                         castToNodeImpl(current)->getTextContent(NULL, nContentLength);
00860                                         rnBufferLength += nContentLength;
00861                                 }
00862                         }
00863 
00864                         current = current->getNextSibling();
00865 
00866                 }
00867     }
00868 
00869     break;
00870 
00871     case DOMNode::ATTRIBUTE_NODE:
00872     case DOMNode::TEXT_NODE:
00873     case DOMNode::CDATA_SECTION_NODE:
00874     case DOMNode::COMMENT_NODE:
00875     case DOMNode::PROCESSING_INSTRUCTION_NODE:
00876     {
00877                 const XMLCh* pzValue = thisNode->getNodeValue();
00878                 XMLSize_t nStrLen = XMLString::stringLen(pzValue);
00879 
00880                 if (pzBuffer)
00881                 {
00882                         XMLSize_t nContentLength = (nRemainingBuffer >= nStrLen) ? nStrLen : nRemainingBuffer;
00883                         XMLString::copyNString(pzBuffer + rnBufferLength, pzValue, nContentLength);
00884                         rnBufferLength += nContentLength;
00885                         nRemainingBuffer -= nContentLength;
00886                 }
00887                 else
00888                 {
00889                         rnBufferLength += nStrLen;
00890                 }
00891 
00892     }
00893 
00894     break;
00895 
00896         /***
00897          DOCUMENT_NODE
00898                  DOCUMENT_TYPE_NODE
00899                  NOTATION_NODE
00900         ***/
00901         default:
00902 
00903                 break;
00904         }
00905 
00906         return pzBuffer;
00907 
00908 }
00909 
00910 void DOMNodeImpl::setTextContent(const XMLCh* textContent){
00911     DOMNode *thisNode = castToNode(this);
00912     switch (thisNode->getNodeType())
00913     {
00914         case DOMNode::ELEMENT_NODE:
00915         case DOMNode::ENTITY_NODE:
00916         case DOMNode::ENTITY_REFERENCE_NODE:
00917         case DOMNode::DOCUMENT_FRAGMENT_NODE:
00918             {
00919                 if (isReadOnly())
00920                   throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00921 
00922                 // Remove all childs
00923                 DOMNode* current = thisNode->getFirstChild();
00924                 while (current != NULL)
00925                 {
00926                     thisNode->removeChild(current);
00927                     current = thisNode->getFirstChild();
00928                 }
00929                 if (textContent != NULL)
00930                 {
00931                     // Add textnode containing data
00932                     current = ((DOMDocumentImpl*)thisNode->getOwnerDocument())->createTextNode(textContent);
00933                     thisNode->appendChild(current);
00934                 }
00935             }
00936             break;
00937 
00938         case DOMNode::ATTRIBUTE_NODE:
00939         case DOMNode::TEXT_NODE:
00940         case DOMNode::CDATA_SECTION_NODE:
00941         case DOMNode::COMMENT_NODE:
00942         case DOMNode::PROCESSING_INSTRUCTION_NODE:
00943             if (isReadOnly())
00944                 throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00945 
00946             thisNode->setNodeValue(textContent);
00947             break;
00948 
00949         case DOMNode::DOCUMENT_NODE:
00950         case DOMNode::DOCUMENT_TYPE_NODE:
00951         case DOMNode::NOTATION_NODE:
00952             break;
00953 
00954         default:
00955             throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, GetDOMNodeMemoryManager);
00956     }
00957 }
00958 
00959 
00960 bool DOMNodeImpl::isDefaultNamespace(const XMLCh* namespaceURI) const{
00961         DOMNode *thisNode = castToNode(this);
00962     short type = thisNode->getNodeType();
00963     switch (type) {
00964     case DOMNode::ELEMENT_NODE: {
00965         const XMLCh *prefix = thisNode->getPrefix();
00966 
00967         // REVISIT: is it possible that prefix is empty string?
00968         if (prefix == 0 || !*prefix) {
00969             return XMLString::equals(namespaceURI, thisNode->getNamespaceURI());
00970         }
00971 
00972         if (thisNode->hasAttributes()) {
00973             DOMElement *elem = (DOMElement *)thisNode;
00974             DOMNode *attr = elem->getAttributeNodeNS(XMLUni::fgXMLNSURIName, XMLUni::fgXMLNSString);
00975             if (attr != 0) {
00976                 const XMLCh *value = attr->getNodeValue();
00977                 return XMLString::equals(namespaceURI, value);
00978             }
00979         }
00980         DOMNode *ancestor = getElementAncestor(thisNode);
00981         if (ancestor != 0) {
00982             return ancestor->isDefaultNamespace(namespaceURI);
00983         }
00984 
00985         return false;
00986     }
00987     case DOMNode::DOCUMENT_NODE:{
00988         return ((DOMDocument*)thisNode)->getDocumentElement()->isDefaultNamespace(namespaceURI);
00989     }
00990 
00991     case DOMNode::ENTITY_NODE :
00992     case DOMNode::NOTATION_NODE:
00993     case DOMNode::DOCUMENT_FRAGMENT_NODE:
00994     case DOMNode::DOCUMENT_TYPE_NODE:
00995         // type is unknown
00996         return false;
00997     case DOMNode::ATTRIBUTE_NODE:{
00998         if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
00999             return fOwnerNode->isDefaultNamespace(namespaceURI);
01000 
01001         }
01002         return false;
01003     }
01004     default:{
01005         DOMNode *ancestor = getElementAncestor(thisNode);
01006         if (ancestor != 0) {
01007             return ancestor->isDefaultNamespace(namespaceURI);
01008         }
01009         return false;
01010     }
01011 
01012     }
01013 }
01014 
01015 void* DOMNodeImpl::getFeature(const XMLCh*, const XMLCh*) const {
01016     return 0;
01017 }
01018 
01019 
01020 // non-standard extension
01021 void DOMNodeImpl::release()
01022 {
01023     // shouldn't reach here
01024     throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
01025 }
01026 
01027 XERCES_CPP_NAMESPACE_END
01028