~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/extensions/transformiix/source/xpath/nsXPathResult.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Netscape Public License
 
6
 * Version 1.1 (the "License"); you may not use this file except in
 
7
 * compliance with the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/NPL/
 
9
 *
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is mozilla.org code.
 
16
 *
 
17
 * The Initial Developer of the Original Code is 
 
18
 * Netscape Communications Corporation.
 
19
 * Portions created by the Initial Developer are Copyright (C) 2001
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *   Peter Van der Beken <peterv@netscape.com>
 
24
 *
 
25
 *
 
26
 * Alternatively, the contents of this file may be used under the terms of
 
27
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
28
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
29
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
30
 * of those above. If you wish to allow use of your version of this file only
 
31
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
32
 * use your version of this file under the terms of the NPL, indicate your
 
33
 * decision by deleting the provisions above and replace them with the notice
 
34
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
35
 * the provisions above, a recipient may use your version of this file under
 
36
 * the terms of any one of the NPL, the GPL or the LGPL.
 
37
 *
 
38
 * ***** END LICENSE BLOCK ***** */
 
39
 
 
40
#include "nsXPathResult.h"
 
41
#include "ExprResult.h"
 
42
#include "txNodeSet.h"
 
43
#include "nsDOMError.h"
 
44
#include "nsIContent.h"
 
45
#include "nsIDOMClassInfo.h"
 
46
#include "nsIDOMNode.h"
 
47
#include "nsXPathException.h"
 
48
#include "nsIDOMDocument.h"
 
49
#include "nsDOMString.h"
 
50
 
 
51
nsXPathResult::nsXPathResult() : mNumberValue(0),
 
52
                                 mDocument(0),
 
53
                                 mCurrentPos(0),
 
54
                                 mResultType(ANY_TYPE),
 
55
                                 mInvalidIteratorState(PR_TRUE)
 
56
{
 
57
}
 
58
 
 
59
nsXPathResult::~nsXPathResult()
 
60
{
 
61
    Reset();
 
62
}
 
63
 
 
64
NS_IMPL_ADDREF(nsXPathResult)
 
65
NS_IMPL_RELEASE(nsXPathResult)
 
66
NS_INTERFACE_MAP_BEGIN(nsXPathResult)
 
67
  NS_INTERFACE_MAP_ENTRY(nsIDOMXPathResult)
 
68
  NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
 
69
  NS_INTERFACE_MAP_ENTRY(nsIXPathResult)
 
70
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXPathResult)
 
71
  NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(XPathResult)
 
72
NS_INTERFACE_MAP_END
 
73
 
 
74
NS_IMETHODIMP
 
75
nsXPathResult::GetResultType(PRUint16 *aResultType)
 
76
{
 
77
    NS_ENSURE_ARG(aResultType);
 
78
    *aResultType = mResultType;
 
79
    return NS_OK;
 
80
}
 
81
 
 
82
NS_IMETHODIMP
 
83
nsXPathResult::GetNumberValue(double *aNumberValue)
 
84
{
 
85
    if (mResultType != NUMBER_TYPE)
 
86
        return NS_ERROR_DOM_TYPE_ERR;
 
87
 
 
88
    NS_ENSURE_ARG(aNumberValue);
 
89
    *aNumberValue = mNumberValue;
 
90
    return NS_OK;
 
91
}
 
92
 
 
93
NS_IMETHODIMP
 
94
nsXPathResult::GetStringValue(nsAString &aStringValue)
 
95
{
 
96
    if (mResultType != STRING_TYPE)
 
97
        return NS_ERROR_DOM_TYPE_ERR;
 
98
 
 
99
    if (mStringValue)
 
100
        aStringValue.Assign(*mStringValue);
 
101
    else
 
102
        SetDOMStringToNull(aStringValue);
 
103
    return NS_OK;
 
104
}
 
105
 
 
106
NS_IMETHODIMP
 
