1 | // |
2 | // AbstractNode.cpp |
3 | // |
4 | // Library: XML |
5 | // Package: DOM |
6 | // Module: DOM |
7 | // |
8 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/DOM/AbstractNode.h" |
16 | #include "Poco/DOM/Document.h" |
17 | #include "Poco/DOM/ChildNodesList.h" |
18 | #include "Poco/DOM/EventDispatcher.h" |
19 | #include "Poco/DOM/DOMException.h" |
20 | #include "Poco/DOM/EventException.h" |
21 | #include "Poco/DOM/DOMImplementation.h" |
22 | #include "Poco/DOM/Attr.h" |
23 | #include "Poco/XML/Name.h" |
24 | #include "Poco/DOM/AutoPtr.h" |
25 | |
26 | |
27 | namespace Poco { |
28 | namespace XML { |
29 | |
30 | |
31 | const XMLString AbstractNode::NODE_NAME = toXMLString("#node" ); |
32 | const XMLString AbstractNode::EMPTY_STRING; |
33 | |
34 | |
35 | AbstractNode::AbstractNode(Document* pOwnerDocument): |
36 | _pParent(0), |
37 | _pNext(0), |
38 | _pOwner(pOwnerDocument), |
39 | _pEventDispatcher(0) |
40 | { |
41 | } |
42 | |
43 | |
44 | AbstractNode::AbstractNode(Document* pOwnerDocument, const AbstractNode& node): |
45 | _pParent(0), |
46 | _pNext(0), |
47 | _pOwner(pOwnerDocument), |
48 | _pEventDispatcher(0) |
49 | { |
50 | } |
51 | |
52 | |
53 | AbstractNode::~AbstractNode() |
54 | { |
55 | delete _pEventDispatcher; |
56 | if (_pNext) _pNext->release(); |
57 | } |
58 | |
59 | |
60 | void AbstractNode::autoRelease() |
61 | { |
62 | _pOwner->autoReleasePool().add(this); |
63 | } |
64 | |
65 | |
66 | const XMLString& AbstractNode::nodeName() const |
67 | { |
68 | return NODE_NAME; |
69 | } |
70 | |
71 | |
72 | const XMLString& AbstractNode::getNodeValue() const |
73 | { |
74 | return EMPTY_STRING; |
75 | } |
76 | |
77 | |
78 | void AbstractNode::setNodeValue(const XMLString& value) |
79 | { |
80 | throw DOMException(DOMException::NO_DATA_ALLOWED_ERR); |
81 | } |
82 | |
83 | |
84 | Node* AbstractNode::parentNode() const |
85 | { |
86 | return _pParent; |
87 | } |
88 | |
89 | |
90 | NodeList* AbstractNode::childNodes() const |
91 | { |
92 | return new ChildNodesList(this); |
93 | } |
94 | |
95 | |
96 | Node* AbstractNode::firstChild() const |
97 | { |
98 | return 0; |
99 | } |
100 | |
101 | |
102 | Node* AbstractNode::lastChild() const |
103 | { |
104 | return 0; |
105 | } |
106 | |
107 | |
108 | Node* AbstractNode::previousSibling() const |
109 | { |
110 | if (_pParent) |
111 | { |
112 | AbstractNode* pSibling = _pParent->_pFirstChild; |
113 | while (pSibling) |
114 | { |
115 | if (pSibling->_pNext == this) return pSibling; |
116 | pSibling = pSibling->_pNext; |
117 | } |
118 | } |
119 | return 0; |
120 | } |
121 | |
122 | |
123 | Node* AbstractNode::nextSibling() const |
124 | { |
125 | return _pNext; |
126 | } |
127 | |
128 | |
129 | NamedNodeMap* AbstractNode::attributes() const |
130 | { |
131 | return 0; |
132 | } |
133 | |
134 | |
135 | Document* AbstractNode::ownerDocument() const |
136 | { |
137 | return _pOwner; |
138 | } |
139 | |
140 | |
141 | Node* AbstractNode::insertBefore(Node* newChild, Node* refChild) |
142 | { |
143 | throw DOMException(DOMException::HIERARCHY_REQUEST_ERR); |
144 | } |
145 | |
146 | |
147 | Node* AbstractNode::replaceChild(Node* newChild, Node* oldChild) |
148 | { |
149 | throw DOMException(DOMException::HIERARCHY_REQUEST_ERR); |
150 | } |
151 | |
152 | |
153 | Node* AbstractNode::removeChild(Node* oldChild) |
154 | { |
155 | throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR); |
156 | } |
157 | |
158 | |
159 | Node* AbstractNode::appendChild(Node* newChild) |
160 | { |
161 | throw DOMException(DOMException::HIERARCHY_REQUEST_ERR); |
162 | } |
163 | |
164 | |
165 | bool AbstractNode::hasChildNodes() const |
166 | { |
167 | return false; |
168 | } |
169 | |
170 | |
171 | Node* AbstractNode::cloneNode(bool deep) const |
172 | { |
173 | return copyNode(deep, _pOwner); |
174 | } |
175 | |
176 | |
177 | void AbstractNode::normalize() |
178 | { |
179 | } |
180 | |
181 | |
182 | bool AbstractNode::isSupported(const XMLString& feature, const XMLString& version) const |
183 | { |
184 | return DOMImplementation::instance().hasFeature(feature, version); |
185 | } |
186 | |
187 | |
188 | const XMLString& AbstractNode::namespaceURI() const |
189 | { |
190 | return EMPTY_STRING; |
191 | } |
192 | |
193 | |
194 | XMLString AbstractNode::prefix() const |
195 | { |
196 | return EMPTY_STRING; |
197 | } |
198 | |
199 | |
200 | const XMLString& AbstractNode::localName() const |
201 | { |
202 | return EMPTY_STRING; |
203 | } |
204 | |
205 | |
206 | bool AbstractNode::hasAttributes() const |
207 | { |
208 | return false; |
209 | } |
210 | |
211 | |
212 | XMLString AbstractNode::innerText() const |
213 | { |
214 | return EMPTY_STRING; |
215 | } |
216 | |
217 | |
218 | Node* AbstractNode::getNodeByPath(const XMLString& path) const |
219 | { |
220 | return 0; |
221 | } |
222 | |
223 | |
224 | Node* AbstractNode::getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const |
225 | { |
226 | return 0; |
227 | } |
228 | |
229 | |
230 | void AbstractNode::addEventListener(const XMLString& type, EventListener* listener, bool useCapture) |
231 | { |
232 | if (_pEventDispatcher) |
233 | _pEventDispatcher->removeEventListener(type, listener, useCapture); |
234 | else |
235 | _pEventDispatcher = new EventDispatcher; |
236 | |
237 | _pEventDispatcher->addEventListener(type, listener, useCapture); |
238 | } |
239 | |
240 | |
241 | void AbstractNode::removeEventListener(const XMLString& type, EventListener* listener, bool useCapture) |
242 | { |
243 | if (_pEventDispatcher) |
244 | _pEventDispatcher->removeEventListener(type, listener, useCapture); |
245 | } |
246 | |
247 | |
248 | bool AbstractNode::dispatchEvent(Event* evt) |
249 | { |
250 | if (eventsSuspended()) return true; |
251 | |
252 | if (evt->type().empty()) throw EventException(EventException::UNSPECIFIED_EVENT_TYPE_ERR); |
253 | |
254 | evt->setTarget(this); |
255 | evt->setCurrentPhase(Event::CAPTURING_PHASE); |
256 | |
257 | if (_pParent) _pParent->captureEvent(evt); |
258 | |
259 | if (_pEventDispatcher && !evt->isStopped()) |
260 | { |
261 | evt->setCurrentPhase(Event::AT_TARGET); |
262 | evt->setCurrentTarget(this); |
263 | _pEventDispatcher->dispatchEvent(evt); |
264 | } |
265 | if (!evt->isStopped() && evt->bubbles() && _pParent) |
266 | { |
267 | evt->setCurrentPhase(Event::BUBBLING_PHASE); |
268 | _pParent->bubbleEvent(evt); |
269 | } |
270 | |
271 | return evt->isCanceled(); |
272 | } |
273 | |
274 | |
275 | void AbstractNode::captureEvent(Event* evt) |
276 | { |
277 | if (_pParent) |
278 | _pParent->captureEvent(evt); |
279 | |
280 | if (_pEventDispatcher && !evt->isStopped()) |
281 | { |
282 | evt->setCurrentTarget(this); |
283 | _pEventDispatcher->captureEvent(evt); |
284 | } |
285 | } |
286 | |
287 | |
288 | void AbstractNode::bubbleEvent(Event* evt) |
289 | { |
290 | evt->setCurrentTarget(this); |
291 | if (_pEventDispatcher) |
292 | { |
293 | _pEventDispatcher->bubbleEvent(evt); |
294 | } |
295 | if (_pParent && !evt->isStopped()) |
296 | _pParent->bubbleEvent(evt); |
297 | } |
298 | |
299 | |
300 | void AbstractNode::dispatchSubtreeModified() |
301 | { |
302 | AutoPtr<MutationEvent> pEvent = new MutationEvent(_pOwner, MutationEvent::DOMSubtreeModified, this, true, false, 0); |
303 | dispatchEvent(pEvent.get()); |
304 | } |
305 | |
306 | |
307 | void AbstractNode::dispatchNodeInserted() |
308 | { |
309 | AutoPtr<MutationEvent> pEvent = new MutationEvent(_pOwner, MutationEvent::DOMNodeInserted, this, true, false, parentNode()); |
310 | dispatchEvent(pEvent.get()); |
311 | } |
312 | |
313 | |
314 | void AbstractNode::dispatchNodeRemoved() |
315 | { |
316 | AutoPtr<MutationEvent> pEvent = new MutationEvent(_pOwner, MutationEvent::DOMNodeRemoved, this, true, false, parentNode()); |
317 | dispatchEvent(pEvent.get()); |
318 | } |
319 | |
320 | |
321 | void AbstractNode::dispatchNodeRemovedFromDocument() |
322 | { |
323 | AutoPtr<MutationEvent> pEvent = new MutationEvent(_pOwner, MutationEvent::DOMNodeRemovedFromDocument, this, false, false, 0); |
324 | dispatchEvent(pEvent.get()); |
325 | } |
326 | |
327 | |
328 | void AbstractNode::dispatchNodeInsertedIntoDocument() |
329 | { |
330 | AutoPtr<MutationEvent> pEvent = new MutationEvent(_pOwner, MutationEvent::DOMNodeInsertedIntoDocument, this, false, false, 0); |
331 | dispatchEvent(pEvent.get()); |
332 | } |
333 | |
334 | |
335 | void AbstractNode::dispatchAttrModified(Attr* pAttr, MutationEvent::AttrChangeType changeType, const XMLString& prevValue, const XMLString& newValue) |
336 | { |
337 | AutoPtr<MutationEvent> pEvent = new MutationEvent(_pOwner, MutationEvent::DOMAttrModified, this, true, false, pAttr, prevValue, newValue, pAttr->name(), changeType); |
338 | dispatchEvent(pEvent.get()); |
339 | } |
340 | |
341 | |
342 | void AbstractNode::dispatchCharacterDataModified(const XMLString& prevValue, const XMLString& newValue) |
343 | { |
344 | AutoPtr<MutationEvent> pEvent = new MutationEvent(_pOwner, MutationEvent::DOMCharacterDataModified, this, true, false, 0, prevValue, newValue, EMPTY_STRING, MutationEvent::MODIFICATION); |
345 | dispatchEvent(pEvent.get()); |
346 | } |
347 | |
348 | |
349 | bool AbstractNode::events() const |
350 | { |
351 | return _pOwner->events(); |
352 | } |
353 | |
354 | |
355 | bool AbstractNode::eventsSuspended() const |
356 | { |
357 | return _pOwner->eventsSuspended(); |
358 | } |
359 | |
360 | |
361 | void AbstractNode::setOwnerDocument(Document* pOwnerDocument) |
362 | { |
363 | _pOwner = pOwnerDocument; |
364 | } |
365 | |
366 | |
367 | } } // namespace Poco::XML |
368 | |