source: icXML/icXML-devel/src/xercesc/dom/impl/DOMDocumentTypeImpl.cpp @ 2722

Last change on this file since 2722 was 2722, checked in by cameron, 6 years ago

Original Xerces files with import mods for icxercesc

File size: 18.9 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: DOMDocumentTypeImpl.cpp 678709 2008-07-22 10:56:56Z borisk $
20 */
21
22#include "DOMDocumentTypeImpl.hpp"
23#include <xercesc/dom/DOMNode.hpp>
24#include <xercesc/dom/DOMException.hpp>
25#include <xercesc/dom/DOMImplementationRegistry.hpp>
26#include <xercesc/dom/DOMImplementation.hpp>
27#include <xercesc/util/XMLUniDefs.hpp>
28#include <xercesc/util/XMLChar.hpp>
29#include <xercesc/util/Mutexes.hpp>
30#include <icxercesc/util/PlatformUtils.hpp>
31#include <xercesc/util/XMLInitializer.hpp>
32
33#include "DOMNamedNodeMapImpl.hpp"
34#include "DOMDocumentImpl.hpp"
35#include "DOMCasts.hpp"
36
37XERCES_CPP_NAMESPACE_BEGIN
38
39static DOMDocument* sDocument = 0;
40static XMLMutex*    sDocumentMutex = 0;
41
42void XMLInitializer::initializeDOMDocumentTypeImpl()
43{
44    sDocumentMutex = new XMLMutex(XMLPlatformUtils::fgMemoryManager);
45
46    static const XMLCh gCoreStr[] = { chLatin_C, chLatin_o, chLatin_r, chLatin_e, chNull };
47    DOMImplementation* impl =  DOMImplementationRegistry::getDOMImplementation(gCoreStr);
48    sDocument = impl->createDocument(); // document type object (DTD).
49}
50
51void XMLInitializer::terminateDOMDocumentTypeImpl()
52{
53    sDocument->release();
54    sDocument = 0;
55
56    delete sDocumentMutex;
57    sDocumentMutex = 0;
58}
59
60DOMDocumentTypeImpl::DOMDocumentTypeImpl(DOMDocument *ownerDoc,
61                                   const XMLCh *dtName,
62                                   bool heap)
63    : fNode(ownerDoc),
64    fParent(ownerDoc),
65    fName(0),
66    fEntities(0),
67    fNotations(0),
68    fElements(0),
69    fPublicId(0),
70    fSystemId(0),
71    fInternalSubset(0),
72    fIntSubsetReading(false),
73    fIsCreatedFromHeap(heap)
74{
75    if (ownerDoc)
76    {
77        fName = ((DOMDocumentImpl *)ownerDoc)->getPooledString(dtName);
78        fEntities = new (ownerDoc) DOMNamedNodeMapImpl(this);
79        fNotations= new (ownerDoc) DOMNamedNodeMapImpl(this);
80        fElements = new (ownerDoc) DOMNamedNodeMapImpl(this);
81    }
82    else
83    {
84        XMLMutexLock lock(sDocumentMutex);
85        DOMDocument* doc = sDocument;
86        fName = ((DOMDocumentImpl *)doc)->getPooledString(dtName);
87        fEntities = new (doc) DOMNamedNodeMapImpl(this);
88        fNotations= new (doc) DOMNamedNodeMapImpl(this);
89        fElements = new (doc) DOMNamedNodeMapImpl(this);
90    }
91}
92
93
94//Introduced in DOM Level 2
95DOMDocumentTypeImpl::DOMDocumentTypeImpl(DOMDocument *ownerDoc,
96                                   const XMLCh *qualifiedName,
97                                   const XMLCh *pubId,
98                                   const XMLCh *sysId,
99                                   bool heap)
100    : fNode(ownerDoc),
101    fParent(ownerDoc),
102    fName(0),
103    fEntities(0),
104    fNotations(0),
105    fElements(0),
106    fPublicId(0),
107    fSystemId(0),
108    fInternalSubset(0),
109    fIntSubsetReading(false),
110    fIsCreatedFromHeap(heap)
111{
112    int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName);
113    if (index < 0)
114        throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
115    else if (index > 0)
116    {
117        // we have to make sure the qualifiedName has correct prefix and localName
118        // although we don't really to store them separately
119        XMLCh* newName;
120        XMLCh temp[256];
121        if (index >= 255)
122            newName = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
123            (
124                (XMLString::stringLen(qualifiedName)+1) * sizeof(XMLCh)
125            );//new XMLCh[XMLString::stringLen(qualifiedName)+1];
126        else
127            newName = temp;
128
129        XMLString::copyNString(newName, qualifiedName, index);
130        newName[index] = chNull;
131
132        // Before we carry on, we should check if the prefix or localName are valid XMLName
133        if (ownerDoc) {
134            if (!((DOMDocumentImpl*)ownerDoc)->isXMLName(newName) || !((DOMDocumentImpl*)ownerDoc)->isXMLName(qualifiedName+index+1))
135                throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
136        }
137        else {
138            // document is not there yet, so assume XML 1.0
139            if (!XMLChar1_0::isValidName(newName) || !XMLChar1_0::isValidName(qualifiedName+index+1))
140                throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
141        }
142
143        if (index >= 255)
144            XMLPlatformUtils::fgMemoryManager->deallocate(newName);//delete[] newName;
145    }
146
147    if (ownerDoc)
148    {
149        DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc;
150        fPublicId = docImpl->cloneString(pubId);
151        fSystemId = docImpl->cloneString(sysId);
152        fName = ((DOMDocumentImpl *)ownerDoc)->getPooledString(qualifiedName);
153        fEntities = new (ownerDoc) DOMNamedNodeMapImpl(this);
154        fNotations= new (ownerDoc) DOMNamedNodeMapImpl(this);
155        fElements = new (ownerDoc) DOMNamedNodeMapImpl(this);
156    }
157    else
158    {
159        XMLMutexLock lock(sDocumentMutex);
160        DOMDocument* doc = sDocument;
161        fPublicId = ((DOMDocumentImpl*) doc)->cloneString(pubId);
162        fSystemId = ((DOMDocumentImpl*) doc)->cloneString(sysId);
163        fName = ((DOMDocumentImpl*) doc)->getPooledString(qualifiedName);
164        fEntities = new (doc) DOMNamedNodeMapImpl(this);
165        fNotations= new (doc) DOMNamedNodeMapImpl(this);
166        fElements = new (doc) DOMNamedNodeMapImpl(this);
167    }
168}
169
170
171DOMDocumentTypeImpl::DOMDocumentTypeImpl(const DOMDocumentTypeImpl &other, bool heap, bool deep)
172    : fNode(other.fNode),
173    fParent(other.fParent),
174    fChild(other.fChild),
175    fName(0),
176    fEntities(0),
177    fNotations(0),
178    fElements(0),
179    fPublicId(0),
180    fSystemId(0),
181    fInternalSubset(0),
182    fIntSubsetReading(other.fIntSubsetReading),
183    fIsCreatedFromHeap(heap)
184{
185    fName = other.fName;
186
187    //DOM Level 2
188    fPublicId        = other.fPublicId;
189    fSystemId        = other.fSystemId;
190    fInternalSubset  = other.fInternalSubset;
191
192    if ((DOMDocumentImpl *)this->fNode.getOwnerDocument() && deep)
193        fParent.cloneChildren(&other);
194
195    fEntities = other.fEntities->cloneMap(this);
196    fNotations= other.fNotations->cloneMap(this);
197    fElements = other.fElements->cloneMap(this);
198}
199
200
201DOMDocumentTypeImpl::~DOMDocumentTypeImpl()
202{
203}
204
205
206DOMNode *DOMDocumentTypeImpl::cloneNode(bool deep) const
207{
208    DOMNode* newNode = 0;
209    DOMDocument* doc = castToNodeImpl(this)->getOwnerDocument();
210    if (doc != 0)
211        newNode = new (doc, DOMMemoryManager::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(*this, false, deep);
212    else
213    {
214        XMLMutexLock lock(sDocumentMutex);
215        newNode = new (sDocument, DOMMemoryManager::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(*this, false, deep);
216    }
217
218    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
219    return newNode;
220}
221
222/**
223 * NON-DOM
224 * set the ownerDocument of this node and its children
225 */
226void DOMDocumentTypeImpl::setOwnerDocument(DOMDocument *doc) {
227
228    if (castToNodeImpl(this)->getOwnerDocument()) {
229        fNode.setOwnerDocument(doc);
230        fParent.setOwnerDocument(doc);
231    }
232    else {
233        if (doc) {
234            DOMDocumentImpl *docImpl = (DOMDocumentImpl *)doc;
235
236            fPublicId = docImpl->cloneString(fPublicId);
237            fSystemId = docImpl->cloneString(fSystemId);
238            fInternalSubset = docImpl->cloneString(fInternalSubset);
239            fName = docImpl->getPooledString(fName);
240
241            fNode.setOwnerDocument(doc);
242            fParent.setOwnerDocument(doc);
243
244            DOMNamedNodeMapImpl* entitiesTemp = fEntities->cloneMap(this);
245            DOMNamedNodeMapImpl* notationsTemp = fNotations->cloneMap(this);
246            DOMNamedNodeMapImpl* elementsTemp = fElements->cloneMap(this);
247
248            fEntities = entitiesTemp;
249            fNotations = notationsTemp;
250            fElements = elementsTemp;
251        }
252    }
253}
254
255const XMLCh * DOMDocumentTypeImpl::getNodeName() const
256{
257    return fName;
258}
259
260
261DOMNode::NodeType DOMDocumentTypeImpl::getNodeType()  const {
262    return DOMNode::DOCUMENT_TYPE_NODE;
263}
264
265
266DOMNamedNodeMap *DOMDocumentTypeImpl::getEntities() const
267{
268    return fEntities;
269}
270
271
272
273const XMLCh * DOMDocumentTypeImpl::getName() const
274{
275    return fName;
276}
277
278
279DOMNamedNodeMap *DOMDocumentTypeImpl::getNotations() const
280{
281    return fNotations;
282}
283
284
285DOMNamedNodeMap *DOMDocumentTypeImpl::getElements() const
286{
287    return fElements;
288}
289
290
291void DOMDocumentTypeImpl::setNodeValue(const XMLCh *val)
292{
293    fNode.setNodeValue(val);
294}
295
296
297void DOMDocumentTypeImpl::setReadOnly(bool readOnl, bool deep)
298{
299    fNode.setReadOnly(readOnl,deep);
300    if (fEntities)
301        fEntities->setReadOnly(readOnl,true);
302    if (fNotations)
303        fNotations->setReadOnly(readOnl,true);
304}
305
306
307//Introduced in DOM Level 2
308
309const XMLCh * DOMDocumentTypeImpl::getPublicId() const
310{
311    return fPublicId;
312}
313
314
315const XMLCh * DOMDocumentTypeImpl::getSystemId() const
316{
317    return fSystemId;
318}
319
320
321const XMLCh * DOMDocumentTypeImpl::getInternalSubset() const
322{
323    return fInternalSubset;
324}
325
326bool DOMDocumentTypeImpl::isIntSubsetReading() const
327{
328    return fIntSubsetReading;
329}
330
331
332//set functions
333
334void DOMDocumentTypeImpl::setPublicId(const XMLCh *value)
335{
336    // revist.  Why shouldn't 0 be assigned like any other value?
337    if (value == 0)
338        return;
339
340    DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument();
341    if (doc != 0)
342        fPublicId = doc->cloneString(value);
343    else {
344        XMLMutexLock lock(sDocumentMutex);
345        fPublicId = ((DOMDocumentImpl *)sDocument)->cloneString(value);
346    }
347}
348
349void DOMDocumentTypeImpl::setSystemId(const XMLCh *value)
350{
351    DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument();
352    if (doc != 0)
353        fSystemId = doc->cloneString(value);
354    else {
355        XMLMutexLock lock(sDocumentMutex);
356        fSystemId = ((DOMDocumentImpl *)sDocument)->cloneString(value);
357    }
358}
359
360void DOMDocumentTypeImpl::setInternalSubset(const XMLCh *value)
361{
362    DOMDocumentImpl* doc = (DOMDocumentImpl *)castToNodeImpl(this)->getOwnerDocument();
363    if (doc != 0)
364        fInternalSubset = doc->cloneString(value);
365    else {
366        XMLMutexLock lock(sDocumentMutex);
367        fInternalSubset = ((DOMDocumentImpl *)sDocument)->cloneString(value);
368    }
369}
370
371void DOMDocumentTypeImpl::release()
372{
373    if (fNode.isOwned()) {
374        if (fNode.isToBeReleased()) {
375            // we are calling from documnet.release() which will notify the user data handler
376            if (fIsCreatedFromHeap) {
377                DOMDocumentType* docType = this;
378                delete docType;
379            }
380        }
381        else
382            throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
383    }
384    else {
385        if (fIsCreatedFromHeap) {
386            fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
387            DOMDocumentType* docType = this;
388            delete docType;
389        }
390        else {
391            DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument();
392            if (doc) {
393                fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
394                doc->release(this, DOMMemoryManager::DOCUMENT_TYPE_OBJECT);
395            }
396            else {
397                // shouldn't reach here
398                throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
399            }
400        }
401    }
402}
403
404
405//
406// Delegation for functions inherited from Node
407//
408
409           DOMNode*         DOMDocumentTypeImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); }
410           DOMNamedNodeMap* DOMDocumentTypeImpl::getAttributes() const                   {return fNode.getAttributes (); }
411           DOMNodeList*     DOMDocumentTypeImpl::getChildNodes() const                   {return fParent.getChildNodes (); }
412           DOMNode*         DOMDocumentTypeImpl::getFirstChild() const                   {return fParent.getFirstChild (); }
413           DOMNode*         DOMDocumentTypeImpl::getLastChild() const                    {return fParent.getLastChild (); }
414     const XMLCh*           DOMDocumentTypeImpl::getLocalName() const                    {return fNode.getLocalName (); }
415     const XMLCh*           DOMDocumentTypeImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); }
416           DOMNode*         DOMDocumentTypeImpl::getNextSibling() const                  {return fChild.getNextSibling (); }
417     const XMLCh*           DOMDocumentTypeImpl::getNodeValue() const                    {return fNode.getNodeValue (); }
418           DOMDocument*     DOMDocumentTypeImpl::getOwnerDocument() const                {return fParent.fOwnerDocument; }
419     const XMLCh*           DOMDocumentTypeImpl::getPrefix() const                       {return fNode.getPrefix (); }
420           DOMNode*         DOMDocumentTypeImpl::getParentNode() const                   {return fChild.getParentNode (this); }
421           DOMNode*         DOMDocumentTypeImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); }
422           bool             DOMDocumentTypeImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); }
423           DOMNode*         DOMDocumentTypeImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
424                                                                                         {return fParent.insertBefore (newChild, refChild); }
425           void             DOMDocumentTypeImpl::normalize()                             {fParent.normalize (); }
426           DOMNode*         DOMDocumentTypeImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); }
427           DOMNode*         DOMDocumentTypeImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
428                                                                                         {return fParent.replaceChild (newChild, oldChild); }
429           void             DOMDocumentTypeImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); }
430           bool             DOMDocumentTypeImpl::hasAttributes() const                   {return fNode.hasAttributes(); }
431           bool             DOMDocumentTypeImpl::isSameNode(const DOMNode* other) const  {return fNode.isSameNode(other); }
432           void*            DOMDocumentTypeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
433                                                                                         {return fNode.setUserData(key, data, handler); }
434           void*            DOMDocumentTypeImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); }
435           const XMLCh*     DOMDocumentTypeImpl::getBaseURI() const                      {return fNode.getBaseURI(); }
436           short            DOMDocumentTypeImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); }
437           const XMLCh*     DOMDocumentTypeImpl::getTextContent() const                  {return fNode.getTextContent(); }
438           void             DOMDocumentTypeImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
439           const XMLCh*     DOMDocumentTypeImpl::lookupPrefix(const XMLCh* namespaceURI) const  {return fNode.lookupPrefix(namespaceURI); }
440           bool             DOMDocumentTypeImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
441           const XMLCh*     DOMDocumentTypeImpl::lookupNamespaceURI(const XMLCh* prefix) const  {return fNode.lookupNamespaceURI(prefix); }
442
443
444bool DOMDocumentTypeImpl::isEqualNode(const DOMNode* arg) const
445{
446    if (isSameNode(arg)) {
447        return true;
448    }
449
450    if (!fNode.isEqualNode(arg)) {
451        return false;
452    }
453
454    DOMDocumentType* argDT = (DOMDocumentType*) arg;
455    // check the string values
456    if (!getPublicId()) {
457        if (argDT->getPublicId()) {
458            return false;
459        }
460    }
461    else if (!XMLString::equals(getPublicId(), argDT->getPublicId())) {
462        return false;
463    }
464
465    if (!getSystemId()) {
466        if (argDT->getSystemId()) {
467            return false;
468        }
469    }
470    else if (!XMLString::equals(getSystemId(), argDT->getSystemId())) {
471        return false;
472    }
473
474    if (!getInternalSubset()) {
475        if (argDT->getInternalSubset()) {
476            return false;
477        }
478    }
479    else if (!XMLString::equals(getInternalSubset(), argDT->getInternalSubset())) {
480        return false;
481    }
482
483    // check the notations
484    if (getNotations()) {
485        if (!argDT->getNotations())
486            return false;
487
488        DOMNamedNodeMap* map1 = getNotations();
489        DOMNamedNodeMap* map2 = argDT->getNotations();
490
491        XMLSize_t len = map1->getLength();
492        if (len != map2->getLength()) {
493            return false;
494        }
495        for (XMLSize_t i = 0; i < len; i++) {
496            DOMNode* n1 = map1->item(i);
497            DOMNode* n2 = map2->getNamedItem(n1->getNodeName());
498            if (!n2 || !n1->isEqualNode(n2)) {
499                return false;
500            }
501        }
502    }
503    else {
504        if (argDT->getNotations())
505            return false;
506    }
507
508    // check the entities
509    if (getEntities()) {
510        if (!argDT->getEntities())
511            return false;
512
513        DOMNamedNodeMap* map1 = getEntities();
514        DOMNamedNodeMap* map2 = argDT->getEntities();
515
516        XMLSize_t len = map1->getLength();
517        if (len != map2->getLength()) {
518            return false;
519        }
520        for (XMLSize_t i = 0; i < len; i++) {
521            DOMNode* n1 = map1->item(i);
522            DOMNode* n2 = map2->getNamedItem(n1->getNodeName());
523            if (!n2 || !n1->isEqualNode(n2)) {
524                return false;
525            }
526        }
527    }
528    else {
529        if (argDT->getEntities())
530            return false;
531    }
532
533    return fParent.isEqualNode(arg);
534}
535
536bool DOMDocumentTypeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
537{
538    // check for 'DOMDocumentTypeImpl' or '+DOMDocumentTypeImpl'
539    if(feature && *feature)
540    {
541        if((*feature==chPlus && XMLString::equals(feature+1, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl)) ||
542           XMLString::equals(feature, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl))
543            return true;
544    }
545    return fNode.isSupported (feature, version);
546}
547
548void* DOMDocumentTypeImpl::getFeature(const XMLCh* feature, const XMLCh* version) const
549{
550    if(XMLString::equals(feature, XMLUni::fgXercescInterfaceDOMDocumentTypeImpl))
551        return (DOMDocumentTypeImpl*)this;
552    return fNode.getFeature(feature,version);
553}
554
555XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.