107
nsXPathResult::GetBooleanValue(PRBool *aBooleanValue)
 
108
{
 
109
    if (mResultType != BOOLEAN_TYPE)
 
110
        return NS_ERROR_DOM_TYPE_ERR;
 
111
 
 
112
    NS_ENSURE_ARG(aBooleanValue);
 
113
    *aBooleanValue = mBooleanValue;
 
114
    return NS_OK;
 
115
}
 
116
 
 
117
NS_IMETHODIMP
 
118
nsXPathResult::GetSingleNodeValue(nsIDOMNode **aSingleNodeValue)
 
119
{
 
120
    if (mResultType != FIRST_ORDERED_NODE_TYPE &&
 
121
        mResultType != ANY_UNORDERED_NODE_TYPE)
 
122
        return NS_ERROR_DOM_TYPE_ERR;
 
123
 
 
124
    NS_ENSURE_ARG(aSingleNodeValue);
 
125
    *aSingleNodeValue = mNode;
 
126
    NS_IF_ADDREF(*aSingleNodeValue);
 
127
    return NS_OK;
 
128
}
 
129
 
 
130
NS_IMETHODIMP
 
131
nsXPathResult::GetInvalidIteratorState(PRBool *aInvalidIteratorState)
 
132
{
 
133
    NS_ENSURE_ARG(aInvalidIteratorState);
 
134
 
 
135
    if (mResultType != UNORDERED_NODE_ITERATOR_TYPE &&
 
136
        mResultType != ORDERED_NODE_ITERATOR_TYPE) {
 
137
        *aInvalidIteratorState = PR_FALSE;
 
138
        return NS_OK;
 
139
    }
 
140
 
 
141
    *aInvalidIteratorState = mInvalidIteratorState;
 
142
    return NS_OK;
 
143
}
 
144
 
 
145
NS_IMETHODIMP
 
146
nsXPathResult::GetSnapshotLength(PRUint32 *aSnapshotLength)
 
147
{
 
148
    if (mResultType != UNORDERED_NODE_SNAPSHOT_TYPE &&
 
149
        mResultType != ORDERED_NODE_SNAPSHOT_TYPE)
 
150
        return NS_ERROR_DOM_TYPE_ERR;
 
151
 
 
152
    NS_ENSURE_ARG(aSnapshotLength);
 
153
    *aSnapshotLength = 0;
 
154
    if (mElements)
 
155
        *aSnapshotLength = mElements->Count();
 
156
    return NS_OK;
 
157
}
 
158
 
 
159
NS_IMETHODIMP
 
160
nsXPathResult::IterateNext(nsIDOMNode **aResult)
 
161
{
 
162
    if (mResultType != UNORDERED_NODE_ITERATOR_TYPE &&
 
163
        mResultType != ORDERED_NODE_ITERATOR_TYPE)
 
164
        return NS_ERROR_DOM_TYPE_ERR;
 
165
 
 
166
    if (mDocument)
 
167
        mDocument->FlushPendingNotifications(PR_FALSE);
 
168
 
 
169
    if (mInvalidIteratorState)
 
170
        return NS_ERROR_DOM_INVALID_STATE_ERR;
 
171
 
 
172
    NS_ENSURE_ARG(aResult);
 
173
    if (mElements && mCurrentPos < (PRUint32)mElements->Count()) {
 
174
        *aResult = mElements->ObjectAt(mCurrentPos++);
 
175
        NS_ADDREF(*aResult);
 
176
        return NS_OK;
 
177
    }
 
178
    *aResult = nsnull;
 
179
    return NS_OK;
 
180
}
 
181
 
 
182
NS_IMETHODIMP
 
183
nsXPathResult::SnapshotItem(PRUint32 aIndex, nsIDOMNode **aResult)
 
