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$
20  */
21 
22 #include <xercesc/dom/DOMException.hpp>
23 #include <xercesc/dom/DOMNode.hpp>
24 #include <xercesc/dom/DOMEntityReference.hpp>
25 #include "DOMEntityImpl.hpp"
26 #include "DOMDocumentImpl.hpp"
27 
28 XERCES_CPP_NAMESPACE_BEGIN
29 
DOMEntityImpl(DOMDocument * ownerDoc,const XMLCh * eName)30 DOMEntityImpl::DOMEntityImpl(DOMDocument *ownerDoc, const XMLCh *eName)
31    : fNode(this, ownerDoc),
32      fParent(this, ownerDoc),
33      fPublicId(0),
34      fSystemId(0),
35      fNotationName(0),
36      fRefEntity(0),
37      fInputEncoding(0),
38      fXmlEncoding(0),
39      fXmlVersion(0),
40      fBaseURI(0),
41      fEntityRefNodeCloned(false)
42 {
43     fName        = ((DOMDocumentImpl *)ownerDoc)->getPooledString(eName);
44     fNode.setReadOnly(true, true);
45 }
46 
47 
DOMEntityImpl(const DOMEntityImpl & other,bool deep)48 DOMEntityImpl::DOMEntityImpl(const DOMEntityImpl &other, bool deep)
49     : DOMEntity(other),
50       fNode(this, other.fNode),
51       fParent(this, other.fParent),
52       fName(other.fName),
53       fPublicId(other.fPublicId),
54       fSystemId(other.fSystemId),
55       fNotationName(other.fNotationName),
56       fRefEntity(other.fRefEntity),
57       fInputEncoding(other.fInputEncoding),
58       fXmlEncoding(other.fXmlEncoding),
59       fXmlVersion(other.fXmlVersion),
60       fBaseURI(other.fBaseURI),
61       fEntityRefNodeCloned(false)
62 {
63     if (deep)
64         fParent.cloneChildren(&other);
65     fNode.setReadOnly(true, true);
66 }
67 
68 
~DOMEntityImpl()69 DOMEntityImpl::~DOMEntityImpl() {
70 }
71 
72 
cloneNode(bool deep) const73 DOMNode *DOMEntityImpl::cloneNode(bool deep) const
74 {
75     DOMNode* newNode = new (fParent.fOwnerDocument, DOMMemoryManager::ENTITY_OBJECT) DOMEntityImpl(*this, deep);
76     fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
77     return newNode;
78 }
79 
80 
getNodeName() const81 const XMLCh * DOMEntityImpl::getNodeName() const {
82     return fName;
83 }
84 
85 
getNodeType() const86 DOMNode::NodeType DOMEntityImpl::getNodeType() const {
87     return DOMNode::ENTITY_NODE;
88 }
89 
90 
getNotationName() const91 const XMLCh * DOMEntityImpl::getNotationName() const
92 {
93     return fNotationName;
94 }
95 
96 
getPublicId() const97 const XMLCh * DOMEntityImpl::getPublicId() const {
98     return fPublicId;
99 }
100 
101 
getSystemId() const102 const XMLCh * DOMEntityImpl::getSystemId() const
103 {
104     return fSystemId;
105 }
106 
107 
getBaseURI() const108 const XMLCh* DOMEntityImpl::getBaseURI() const
109 {
110     return fBaseURI;
111 }
112 
113 
setNodeValue(const XMLCh * arg)114 void DOMEntityImpl::setNodeValue(const XMLCh *arg)
115 {
116     fNode.setNodeValue(arg);
117 }
118 
119 
setNotationName(const XMLCh * arg)120 void DOMEntityImpl::setNotationName(const XMLCh *arg)
121 {
122     DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
123     fNotationName = doc->cloneString(arg);
124 }
125 
126 
setPublicId(const XMLCh * arg)127 void DOMEntityImpl::setPublicId(const XMLCh *arg)
128 {
129     DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
130     fPublicId = doc->cloneString(arg);
131 }
132 
133 
setSystemId(const XMLCh * arg)134 void DOMEntityImpl::setSystemId(const XMLCh *arg)
135 {
136     DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
137     fSystemId = doc->cloneString(arg);
138 }
139 
140 
setBaseURI(const XMLCh * baseURI)141 void DOMEntityImpl::setBaseURI(const XMLCh* baseURI) {
142     if (baseURI && *baseURI) {
143         XMLCh* temp = (XMLCh*) ((DOMDocumentImpl *)fParent.fOwnerDocument)->allocate((XMLString::stringLen(baseURI) + 9)*sizeof(XMLCh));
144         XMLString::fixURI(baseURI, temp);
145         fBaseURI = temp;
146     }
147     else
148         fBaseURI = 0;
149 }
150 
151 
setEntityRef(DOMEntityReference * other)152 void   DOMEntityImpl::setEntityRef(DOMEntityReference* other)
153 {
154     fRefEntity = other;
155 }
156 
157 
getEntityRef() const158 DOMEntityReference*  DOMEntityImpl::getEntityRef() const
159 {
160     return fRefEntity;
161 }
162 
cloneEntityRefTree() const163 void  DOMEntityImpl::cloneEntityRefTree() const
164 {
165     if (fEntityRefNodeCloned)
166         return;
167 
168     // cast off const.  This method is const because it is
169     //   called from a bunch of logically const methods, like
170     //   getFirstChild().
171     DOMEntityImpl *ncThis = (DOMEntityImpl *)this;
172 
173     //lazily clone the entityRef tree to this entity
174     if (fParent.fFirstChild != 0)
175         return;
176 
177     if (!fRefEntity)
178         return;
179 
180     ncThis->fEntityRefNodeCloned = true;
181     ncThis->fNode.setReadOnly(false, true);
182     ncThis->fParent.cloneChildren(fRefEntity);
183     ncThis->fNode.setReadOnly(true, true);
184 }
185 
getFirstChild() const186 DOMNode * DOMEntityImpl::getFirstChild() const
187 {
188     cloneEntityRefTree();
189     return fParent.fFirstChild;
190 }
191 
getLastChild() const192 DOMNode *   DOMEntityImpl::getLastChild() const
193 {
194     cloneEntityRefTree();
195     return fParent.getLastChild();
196 }
197 
getChildNodes() const198 DOMNodeList* DOMEntityImpl::getChildNodes() const
199 {
200     cloneEntityRefTree();
201     return this->fParent.getChildNodes();
202 
203 }
204 
hasChildNodes() const205 bool DOMEntityImpl::hasChildNodes() const
206 {
207     cloneEntityRefTree();
208     return fParent.fFirstChild!=0;
209 }
210 
211 
release()212 void DOMEntityImpl::release()
213 {
214     if (fNode.isOwned() && !fNode.isToBeReleased())
215         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
216 
217     DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument;
218     if (doc) {
219         fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
220         fParent.release();
221         doc->release(this, DOMMemoryManager::ENTITY_OBJECT);
222     }
223     else {
224         // shouldn't reach here
225         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
226     }
227 }
228 
229 //
230 //  Functions inherited from Node
231 //
232 
appendChild(DOMNode * newChild)233            DOMNode*         DOMEntityImpl::appendChild(DOMNode *newChild)          {cloneEntityRefTree(); return fParent.appendChild (newChild); }
getAttributes() const234            DOMNamedNodeMap* DOMEntityImpl::getAttributes() const                   {return fNode.getAttributes (); }
getLocalName() const235      const XMLCh*           DOMEntityImpl::getLocalName() const                    {return fNode.getLocalName (); }
getNamespaceURI() const236      const XMLCh*           DOMEntityImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); }
getNextSibling() const237            DOMNode*         DOMEntityImpl::getNextSibling() const                  {return fNode.getNextSibling (); }
getNodeValue() const238      const XMLCh*           DOMEntityImpl::getNodeValue() const                    {return fNode.getNodeValue (); }
getOwnerDocument() const239            DOMDocument*     DOMEntityImpl::getOwnerDocument() const                {return fParent.fOwnerDocument; }
getPrefix() const240      const XMLCh*           DOMEntityImpl::getPrefix() const                       {return fNode.getPrefix (); }
getParentNode() const241            DOMNode*         DOMEntityImpl::getParentNode() const                   {return fNode.getParentNode (); }
getPreviousSibling() const242            DOMNode*         DOMEntityImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); }
insertBefore(DOMNode * newChild,DOMNode * refChild)243            DOMNode*         DOMEntityImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
244                                                                                    {cloneEntityRefTree(); return fParent.insertBefore (newChild, refChild); }
normalize()245            void             DOMEntityImpl::normalize()                             {cloneEntityRefTree(); fParent.normalize (); }
removeChild(DOMNode * oldChild)246            DOMNode*         DOMEntityImpl::removeChild(DOMNode *oldChild)          {cloneEntityRefTree(); return fParent.removeChild (oldChild); }
replaceChild(DOMNode * newChild,DOMNode * oldChild)247            DOMNode*         DOMEntityImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
248                                                                                    {cloneEntityRefTree(); return fParent.replaceChild (newChild, oldChild); }
isSupported(const XMLCh * feature,const XMLCh * version) const249            bool             DOMEntityImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
250                                                                                    {return fNode.isSupported (feature, version); }
setPrefix(const XMLCh * prefix)251            void             DOMEntityImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); }
hasAttributes() const252            bool             DOMEntityImpl::hasAttributes() const                   {return fNode.hasAttributes(); }
isSameNode(const DOMNode * other) const253            bool             DOMEntityImpl::isSameNode(const DOMNode* other) const  {return fNode.isSameNode(other); }
isEqualNode(const DOMNode * arg) const254            bool             DOMEntityImpl::isEqualNode(const DOMNode* arg) const   {cloneEntityRefTree(); return fParent.isEqualNode(arg); }
setUserData(const XMLCh * key,void * data,DOMUserDataHandler * handler)255            void*            DOMEntityImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
256                                                                                    {return fNode.setUserData(key, data, handler); }
getUserData(const XMLCh * key) const257            void*            DOMEntityImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); }
compareDocumentPosition(const DOMNode * other) const258            short            DOMEntityImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); }
getTextContent() const259            const XMLCh*     DOMEntityImpl::getTextContent() const                  {return fNode.getTextContent(); }
setTextContent(const XMLCh * textContent)260            void             DOMEntityImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
lookupPrefix(const XMLCh * namespaceURI) const261            const XMLCh*     DOMEntityImpl::lookupPrefix(const XMLCh* namespaceURI) const  {return fNode.lookupPrefix(namespaceURI); }
isDefaultNamespace(const XMLCh * namespaceURI) const262            bool             DOMEntityImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
lookupNamespaceURI(const XMLCh * prefix) const263            const XMLCh*     DOMEntityImpl::lookupNamespaceURI(const XMLCh* prefix) const  {return fNode.lookupNamespaceURI(prefix); }
getFeature(const XMLCh * feature,const XMLCh * version) const264            void*            DOMEntityImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); }
265 
266 // Macro-in implementation accessors.
267 DOMNODEIMPL_IMPL(DOMEntityImpl);
268 DOMPARENTIMPL_IMPL(DOMEntityImpl);
269 
270 //Introduced in DOM Level 3
getInputEncoding() const271 const XMLCh* DOMEntityImpl::getInputEncoding() const {
272     return fInputEncoding;
273 }
274 
setInputEncoding(const XMLCh * actualEncoding)275 void DOMEntityImpl::setInputEncoding(const XMLCh* actualEncoding){
276     DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
277     fInputEncoding = doc->cloneString(actualEncoding);
278 }
279 
getXmlEncoding() const280 const XMLCh* DOMEntityImpl::getXmlEncoding() const {
281     return fXmlEncoding;
282 }
283 
setXmlEncoding(const XMLCh * encoding)284 void DOMEntityImpl::setXmlEncoding(const XMLCh* encoding){
285     DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
286     fXmlEncoding = doc->cloneString(encoding);
287 }
288 
getXmlVersion() const289 const XMLCh* DOMEntityImpl::getXmlVersion() const {
290     return fXmlVersion;
291 }
292 
setXmlVersion(const XMLCh * version)293 void DOMEntityImpl::setXmlVersion(const XMLCh* version){
294     DOMDocumentImpl *doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
295     fXmlVersion = doc->cloneString(version);
296 }
297 
298 XERCES_CPP_NAMESPACE_END
299