GME  13
DOMTextImpl.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: DOMTextImpl.cpp 678709 2008-07-22 10:56:56Z borisk $
00020  */
00021 
00022 
00023 #include <xercesc/util/XMLUniDefs.hpp>
00024 
00025 #include <xercesc/dom/DOMException.hpp>
00026 #include <xercesc/dom/DOMNode.hpp>
00027 #include <xercesc/dom/DOMElement.hpp>
00028 #include <xercesc/dom/DOMCDATASection.hpp>
00029 #include <xercesc/dom/DOMNodeFilter.hpp>
00030 #include <xercesc/dom/DOMTreeWalker.hpp>
00031 
00032 #include "DOMDocumentImpl.hpp"
00033 #include "DOMStringPool.hpp"
00034 #include "DOMTextImpl.hpp"
00035 #include "DOMCharacterDataImpl.hpp"
00036 #include "DOMChildNode.hpp"
00037 #include "DOMRangeImpl.hpp"
00038 #include "DOMCasts.hpp"
00039 
00040 #include <assert.h>
00041 
00042 XERCES_CPP_NAMESPACE_BEGIN
00043 
00044 class DOMDocument;
00045 
00046 DOMTextImpl::DOMTextImpl(DOMDocument *ownerDoc, const XMLCh *dat)
00047     : fNode(ownerDoc), fCharacterData(ownerDoc, dat)
00048 {
00049     fNode.setIsLeafNode(true);
00050 }
00051 
00052 DOMTextImpl::
00053 DOMTextImpl(DOMDocument *ownerDoc, const XMLCh* dat, XMLSize_t n)
00054     : fNode(ownerDoc), fCharacterData(ownerDoc, dat, n)
00055 {
00056     fNode.setIsLeafNode(true);
00057 }
00058 
00059 DOMTextImpl::DOMTextImpl(const DOMTextImpl &other, bool)
00060     : DOMText(other)
00061     , fNode(other.fNode)
00062     , fCharacterData(other.fCharacterData)
00063 {
00064     fNode.setIsLeafNode(true);
00065 }
00066 
00067 DOMTextImpl::~DOMTextImpl()
00068 {
00069 }
00070 
00071 
00072 DOMNode *DOMTextImpl::cloneNode(bool deep) const
00073 {
00074     DOMNode* newNode = new (getOwnerDocument(), DOMMemoryManager::TEXT_OBJECT) DOMTextImpl(*this, deep);
00075     fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
00076     return newNode;
00077 }
00078 
00079 
00080 const XMLCh * DOMTextImpl::getNodeName() const {
00081     static const XMLCh gtext[] = {chPound, chLatin_t, chLatin_e, chLatin_x, chLatin_t, chNull};
00082     return gtext;
00083 }
00084 
00085 DOMNode::NodeType DOMTextImpl::getNodeType() const {
00086     return DOMNode::TEXT_NODE;
00087 }
00088 
00089 
00090 DOMText *DOMTextImpl::splitText(XMLSize_t offset)
00091 {
00092     if (fNode.isReadOnly())
00093     {
00094         throw DOMException(
00095             DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00096     }
00097     XMLSize_t len = fCharacterData.fDataBuf->getLen();
00098     if (offset > len)
00099         throw DOMException(DOMException::INDEX_SIZE_ERR, 0, GetDOMNodeMemoryManager);
00100 
00101     DOMDocumentImpl *doc = (DOMDocumentImpl *)getOwnerDocument();
00102     DOMText *newText = doc->createTextNode(
00103       this->substringData(offset, len - offset));
00104 
00105     DOMNode *parent = getParentNode();
00106     if (parent != 0)
00107         parent->insertBefore(newText, getNextSibling());
00108 
00109     fCharacterData.fDataBuf->chop(offset);
00110 
00111     if (doc != 0) {
00112         Ranges* ranges = doc->getRanges();
00113         if (ranges != 0) {
00114             XMLSize_t sz = ranges->size();
00115             if (sz != 0) {
00116                 for (XMLSize_t i =0; i<sz; i++) {
00117                     ranges->elementAt(i)->updateSplitInfo( this, newText, offset);
00118                 }
00119             }
00120         }
00121     }
00122 
00123     return newText;
00124 }
00125 
00126 
00127 bool DOMTextImpl::isIgnorableWhitespace() const
00128 {
00129     return fNode.ignorableWhitespace();
00130 }
00131 
00132 
00133 
00134 void DOMTextImpl::setIgnorableWhitespace(bool ignorable)
00135 {
00136     fNode.ignorableWhitespace(ignorable);
00137 }
00138 
00139 
00140 bool DOMTextImpl::getIsElementContentWhitespace() const
00141 {
00142     return isIgnorableWhitespace();
00143 }
00144 
00145 const XMLCh* DOMTextImpl::getWholeText() const
00146 {
00147     DOMDocument *doc = getOwnerDocument();
00148     DOMTreeWalker* pWalker=doc->createTreeWalker(doc->getDocumentElement(), DOMNodeFilter::SHOW_ALL, NULL, true);
00149     pWalker->setCurrentNode((DOMNode*)this);
00150     // Logically-adjacent text nodes are Text or CDATASection nodes that can be visited sequentially in document order or in
00151     // reversed document order without entering, exiting, or passing over Element, Comment, or ProcessingInstruction nodes.
00152         DOMNode* prevNode;
00153     while((prevNode=pWalker->previousNode())!=NULL)
00154     {
00155         if(prevNode->getNodeType()==ELEMENT_NODE || prevNode->getNodeType()==COMMENT_NODE || prevNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
00156             break;
00157     }
00158         XMLBuffer buff(1023, GetDOMNodeMemoryManager);
00159         DOMNode* nextNode;
00160     while((nextNode=pWalker->nextNode())!=NULL)
00161     {
00162         if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
00163             break;
00164         if(nextNode->getNodeType()==TEXT_NODE || nextNode->getNodeType()==CDATA_SECTION_NODE)
00165                 buff.append(nextNode->getNodeValue());
00166     }
00167     pWalker->release();
00168 
00169     XMLCh* wholeString = (XMLCh*) (GetDOMNodeMemoryManager->allocate((buff.getLen()+1)*sizeof(XMLCh)));
00170         XMLString::copyString(wholeString, buff.getRawBuffer());
00171         return wholeString;
00172 }
00173 
00174 DOMText* DOMTextImpl::replaceWholeText(const XMLCh* newText)
00175 {
00176     DOMDocument *doc = getOwnerDocument();
00177     DOMTreeWalker* pWalker=doc->createTreeWalker(doc->getDocumentElement(), DOMNodeFilter::SHOW_ALL, NULL, true);
00178     pWalker->setCurrentNode((DOMNode*)this);
00179     // Logically-adjacent text nodes are Text or CDATASection nodes that can be visited sequentially in document order or in
00180     // reversed document order without entering, exiting, or passing over Element, Comment, or ProcessingInstruction nodes.
00181     DOMNode* pFirstTextNode=this;
00182         DOMNode* prevNode;
00183     while((prevNode=pWalker->previousNode())!=NULL)
00184     {
00185         if(prevNode->getNodeType()==ELEMENT_NODE || prevNode->getNodeType()==COMMENT_NODE || prevNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
00186             break;
00187         pFirstTextNode=prevNode;
00188     }
00189     // before doing any change we need to check if we are going to remove an entity reference that doesn't contain just text
00190     DOMNode* pCurrentNode=pWalker->getCurrentNode();
00191         DOMNode* nextNode;
00192     while((nextNode=pWalker->nextNode())!=NULL)
00193     {
00194         if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
00195             break;
00196         if(nextNode->getNodeType()==ENTITY_REFERENCE_NODE)
00197         {
00198             DOMTreeWalker* pInnerWalker=doc->createTreeWalker(nextNode, DOMNodeFilter::SHOW_ALL, NULL, true);
00199             while(pInnerWalker->nextNode())
00200             {
00201                 short nodeType=pInnerWalker->getCurrentNode()->getNodeType();
00202                 if(nodeType!=ENTITY_REFERENCE_NODE && nodeType!=TEXT_NODE && nodeType!=CDATA_SECTION_NODE)
00203                     throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00204             }
00205             pInnerWalker->release();
00206         }
00207     }
00208     DOMText* retVal=NULL;
00209     // if the first node in the chain is a text node, replace its content, otherwise create a new node
00210     if(newText && *newText)
00211     {
00212         if(!castToNodeImpl(pFirstTextNode)->isReadOnly() && (pFirstTextNode->getNodeType()==TEXT_NODE || pFirstTextNode->getNodeType()==CDATA_SECTION_NODE))
00213         {
00214             pFirstTextNode->setNodeValue(newText);
00215             retVal=(DOMText*)pFirstTextNode;
00216         }
00217         else
00218         {
00219             if(getNodeType()==TEXT_NODE)
00220                 retVal=doc->createTextNode(newText);
00221             else
00222                 retVal=doc->createCDATASection(newText);
00223             pFirstTextNode->getParentNode()->insertBefore(retVal, pFirstTextNode);
00224         }
00225     }
00226     // now delete all the following text nodes
00227     pWalker->setCurrentNode(pCurrentNode);
00228     while((nextNode=pWalker->nextNode())!=NULL)
00229     {
00230         if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
00231             break;
00232         if(nextNode!=retVal)
00233         {
00234             // keep the tree walker valid
00235             pWalker->previousNode();
00236             nextNode->getParentNode()->removeChild(nextNode);
00237             nextNode->release();
00238         }
00239     }
00240     pWalker->release();
00241     return retVal;
00242 }
00243 
00244 
00245 void DOMTextImpl::release()
00246 {
00247     if (fNode.isOwned() && !fNode.isToBeReleased())
00248         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
00249 
00250     DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument();
00251     if (doc) {
00252         fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
00253         fCharacterData.releaseBuffer();
00254         doc->release(this, DOMMemoryManager::TEXT_OBJECT);
00255     }
00256     else {
00257         // shouldn't reach here
00258         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
00259     }
00260 }
00261 
00262 //
00263 //  Delegation functions
00264 //
00265            DOMNode*         DOMTextImpl::appendChild(DOMNode *newChild)          {return fNode.appendChild (newChild); }
00266            DOMNamedNodeMap* DOMTextImpl::getAttributes() const                   {return fNode.getAttributes (); }
00267            DOMNodeList*     DOMTextImpl::getChildNodes() const                   {return fNode.getChildNodes (); }
00268            DOMNode*         DOMTextImpl::getFirstChild() const                   {return fNode.getFirstChild (); }
00269            DOMNode*         DOMTextImpl::getLastChild() const                    {return fNode.getLastChild (); }
00270      const XMLCh*           DOMTextImpl::getLocalName() const                    {return fNode.getLocalName (); }
00271      const XMLCh*           DOMTextImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); }
00272            DOMNode*         DOMTextImpl::getNextSibling() const                  {return fChild.getNextSibling (); }
00273      const XMLCh*           DOMTextImpl::getNodeValue() const                    {return fCharacterData.getNodeValue (); }
00274            DOMDocument*     DOMTextImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); }
00275      const XMLCh*           DOMTextImpl::getPrefix() const                       {return fNode.getPrefix (); }
00276            DOMNode*         DOMTextImpl::getParentNode() const                   {return fChild.getParentNode (this); }
00277            DOMNode*         DOMTextImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); }
00278            bool             DOMTextImpl::hasChildNodes() const                   {return fNode.hasChildNodes (); }
00279            DOMNode*         DOMTextImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
00280                                                                                  {return fNode.insertBefore (newChild, refChild); }
00281            void             DOMTextImpl::normalize()                             {fNode.normalize (); }
00282            DOMNode*         DOMTextImpl::removeChild(DOMNode *oldChild)          {return fNode.removeChild (oldChild); }
00283            DOMNode*         DOMTextImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
00284                                                                                  {return fNode.replaceChild (newChild, oldChild); }
00285            bool             DOMTextImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
00286                                                                                  {return fNode.isSupported (feature, version); }
00287            void             DOMTextImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); }
00288            bool             DOMTextImpl::hasAttributes() const                   {return fNode.hasAttributes(); }
00289            bool             DOMTextImpl::isSameNode(const DOMNode* other) const  {return fNode.isSameNode(other); }
00290            bool             DOMTextImpl::isEqualNode(const DOMNode* arg) const   {return fNode.isEqualNode(arg); }
00291            void*            DOMTextImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
00292                                                                                  {return fNode.setUserData(key, data, handler); }
00293            void*            DOMTextImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); }
00294            const XMLCh*     DOMTextImpl::getBaseURI() const                      {return fNode.getBaseURI(); }
00295            short            DOMTextImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); }
00296            const XMLCh*     DOMTextImpl::getTextContent() const                  {return fNode.getTextContent(); }
00297            void             DOMTextImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
00298            const XMLCh*     DOMTextImpl::lookupPrefix(const XMLCh* namespaceURI) const  {return fNode.lookupPrefix(namespaceURI); }
00299            bool             DOMTextImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
00300            const XMLCh*     DOMTextImpl::lookupNamespaceURI(const XMLCh* prefix) const  {return fNode.lookupNamespaceURI(prefix); }
00301            void*            DOMTextImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); }
00302 
00303 
00304 
00305 //
00306 //   Delegation of CharacerData functions.
00307 //
00308 
00309 
00310           const XMLCh*      DOMTextImpl::getData() const                         {return fCharacterData.getData();}
00311           XMLSize_t         DOMTextImpl::getLength() const                       {return fCharacterData.getLength();}
00312           const XMLCh*      DOMTextImpl::substringData(XMLSize_t offset, XMLSize_t count) const
00313                                                                                  {return fCharacterData.substringData(this, offset, count);}
00314           void              DOMTextImpl::appendData(const XMLCh *arg)            {fCharacterData.appendData(this, arg);}
00315           void              DOMTextImpl::insertData(XMLSize_t offset, const  XMLCh *arg)
00316                                                                                  {fCharacterData.insertData(this, offset, arg);}
00317           void              DOMTextImpl::deleteData(XMLSize_t offset, XMLSize_t count)
00318                                                                                  {fCharacterData.deleteData(this, offset, count);}
00319           void              DOMTextImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg)
00320                                                                                  {fCharacterData.replaceData(this, offset, count, arg);}
00321           void              DOMTextImpl::setData(const XMLCh *data)              {fCharacterData.setData(this, data);}
00322           void              DOMTextImpl::setNodeValue(const XMLCh  *nodeValue)   {fCharacterData.setNodeValue (this, nodeValue); }
00323 
00324           void              DOMTextImpl::appendData(const XMLCh *arg, XMLSize_t n) {fCharacterData.appendData(this, arg, n);}
00325 
00326 XERCES_CPP_NAMESPACE_END