184
{
 
185
    if (mResultType != UNORDERED_NODE_SNAPSHOT_TYPE &&
 
186
        mResultType != ORDERED_NODE_SNAPSHOT_TYPE)
 
187
        return NS_ERROR_DOM_TYPE_ERR;
 
188
 
 
189
    NS_ENSURE_ARG(aResult);
 
190
    if (mElements && aIndex < (PRUint32)mElements->Count()) {
 
191
        *aResult = mElements->ObjectAt(aIndex);
 
192
        NS_ADDREF(*aResult);
 
193
        return NS_OK;
 
194
    }
 
195
    *aResult = nsnull;
 
196
    return NS_OK;
 
197
}
 
198
 
 
199
NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(nsXPathResult)
 
200
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsXPathResult)
 
201
NS_IMPL_NSIDOCUMENTOBSERVER_REFLOW_STUB(nsXPathResult)
 
202
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsXPathResult)
 
203
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsXPathResult)
 
204
 
 
205
void
 
206
nsXPathResult::CharacterDataChanged(nsIDocument* aDocument,
 
207
                                    nsIContent *aContent,
 
208
                                    PRBool aAppend)
 
209
{
 
210
    Invalidate();
 
211
}
 
212
 
 
213
void
 
214
nsXPathResult::AttributeChanged(nsIDocument* aDocument,
 
215
                                nsIContent* aContent,
 
216
                                PRInt32 aNameSpaceID,
 
217
                                nsIAtom* aAttribute,
 
218
                                PRInt32 aModType)
 
219
{
 
220
    Invalidate();
 
221
}
 
222
 
 
223
void
 
224
nsXPathResult::ContentAppended(nsIDocument* aDocument,
 
225
                               nsIContent* aContainer,
 
226
                               PRInt32 aNewIndexInContainer)
 
227
{
 
228
    Invalidate();
 
229
}
 
230
 
 
231
void
 
232
nsXPathResult::ContentInserted(nsIDocument* aDocument,
 
233
                               nsIContent* aContainer,
 
234
                               nsIContent* aChild,
 
235
                               PRInt32 aIndexInContainer)
 
236
{
 
237
    Invalidate();
 
238
}
 
239
 
 
240
void
 
241
nsXPathResult::ContentReplaced(nsIDocument* aDocument,
 
242
                               nsIContent* aContainer,
 
243
                               nsIContent* aOldChild,
 
244
                               nsIContent* aNewChild,
 
245
                               PRInt32 aIndexInContainer)
 
246
{
 
247
    Invalidate();
 
248
}
 
249
 
 
250
void
 
251
nsXPathResult::ContentRemoved(nsIDocument* aDocument,
 
252
                              nsIContent* aContainer,
 
253
                              nsIContent* aChild,
 
254
                              PRInt32 aIndexInContainer)
 
255
{
 
256
    Invalidate();
 
257
}
 
258
 
 
259
NS_IMETHODIMP
 
260
nsXPathResult::SetExprResult(txAExprResult* aExprResult, PRUint16 aResultType)
 
