GME  13
DOMDocumentTypeImpl.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: DOMDocumentTypeImpl.cpp 678709 2008-07-22 10:56:56Z borisk $
00020  */
00021 
00022 #include "DOMDocumentTypeImpl.hpp"
00023 #include <xercesc/dom/DOMNode.hpp>
00024 #include <xercesc/dom/DOMException.hpp>
00025 #include <xercesc/dom/DOMImplementationRegistry.hpp>
00026 #include <xercesc/dom/DOMImplementation.hpp>
00027 #include <xercesc/util/XMLUniDefs.hpp>
00028 #include <xercesc/util/XMLChar.hpp>
00029 #include <xercesc/util/Mutexes.hpp>
00030 #include <xercesc/util/PlatformUtils.hpp>
00031 #include <xercesc/util/XMLInitializer.hpp>
00032 
00033 #include "DOMNamedNodeMapImpl.hpp"
00034 #include "DOMDocumentImpl.hpp"
00035 #include "DOMCasts.hpp"
00036 
00037 XERCES_CPP_NAMESPACE_BEGIN
00038 
00039 static DOMDocument* sDocument = 0;
00040 static XMLMutex*    sDocumentMutex = 0;
00041 
00042 void XMLInitializer::initializeDOMDocumentTypeImpl()
00043 {
00044     sDocumentMutex = new XMLMutex(XMLPlatformUtils::fgMemoryManager);
00045 
00046     static const XMLCh gCoreStr[] = { chLatin_C, chLatin_o, chLatin_r, chLatin_e, chNull };
00047     DOMImplementation* impl =  DOMImplementationRegistry::getDOMImplementation(gCoreStr);
00048     sDocument = impl->createDocument(); // document type object (DTD).
00049 }
00050 
00051 void XMLInitializer::terminateDOMDocumentTypeImpl()
00052 {
00053     sDocument->release();
00054     sDocument = 0;
00055 
00056     delete sDocumentMutex;
00057     sDocumentMutex = 0;
00058 }
00059 
00060 DOMDocumentTypeImpl::DOMDocumentTypeImpl(DOMDocument *ownerDoc,
00061                                    const XMLCh *dtName,
00062                                    bool heap)
00063     : fNode(ownerDoc),
00064     fParent(ownerDoc),
00065     fName(0),
00066     fEntities(0),
00067     fNotations(0),
00068     fElements(0),
00069     fPublicId(0),
00070     fSystemId(0),
00071     fInternalSubset(0),
00072     fIntSubsetReading(false),
00073     fIsCreatedFromHeap(heap)
00074 {
00075     if (ownerDoc)
00076     {
00077         fName = ((DOMDocumentImpl *)ownerDoc)->getPooledString(dtName);
00078         fEntities = new (ownerDoc) DOMNamedNodeMapImpl(this);
00079         fNotations= new (ownerDoc) DOMNamedNodeMapImpl(this);
00080         fElements = new (ownerDoc) DOMNamedNodeMapImpl(this);
00081     }
00082     else
00083     {
00084         XMLMutexLock lock(sDocumentMutex);
00085         DOMDocument* doc = sDocument;
00086         fName = ((DOMDocumentImpl *)doc)->getPooledString(dtName);
00087         fEntities = new (doc) DOMNamedNodeMapImpl(this);
00088         fNotations= new (doc) DOMNamedNodeMapImpl(this);
00089         fElements = new (doc) DOMNamedNodeMapImpl(this);
00090     }
00091 }
00092 
00093 
00094 //Introduced in DOM Level 2
00095 DOMDocumentTypeImpl::DOMDocumentTypeImpl(DOMDocument *ownerDoc,
00096                                    const XMLCh *qualifiedName,
00097                                    const XMLCh *pubId,
00098                                    const XMLCh *sysId,
00099                                    bool heap)
00100     : fNode(ownerDoc),
00101     fParent(ownerDoc),
00102     fName(0),
00103     fEntities(0),
00104     fNotations(0),
00105     fElements(0),
00106     fPublicId(0),
00107     fSystemId(0),
00108     fInternalSubset(0),
00109     fIntSubsetReading(false),
00110     fIsCreatedFromHeap(heap)
00111 {
00112     int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName);
00113     if (index < 0)
00114         throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
00115     else if (index > 0)
00116     {
00117         // we have to make sure the qualifiedName has correct prefix and localName
00118         // although we don't really to store them separately
00119         XMLCh* newName;
00120         XMLCh temp[256];
00121         if (index >= 255)
00122             newName = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
00123             (
00124                 (XMLString::stringLen(qualifiedName)+1) * sizeof(XMLCh)
00125             );//new XMLCh[XMLString::stringLen(qualifiedName)+1];
00126         else
00127             newName = temp;
00128 
00129         XMLString::copyNString(newName, qualifiedName, index);
00130         newName[index] = chNull;
00131 
00132         // Before we carry on, we should check if the prefix or localName are valid XMLName
00133         if (ownerDoc) {
00134             if (!((DOMDocumentImpl*)ownerDoc)->isXMLName(newName) || !((DOMDocumentImpl*)ownerDoc)->isXMLName(qualifiedName+index+1))
00135                 throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
00136         }
00137         else {
00138             // document is not there yet, so assume XML 1.0
00139             if (!XMLChar1_0::isValidName(newName) || !XMLChar1_0::isValidName(qualifiedName+index+1))
00140                 throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
00141         }
00142 
00143         if (index >= 255)
00144             XMLPlatformUtils::fgMemoryManager->deallocate(newName);//delete[] newName;
00145     }
00146 
00147     if (ownerDoc)
00148     {
00149         DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc;
00150         fPublicId = docImpl->cloneString(pubId);
00151         fSystemId = docImpl->cloneString(sysId);
00152         fName = ((DOMDocumentImpl *)ownerDoc)->getPooledString(qualifiedName);
00153         fEntities = new (ownerDoc) DOMNamedNodeMapImpl(this);
00154         fNotations= new (ownerDoc) DOMNamedNodeMapImpl(this);
00155         fElements = new (ownerDoc) DOMNamedNodeMapImpl(this);
00156     }
00157     else
00158     {
00159         XMLMutexLock lock(sDocumentMutex);
00160         DOMDocument* doc = sDocument;
00161         fPublicId = ((DOMDocumentImpl*) doc)->cloneString(pubId);
00162         fSystemId = ((DOMDocumentImpl*) doc)->cloneString(sysId);
00163         fName = ((DOMDocumentImpl*) doc)->getPooledString(qualifiedName);
00164         fEntities = new (doc) DOMNamedNodeMapImpl(this);
00165         fNotations= new (doc) DOMNamedNodeMapImpl(this);
00166         fElements = new (doc) DOMNamedNodeMapImpl(this);
00167     }
00168 }
00169 
00170 
00171 DOMDocumentTypeImpl::DOMDocumentTypeImpl(const DOMDocumentTypeImpl &other, bool heap, bool deep)
00172     : fNode(other.fNode),
00173     fParent(other.fParent),
00174     fChild(other.fChild),
00175     fName(0),
00176     fEntities(0),
00177     fNotations(0),
00178     fElements(0),
00179     fPublicId(0),
00180     fSystemId(0),
00181     fInternalSubset(0),
00182     fIntSubsetReading(other.fIntSubsetReading),
00183     fIsCreatedFromHeap(heap)
00184 {
00185     fName = other.fName;
00186 
00187     //DOM Level 2
00188     fPublicId        = other.fPublicId;
00189     fSystemId        = other.fSystemId;
00190     fInternalSubset  = other.fInternalSubset;
00191 
00192     if ((DOMDocumentImpl *)this->fNode.getOwnerDocument() && deep)
00193         fParent.cloneChildren(&other);
00194 
00195     fEntities = other.fEntities->cloneMap(this);
00196     fNotations= other.fNotations->cloneMap(this);
00197     fElements = other.fElements->cloneMap(this);
00198 }
00199 
00200 
00201 DOMDocumentTypeImpl::~DOMDocumentTypeImpl()
00202 {
00203 }
00204 
00205 
00206 DOMNode *DOMDocumentTypeImpl::cloneNode(bool deep) const
00207 {
00208     DOMNode* newNode = 0;
00209     DOMDocument* doc = castToNodeImpl(this)->getOwnerDocument();
00210     if (doc != 0)
00211         newNode = new (doc, DOMMemoryManager::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(*this, false, deep);
00212     else
00213     {
00214         XMLMutexLock lock(sDocumentMutex);
00215         newNode = new (sDocument, DOMMemoryManager::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(*this, false, deep);
00216     }
00217 
00218     fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
00219     return newNode;
00220 }
00221 
00226 void DOMDocumentTypeImpl::setOwnerDocument(DOMDocument *doc) {
00227 
00228     if (castToNodeImpl(this)->getOwnerDocument()) {
00229         fNode.setOwnerDocument(doc);
00230         fParent.setOwnerDocument(doc);
00231     }
00232     else {
00233         if (doc) {
00234             DOMDocumentImpl *docImpl = (DOMDocumentImpl *)doc;
00235 
00236             fPublicId = docImpl->cloneString(fPublicId);
00237             fSystemId = docImpl->cloneString(fSystemId);
00238             fInternalSubset = docImpl->cloneString(fInternalSubset);
00239             fName = docImpl->getPooledString(fName);
00240 
00241             fNode.setOwnerDocument(doc);
00242             fParent.setOwnerDocument(doc);
00243 
00244             DOMNamedNodeMapImpl* entitiesTemp = fEntities->cloneMap(this);
00245             DOMNamedNodeMapImpl* notationsTemp = fNotations->cloneMap(this);
00246             DOMNamedNodeMapImpl* elementsTemp = fElements->cloneMap(this);
00247 
00248             fEntities = entitiesTemp;
00249             fNotations = notationsTemp;
00250             fElements = elementsTemp;
00251         }
00252     }
00253 }
00254 
00255 const XMLCh * DOMDocumentTypeImpl::getNodeName() const
00256 {
00257     return fName;
00258 }
00259 
00260 
00261 DOMNode::NodeType DOMDocumentTypeImpl::getNodeType()  const {
00262     return DOMNode::DOCUMENT_TYPE_NODE;
00263 }
00264 
00265 
00266 DOMNamedNodeMap *DOMDocumentTypeImpl::getEntities() const
00267 {
00268     return fEntities;
00269 }
00270 
00271 
00272 
00273 const XMLCh * DOMDocumentTypeImpl::getName() const
00274 {
00275     return fName;
00276 }
00277 
00278 
00279 DOMNamedNodeMap *DOMDocumentTypeImpl::getNotations() const
00280 {
00281     return fNotations;
00282 }
00283 
00284 
00285 DOMNamedNodeMap *DOMDocumentTypeImpl::getElements() const
00286 {
00287     return fElements;
00288 }
00289 
00290 
00291 void DOMDocumentTypeImpl::setNodeValue(const XMLCh *val)
00292 {
00293     fNode.setNodeValue(val);
00294 }
00295 
00296 
00297 void DOMDocumentTypeImpl::setReadOnly(bool readOnl, bool deep)
00298 {
00299     fNode.setReadOnly(readOnl,deep);
00300     if (fEntities)
00301         fEntities->setReadOnly(readOnl,true);
00302     if (fNotations)
00303         fNotations->setReadOnly(readOnl,true);
00304 }
00305 
00306 
00307 //Introduced in DOM Level 2
00308 
00309 const XMLCh * DOMDocumentTypeImpl::getPublicId() const
00310 {
00311     return fPublicId;
00312 }
00313 
00314 
00315 const XMLCh * DOMDocumentTypeImpl::getSystemId() const
00316 {
00317     return fSystemId;
00318 }
00319 
00320 
00321 const XMLCh * DOMDocumentTypeImpl::getInternalSubset() const
00322 {
00323     return fInternalSubset;
00324 }
00325 
00326 bool DOMDocumentTypeImpl::isIntSubsetReading() const
00327 {
00328     return fIntSubsetReading;
00329 }
00330 
00331 
00332 //set functions
00333 
00334 void DOMDocumentTypeImpl::setPublicId(const XMLCh *value)
00335 {
00336     // revist.  Why shouldn't 0 be assigned like any other value?
00337     if (value == 0)
00338         return;
00339 
00340     DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument();
00341     if (doc != 0)
00342         fPublicId = doc->cloneString(value);
00343     else {
00344         XMLMutexLock lock(sDocumentMutex);
00345         fPublicId = ((DOMDocumentImpl *)sDocument)->cloneString(value);
00346     }
00347 }
00348 
00349 void DOMDocumentTypeImpl::setSystemId(const XMLCh *value)
00350 {
00351     DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument();
00352     if (doc != 0)
00353         fSystemId = doc->cloneString(value);
00354     else {
00355         XMLMutexLock lock(sDocumentMutex);
00356         fSystemId = ((DOMDocumentImpl *)sDocument)->cloneString(value);
00357     }
00358 }
00359 
00360 void DOMDocumentTypeImpl::setInternalSubset(const XMLCh *value)
00361 {
00362     DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument();
00363     if (doc != 0)
00364         fInternalSubset = doc->cloneString(value);
00365     else {
00366         XMLMutexLock lock(sDocumentMutex);
00367         fInternalSubset = ((DOMDocumentImpl *)sDocument)->cloneString(value);
00368     }
00369 }
00370 
00371 void DOMDocumentTypeImpl::release()
00372 {
00373     if (fNode.isOwned()) {
00374         if (fNode.isToBeReleased()) {
00375             // we are calling from documnet.release() which will notify the user data handler
00376             if (fIsCreatedFromHeap) {
00377                 DOMDocumentType* docType = this;
00378                 delete docType;
00379             }
00380         }
00381         else
00382             throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
00383     }
00384     else {
00385         if (fIsCreatedFromHeap) {
00386             fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
00387             DOMDocumentType* docType = this;
00388             delete docType;
00389         }
00390         else {
00391             DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument();
00392             if (doc) {
00393                 fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
00394                 doc->release(this, DOMMemoryManager::DOCUMENT_TYPE_OBJECT);
00395             }
00396             else {
00397                 // shouldn't reach here
00398                 throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
00399             }
00400         }
00401     }
00402 }
00403 
00404 
00405 //
00406 // Delegation for functions inherited from Node
00407 //
00408 
00409            DOMNode*         DOMDocumentTypeImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); }
00410            DOMNamedNodeMap* DOMDocumentTypeImpl::getAttributes() const                   {return fNode.getAttributes (); }
00411            DOMNodeList*     DOMDocumentTypeImpl::getChildNodes() const                   {return fParent.getChildNodes (); }
00412            DOMNode*         DOMDocumentTypeImpl::getFirstChild() const                   {return fParent.getFirstChild (); }
00413            DOMNode*         DOMDocumentTypeImpl::getLastChild() const                    {return fParent.getLastChild (); }
00414      const XMLCh*           DOMDocumentTypeImpl::getLocalName() const                    {return fNode.getLocalName (); }
00415      const XMLCh*           DOMDocumentTypeImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); }
00416            DOMNode*         DOMDocumentTypeImpl::getNextSibling() const                  {return fChild.getNextSibling (); }
00417      const XMLCh*           DOMDocumentTypeImpl::getNodeValue() const                    {return fNode.getNodeValue (); }
00418            DOMDocument*     DOMDocumentTypeImpl::getOwnerDocument() const                {return fParent.fOwnerDocument; }
00419      const XMLCh*           DOMDocumentTypeImpl::getPrefix() const                       {return fNode.getPrefix (); }
00420            DOMNode*         DOMDocumentTypeImpl::getParentNode() const                   {return fChild.getParentNode (this); }
00421            DOMNode*         DOMDocumentTypeImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); }
00422            bool             DOMDocumentTypeImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); }
00423            DOMNode*         DOMDocumentTypeImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
00424                                                                                          {return fParent.insertBefore (newChild, refChild); }
00425            void             DOMDocumentTypeImpl::normalize()                             {fParent.normalize (); }
00426            DOMNode*         DOMDocumentTypeImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); }
00427            DOMNode*         DOMDocumentTypeImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
00428                                                                                          {return fParent.replaceChild (newChild, oldChild); }
00429            void             DOMDocumentTypeImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); }
00430            bool             DOMDocumentTypeImpl::hasAttributes() const                   {return fNode.hasAttributes(); }
00431            bool             DOMDocumentTypeImpl::isSameNode(const DOMNode* other) const  {return fNode.isSameNode(other); }
00432            void*            DOMDocumentTypeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
00433                                                                                          {return fNode.setUserData(key, data, handler); }
00434            void*            DOMDocumentTypeImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); }
00435            const XMLCh*     DOMDocumentTypeImpl::getBaseURI() const                      {return fNode.getBaseURI(); }
00436            short            DOMDocumentTypeImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); }
00437            const XMLCh*     DOMDocumentTypeImpl::getTextContent() const                  {return fNode.getTextContent(); }
00438            void             DOMDocumentTypeImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
00439            const XMLCh*     DOMDocumentTypeImpl::lookupPrefix(const XMLCh* namespaceURI) const  {return fNode.lookupPrefix(namespaceURI); }
00440            bool             DOMDocumentTypeImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
00441            const XMLCh*     DOMDocumentTypeImpl::lookupNamespaceURI(const XMLCh* prefix) const  {return fNode.lookupNamespaceURI(prefix); }
00442 
00443 
00444 bool DOMDocumentTypeImpl::isEqualNode(const DOMNode* arg) const
00445 {
00446     if (isSameNode(arg)) {
00447         return true;
00448     }
00449 
00450     if (!fNode.isEqualNode(arg)) {
00451         return false;
00452     }
00453 
00454     DOMDocumentType* argDT = (DOMDocumentType*) arg;
00455     // check the string values
00456     if (!getPublicId()) {
00457         if (argDT->getPublicId()) {
00458             return false;
00459         }
00460     }
00461     else if (!XMLString::equals(getPublicId(), argDT->getPublicId())) {
00462         return false;
00463     }
00464 
00465     if (!getSystemId()) {
00466         if (argDT->getSystemId()) {
00467             return false;
00468         }
00469     }
00470     else if (!XMLString::equals(getSystemId(), argDT->getSystemId())) {
00471         return false;
00472     }
00473 
00474     if (!getInternalSubset()) {
00475         if (argDT->getInternalSubset()) {
00476             return false;
00477         }
00478     }
00479     else if (!XMLString::equals(getInternalSubset(), argDT->getInternalSubset())) {
00480         return false;
00481     }
00482 
00483     // check the notations
00484     if (getNotations()) {
00485         if (!argDT->getNotations())
00486             return false;
00487 
00488         DOMNamedNodeMap* map1 = getNotations();
00489         DOMNamedNodeMap* map2 = argDT->getNotations();
00490 
00491         XMLSize_t len = map1->getLength();
00492         if (len != map2->getLength()) {
00493             return false;
00494         }
00495         for (XMLSize_t i = 0; i < len; i++) {
00496             DOMNode* n1 = map1->item(i);
00497             DOMNode* n2 = map2->getNamedItem(n1->getNodeName());
00498             if (!n2 || !n1->isEqualNode(n2)) {
00499                 return false;
00500             }
00501         }
00502     }
00503     else {
00504         if (argDT->getNotations())
00505             return false;
00506     }
00507 
00508     // check the entities
00509     if (getEntities()) {
00510         if (!argDT->getEntities())
00511             return false;
00512 
00513         DOMNamedNodeMap* map1 = getEntities();
00514         DOMNamedNodeMap* map2 = argDT->getEntities();
00515 
00516         XMLSize_t len = map1->getLength();
00517         if (len != map2->getLength()) {
00518             return false;
00519         }
00520         for (XMLSize_t i = 0; i < len; i++) {
00521             DOMNode* n1 = map1->item(i);
00522             DOMNode* n2 = map2->getNamedItem(n1->getNodeName());
00523             if (!n2 || !n1->isEqualNode(n2)) {
00524                 return false;
00525             }
00526         }
00527     }
00528     else {
00529         if (argDT->getEntities())
00530             return false;
00531     }
00532 
00533     return fParent.isEqualNode(arg);
00534 }
00535 
00536 bool DOMDocumentTypeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
00537 {
00538     // check for 'DOMDocumentTypeImpl' or '+DOMDocumentTypeImpl'
00539     if(feature && *feature)
00540     {
00541         if((*feature==chPlus && XMLString::equals(feature+1, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl)) ||
00542            XMLString::equals(feature, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl))
00543             return true;
00544     }
00545     return fNode.isSupported (feature, version);
00546 }
00547 
00548 void* DOMDocumentTypeImpl::getFeature(const XMLCh* feature, const XMLCh* version) const
00549 {
00550     if(XMLString::equals(feature, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl))
00551         return (DOMDocumentTypeImpl*)this;
00552     return fNode.getFeature(feature,version);
00553 }
00554 
00555 XERCES_CPP_NAMESPACE_END