~ubuntu-branches/ubuntu/gutsy/poco/gutsy

« back to all changes in this revision

Viewing changes to XML/src/AbstractContainerNode.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Burghardt
  • Date: 2007-04-27 18:33:48 UTC
  • Revision ID: james.westby@ubuntu.com-20070427183348-xgnpct0qd6a2ip34
Tags: upstream-1.2.9
ImportĀ upstreamĀ versionĀ 1.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// AbstractContainerNode.cpp
 
3
//
 
4
// $Id: //poco/1.2/XML/src/AbstractContainerNode.cpp#1 $
 
5
//
 
6
// Library: XML
 
7
// Package: DOM
 
8
// Module:  DOM
 
9
//
 
10
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
 
11
// and Contributors.
 
12
//
 
13
// Permission is hereby granted, free of charge, to any person or organization
 
14
// obtaining a copy of the software and accompanying documentation covered by
 
15
// this license (the "Software") to use, reproduce, display, distribute,
 
16
// execute, and transmit the Software, and to prepare derivative works of the
 
17
// Software, and to permit third-parties to whom the Software is furnished to
 
18
// do so, all subject to the following:
 
19
// 
 
20
// The copyright notices in the Software and this entire statement, including
 
21
// the above license grant, this restriction and the following disclaimer,
 
22
// must be included in all copies of the Software, in whole or in part, and
 
23
// all derivative works of the Software, unless such copies or derivative
 
24
// works are solely in the form of machine-executable object code generated by
 
25
// a source language processor.
 
26
// 
 
27
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
28
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
29
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 
30
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 
31
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 
32
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
33
// DEALINGS IN THE SOFTWARE.
 
34
//
 
35
 
 
36
 
 
37
#include "Poco/DOM/AbstractContainerNode.h"
 
38
#include "Poco/DOM/Document.h"
 
39
#include "Poco/DOM/DOMException.h"
 
