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