261
{
 
262
    Reset();
 
263
 
 
264
    mResultType = aResultType;
 
265
 
 
266
    if (mResultType == NUMBER_TYPE) {
 
267
        mNumberValue = aExprResult->numberValue();
 
268
        return NS_OK;
 
269
    }
 
270
 
 
271
    if (mResultType == STRING_TYPE) {
 
272
        mStringValue = new nsString;
 
273
        NS_ENSURE_TRUE(mStringValue, NS_ERROR_OUT_OF_MEMORY);
 
274
        aExprResult->stringValue(*mStringValue);
 
275
        return NS_OK;
 
276
    }
 
277
 
 
278
    if (mResultType == BOOLEAN_TYPE) {
 
279
        mBooleanValue = aExprResult->booleanValue();
 
280
        return NS_OK;
 
281
    }
 
282
 
 
283
    if (aExprResult->getResultType() == txAExprResult::NODESET) {
 
284
        nsresult rv = NS_OK;
 
285
        txNodeSet* nodeSet = NS_STATIC_CAST(txNodeSet*, aExprResult);
 
286
 
 
287
        if (mResultType == FIRST_ORDERED_NODE_TYPE ||
 
288
            mResultType == ANY_UNORDERED_NODE_TYPE) {
 
289
            if (nodeSet->size() > 0) {
 
290
                txXPathNativeNode::getNode(nodeSet->get(0), &mNode);
 
291
            }
 
292
        }
 
293
        else {
 
294
            if (mResultType == UNORDERED_NODE_ITERATOR_TYPE ||
 
295
                mResultType == ORDERED_NODE_ITERATOR_TYPE) {
 
296
                mInvalidIteratorState = PR_FALSE;
 
297
            }
 
298
 
 
299
            PRInt32 count = nodeSet->size();
 
300
            if (count == 0)
 
301
                return NS_OK;
 
302
 
 
303
            mElements = new nsCOMArray<nsIDOMNode>;
 
304
            NS_ENSURE_TRUE(mElements, NS_ERROR_OUT_OF_MEMORY);
 
305
 
 
306
            nsCOMPtr<nsIDOMNode> node;
 
307
            PRInt32 i;
 
308
            for (i = 0; i < count; ++i) {
 
309
                txXPathNativeNode::getNode(nodeSet->get(i), getter_AddRefs(node));
 
310
                NS_ASSERTION(node, "node isn't an nsIDOMNode");
 
311
                mElements->AppendObject(node);
 
312
            }
 
313
 
 
314
            // If we support the document() function in DOM-XPath we need to
 
315
            // observe all documents that we have resultnodes in.
 
316
            if (mResultType == UNORDERED_NODE_ITERATOR_TYPE ||
 
317
                mResultType == ORDERED_NODE_ITERATOR_TYPE) {
 
318
                nsCOMPtr<nsIDOMDocument> document;
 
319
                node->GetOwnerDocument(getter_AddRefs(document));
 
320
                if (document)
 
321
                    mDocument = do_QueryInterface(document);
 
322
                else
 
323
                    mDocument = do_QueryInterface(node);
 
324
 
 
325
                NS_ASSERTION(mDocument, "We need a document!");
 
326
                if (mDocument)
 
327
                    mDocument->AddObserver(this);
 
328
            }
 
329
        }
 
330
        return rv;
 
331
    }
 
332
 
 
333
    return NS_ERROR_DOM_TYPE_ERR;
 
334
}
 
335
 
 
336
void
 
337
nsXPathResult::Invalidate()
 
338
{
 
339
    if (mDocument) {
 
340
        mDocument->RemoveObserver(this);
 
341
        mDocument = 0;
 
342
    }
 
343
    mInvalidIteratorState = PR_TRUE;
 
344
}
 
345
 
 
346
void
 
347
nsXPathResult::Reset()
 
348
{
 
349
    Invalidate();
 
350
 
 
351
    if (mResultType == STRING_TYPE) {
 
352
        delete mStringValue;
 
353
        mStringValue = 0;
 
354
    }
 
355
    else if (mResultType == UNORDERED_NODE_ITERATOR_TYPE ||
 
356
             mResultType == ORDERED_NODE_ITERATOR_TYPE ||
 
357
             mResultType == UNORDERED_NODE_SNAPSHOT_TYPE ||
 
358
             mResultType == ORDERED_NODE_SNAPSHOT_TYPE) {
 
359
        delete mElements;
 
360
        mCurrentPos = 0;
 
361
    }
 
362
    else if (mResultType == FIRST_ORDERED_NODE_TYPE ||
 
363
             mResultType == ANY_UNORDERED_NODE_TYPE) {
 
364
        NS_IF_RELEASE(mNode);
 
365
    }
 
366
 
 
367
    mResultType = ANY_TYPE;
 
368
    return;
 
369
}