40
 
 
41
 
 
42
namespace Poco {
 
43
namespace XML {
 
44
 
 
45
 
 
46
AbstractContainerNode::AbstractContainerNode(Document* pOwnerDocument): 
 
47
        AbstractNode(pOwnerDocument),
 
48
        _pFirstChild(0)
 
49
{
 
50
}
 
51
 
 
52
 
 
53
AbstractContainerNode::AbstractContainerNode(Document* pOwnerDocument, const AbstractContainerNode& node): 
 
54
        AbstractNode(pOwnerDocument, node),
 
55
        _pFirstChild(0)
 
56
{
 
57
}
 
58
 
 
59
 
 
60
AbstractContainerNode::~AbstractContainerNode()
 
61
{
 
62
        AbstractNode* pChild = static_cast<AbstractNode*>(_pFirstChild);
 
63
        while (pChild)
 
64
        {
 
65
                AbstractNode* pDelNode = pChild;
 
66
                pChild = pChild->_pNext;
 
67
                pDelNode->_pNext   = 0;
 
68
                pDelNode->_pParent = 0;
 
69
                pDelNode->release();
 
70
        }
 
71
}
 
72
 
 
73
 
 
74
Node* AbstractContainerNode::firstChild() const
 
75
{
 
76
        return _pFirstChild;
 
77
}
 
78
 
 
79
 
 
80
Node* AbstractContainerNode::lastChild() const
 
81
{
 
82
        AbstractNode* pChild = _pFirstChild;
 
83
        if (pChild)
 
84
        {
 
85
                while (pChild->_pNext) pChild = pChild->_pNext;
 
86
                return pChild;
 
87
        }
 
88
        return 0;
 
89
}
 
90
 
 
91
 
 
92
Node* AbstractContainerNode::insertBefore(Node* newChild, Node* refChild)
 
93
{
 
94
        poco_check_ptr (newChild);
 
95
 
 
96
        if (static_cast<AbstractNode*>(newChild)->_pOwner != _pOwner && static_cast<AbstractNode*>(newChild)->_pOwner != this)
 
97
                throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
 
98
        if (refChild && static_cast<AbstractNode*>(refChild)->_pParent != this)
 
99
                throw DOMException(DOMException::NOT_FOUND_ERR);
 
100
        if (newChild == refChild)
 
101
                return newChild;
 
102
        if (this == newChild)
 
103
                throw DOMException(DOMException::HIERARCHY_REQUEST_ERR);
 
104
 
 
105
        AbstractNode* pFirst = 0;
 
106
        AbstractNode* pLast  = 0;
 
107
        if (newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)
 
108
        {
 
109
                AbstractContainerNode* pFrag = static_cast<AbstractContainerNode*>(newChild);
 
110
                pFirst = pFrag->_pFirstChild;
 
111
                pLast  = pFirst;
 
112
                if (pFirst)
 
113
                {
 
114
                        while (pLast->_pNext)
 
115
                        {
 
116
                                pLast->_pParent = this;
 
117
                                pLast = pLast->_pNext;
 
118
                        }
 
119
                        pLast->_pParent = this;
 
120
                }
 
121
                pFrag->_pFirstChild = 0;
 
122
        }
 
123
        else
 
124
        {
 
125
                newChild->duplicate();
 
126
                AbstractContainerNode* pParent = static_cast<AbstractNode*>(newChild)->_pParent;
 
127
                if (pParent) pParent->removeChild(newChild);
 
128
                pFirst = static_cast<AbstractNode*>(newChild);
 
129
                pLast  = pFirst;
 
130
                pFirst->_pParent = this;
 
131
        }
 
132
        if (_pFirstChild && pFirst)
 
133
        {
 
134
                AbstractNode* pCur = _pFirstChild;
 
135
                if (pCur == refChild)
 
136
                {
 
137
                        pLast->_pNext = _pFirstChild;
 
138
                        _pFirstChild  = pFirst;
 
139
                }
 
140
                else
 
141
                {
 
142
                        while (pCur && pCur->_pNext != refChild) pCur = pCur->_pNext;
 
143
                        if (pCur)
 
144
                        {
 
145
                                pLast->_pNext = pCur->_pNext;
 
146
                                pCur->_pNext = pFirst;
 
147
                        }
 
148
                        else throw DOMException(DOMException::NOT_FOUND_ERR);
 
149
                }
 
150
        }
 
151
        else _pFirstChild = pFirst;
 
152
 
 
153
        if (events())
 
154
        {
 
155
                while (pFirst && pFirst != pLast->_pNext)
 
156
                {
 
157
                        pFirst->dispatchNodeInserted();
 
158
                        pFirst->dispatchNodeInsertedIntoDocument();
 
159
                        pFirst = pFirst->_pNext;
 
160
                }
 
161
                dispatchSubtreeModified();
 
162
        }
 
163
        return newChild;
 
164
}
 
165
 
 
166
 
 
167
Node* AbstractContainerNode::replaceChild(Node* newChild, Node* oldChild)
 
168
{
 
169
        poco_check_ptr (newChild);
 
170
        poco_check_ptr (oldChild);
 
171
 
 
172
        if (static_cast<AbstractNode*>(newChild)->_pOwner != _pOwner && static_cast<AbstractNode*>(newChild)->_pOwner != this)
 
173
                throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
 
174
        if (static_cast<AbstractNode*>(oldChild)->_pParent != this)
 
175
                throw DOMException(DOMException::NOT_FOUND_ERR);
 
176
        if (newChild == oldChild)
 
177
                return newChild;
 
178
        if (this == newChild)
 
179
                throw DOMException(DOMException::HIERARCHY_REQUEST_ERR);
 
180
 
 
181
        bool doEvents = events();
 
182
        if (newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)
 
183
        {
 
184
                insertBefore(newChild, oldChild);
 
185
                removeChild(oldChild);
 
186
        }
 
187
        else
 
188
        {
 
189
                AbstractContainerNode* pParent = static_cast<AbstractNode*>(newChild)->_pParent;
 
190
                if (pParent) pParent->removeChild(newChild);
 
191
 
 
192
                if (oldChild == _pFirstChild)
 
193
                {
 
194
                        if (doEvents)
 
195
                        {
 
196
                                _pFirstChild->dispatchNodeRemoved();
 
197
                                _pFirstChild->dispatchNodeRemovedFromDocument();
 
198
                        }
 
199
                        static_cast<AbstractNode*>(newChild)->_pNext   = static_cast<AbstractNode*>(oldChild)->_pNext;
 
200
                        static_cast<AbstractNode*>(newChild)->_pParent = this;
 
201
                        _pFirstChild->_pNext   = 0;
 
202
                        _pFirstChild->_pParent = 0;
 
203
                        _pFirstChild = static_cast<AbstractNode*>(newChild);
 
204
                        if (doEvents)
 
205
                        {
 
206
                                static_cast<AbstractNode*>(newChild)->dispatchNodeInserted();
 
207
                                static_cast<AbstractNode*>(newChild)->dispatchNodeInsertedIntoDocument();
 
208
                        }
 
209
                }
 
210
                else
 
211
                {
 
212
                        AbstractNode* pCur = _pFirstChild;
 
213
                        while (pCur && pCur->_pNext != oldChild) pCur = pCur->_pNext;
 
214
                        if (pCur)
 
215
                        {       
 
216
                                poco_assert_dbg (pCur->_pNext == oldChild);
 
217
 
 
218
                                if (doEvents)
 
219
                                {
 
220
                                        static_cast<AbstractNode*>(oldChild)->dispatchNodeRemoved();
 
221
                                        static_cast<AbstractNode*>(oldChild)->dispatchNodeRemovedFromDocument();
 
222
                                }
 
223
                                static_cast<AbstractNode*>(newChild)->_pNext   = static_cast<AbstractNode*>(oldChild)->_pNext;
 
224
                                static_cast<AbstractNode*>(newChild)->_pParent = this;
 
225
                                static_cast<AbstractNode*>(oldChild)->_pNext   = 0;
 
226
                                static_cast<AbstractNode*>(oldChild)->_pParent = 0;
 
227
                                pCur->_pNext = static_cast<AbstractNode*>(newChild);
 
228
                                if (doEvents)
 
229
                                {
 
230
                                        static_cast<AbstractNode*>(newChild)->dispatchNodeInserted();
 
231
                                        static_cast<AbstractNode*>(newChild)->dispatchNodeInsertedIntoDocument();
 
232
                                }
 
233
                        }
 
234
                        else throw DOMException(DOMException::NOT_FOUND_ERR);
 
235
                }
 
236
                newChild->duplicate();
 
237
                oldChild->autoRelease();
 
238
        }
 
239
        if (doEvents) dispatchSubtreeModified();
 
240
        return oldChild;
 
241
}
 
242
 
 
243
 
 
244
Node* AbstractContainerNode::removeChild(Node* oldChild)
 
245
{
 
246
        poco_check_ptr (oldChild);
 
247
 
 
248
        bool doEvents = events();
 
249
        if (oldChild == _pFirstChild)
 
250
        {
 
251
                if (doEvents)
 
252
                {
 
253
                        static_cast<AbstractNode*>(oldChild)->dispatchNodeRemoved();
 
254
                        static_cast<AbstractNode*>(oldChild)->dispatchNodeRemovedFromDocument();
 
255
                }
 
256
                _pFirstChild = _pFirstChild->_pNext;
 
257
                static_cast<AbstractNode*>(oldChild)->_pNext   = 0;
 
258
                static_cast<AbstractNode*>(oldChild)->_pParent = 0;
 
259
        }
 
260
        else
 
261
        {
 
262
                AbstractNode* pCur = _pFirstChild;
 
263
                while (pCur && pCur->_pNext != oldChild) pCur = pCur->_pNext;
 
264
                if (pCur)
 
265
                {
 
266
                        if (doEvents)
 
267
                        {
 
268
                                static_cast<AbstractNode*>(oldChild)->dispatchNodeRemoved();
 
269
                                static_cast<AbstractNode*>(oldChild)->dispatchNodeRemovedFromDocument();
 
270
                        }
 
271
                        pCur->_pNext = pCur->_pNext->_pNext;
 
272
                        static_cast<AbstractNode*>(oldChild)->_pNext   = 0;
 
273
                        static_cast<AbstractNode*>(oldChild)->_pParent = 0;
 
274
                }
 
275
                else throw DOMException(DOMException::NOT_FOUND_ERR);
 
276
        }
 
277
        oldChild->autoRelease();
 
278
        if (doEvents) dispatchSubtreeModified();
 
279
        return oldChild;
 
280
}
 
281
 
 
282
 
 
283
Node* AbstractContainerNode::appendChild(Node* newChild)
 
284
{
 
285
        return insertBefore(newChild, 0);
 
286
}
 
287
 
 
288
 
 
289
void AbstractContainerNode::dispatchNodeRemovedFromDocument()
 
290
{
 
291
        AbstractNode::dispatchNodeRemovedFromDocument();
 
292
        Node* pChild = firstChild();
 
293
        while (pChild)
 
294
        {
 
295
                static_cast<AbstractNode*>(pChild)->dispatchNodeRemovedFromDocument();
 
296
                pChild = pChild->nextSibling();
 
297
        }
 
298
}
 
299
 
 
300
 
 
301
void AbstractContainerNode::dispatchNodeInsertedIntoDocument()
 
302
{
 
303
        AbstractNode::dispatchNodeInsertedIntoDocument();
 
304
        Node* pChild = firstChild();
 
305
        while (pChild)
 
306
        {
 
307
                static_cast<AbstractNode*>(pChild)->dispatchNodeInsertedIntoDocument();
 
308
                pChild = pChild->nextSibling();
 
309
        }
 
310
}
 
311
 
 
312
 
 
313
bool AbstractContainerNode::hasChildNodes() const
 
314
{
 
315
        return _pFirstChild != 0;
 
316
}
 
317
 
 
318
 
 
319
bool AbstractContainerNode::hasAttributes() const
 
320
{
 
321
        return false;
 
322
}
 
323
 
 
324
 
 
325
} } // namespace Poco::XML