Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /*
7 :
8 : A simple composite data source implementation. A composit data
9 : source is just a strategy for combining individual data sources into
10 : a collective graph.
11 :
12 :
13 : 1) A composite data source holds a sequence of data sources. The set
14 : of data sources can be specified during creation of the
15 : database. Data sources can also be added/deleted from a database
16 : later.
17 :
18 : 2) The aggregation mechanism is based on simple super-positioning of
19 : the graphs from the datasources. If there is a conflict (i.e.,
20 : data source A has a true arc from foo to bar while data source B
21 : has a false arc from foo to bar), the data source that it earlier
22 : in the sequence wins.
23 :
24 : The implementation below doesn't really do this and needs to be
25 : fixed.
26 :
27 : */
28 :
29 : #include "xpcom-config.h"
30 : #include "nsCOMPtr.h"
31 : #include "nsIComponentManager.h"
32 : #include "nsIRDFCompositeDataSource.h"
33 : #include "nsIRDFNode.h"
34 : #include "nsIRDFObserver.h"
35 : #include "nsIRDFRemoteDataSource.h"
36 : #include "nsTArray.h"
37 : #include "nsCOMArray.h"
38 : #include "nsArrayEnumerator.h"
39 : #include "nsXPIDLString.h"
40 : #include "rdf.h"
41 : #include "nsCycleCollectionParticipant.h"
42 :
43 : #include "nsEnumeratorUtils.h"
44 :
45 : #include "mozilla/Logging.h"
46 : #include <stdio.h>
47 : mozilla::LazyLogModule nsRDFLog("RDF");
48 :
49 : //----------------------------------------------------------------------
50 : //
51 : // CompositeDataSourceImpl
52 : //
53 :
54 : class CompositeEnumeratorImpl;
55 : class CompositeArcsInOutEnumeratorImpl;
56 : class CompositeAssertionEnumeratorImpl;
57 :
58 : class CompositeDataSourceImpl : public nsIRDFCompositeDataSource,
59 : public nsIRDFObserver
60 : {
61 : public:
62 : CompositeDataSourceImpl(void);
63 : explicit CompositeDataSourceImpl(char** dataSources);
64 :
65 : // nsISupports interface
66 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
67 0 : NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(CompositeDataSourceImpl,
68 : nsIRDFCompositeDataSource)
69 :
70 : // nsIRDFDataSource interface
71 : NS_DECL_NSIRDFDATASOURCE
72 :
73 : // nsIRDFCompositeDataSource interface
74 : NS_DECL_NSIRDFCOMPOSITEDATASOURCE
75 :
76 : // nsIRDFObserver interface
77 : NS_DECL_NSIRDFOBSERVER
78 :
79 : bool HasAssertionN(int n, nsIRDFResource* source,
80 : nsIRDFResource* property,
81 : nsIRDFNode* target,
82 : bool tv);
83 :
84 : protected:
85 : nsCOMArray<nsIRDFObserver> mObservers;
86 : nsCOMArray<nsIRDFDataSource> mDataSources;
87 :
88 : bool mAllowNegativeAssertions;
89 : bool mCoalesceDuplicateArcs;
90 : int32_t mUpdateBatchNest;
91 :
92 0 : virtual ~CompositeDataSourceImpl() {}
93 :
94 : friend class CompositeEnumeratorImpl;
95 : friend class CompositeArcsInOutEnumeratorImpl;
96 : friend class CompositeAssertionEnumeratorImpl;
97 : };
98 :
99 : //----------------------------------------------------------------------
100 : //
101 : // CompositeEnumeratorImpl
102 : //
103 :
104 : class CompositeEnumeratorImpl : public nsISimpleEnumerator
105 : {
106 : // nsISupports
107 : NS_DECL_ISUPPORTS
108 :
109 : // nsISimpleEnumerator interface
110 : NS_DECL_NSISIMPLEENUMERATOR
111 :
112 : // pure abstract methods to be overridden
113 : virtual nsresult
114 : GetEnumerator(nsIRDFDataSource* aDataSource, nsISimpleEnumerator** aResult) = 0;
115 :
116 : virtual nsresult
117 : HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, bool* aResult) = 0;
118 :
119 : protected:
120 : CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
121 : bool aAllowNegativeAssertions,
122 : bool aCoalesceDuplicateArcs);
123 :
124 : virtual ~CompositeEnumeratorImpl();
125 :
126 : CompositeDataSourceImpl* mCompositeDataSource;
127 :
128 : nsISimpleEnumerator* mCurrent;
129 : nsIRDFNode* mResult;
130 : int32_t mNext;
131 : AutoTArray<nsCOMPtr<nsIRDFNode>, 8> mAlreadyReturned;
132 : bool mAllowNegativeAssertions;
133 : bool mCoalesceDuplicateArcs;
134 : };
135 :
136 :
137 0 : CompositeEnumeratorImpl::CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
138 : bool aAllowNegativeAssertions,
139 0 : bool aCoalesceDuplicateArcs)
140 : : mCompositeDataSource(aCompositeDataSource),
141 : mCurrent(nullptr),
142 : mResult(nullptr),
143 : mNext(0),
144 : mAllowNegativeAssertions(aAllowNegativeAssertions),
145 0 : mCoalesceDuplicateArcs(aCoalesceDuplicateArcs)
146 : {
147 0 : NS_ADDREF(mCompositeDataSource);
148 0 : }
149 :
150 :
151 0 : CompositeEnumeratorImpl::~CompositeEnumeratorImpl(void)
152 : {
153 0 : NS_IF_RELEASE(mCurrent);
154 0 : NS_IF_RELEASE(mResult);
155 0 : NS_RELEASE(mCompositeDataSource);
156 0 : }
157 :
158 0 : NS_IMPL_ADDREF(CompositeEnumeratorImpl)
159 0 : NS_IMPL_RELEASE(CompositeEnumeratorImpl)
160 0 : NS_IMPL_QUERY_INTERFACE(CompositeEnumeratorImpl, nsISimpleEnumerator)
161 :
162 : NS_IMETHODIMP
163 0 : CompositeEnumeratorImpl::HasMoreElements(bool* aResult)
164 : {
165 0 : NS_PRECONDITION(aResult != nullptr, "null ptr");
166 0 : if (! aResult)
167 0 : return NS_ERROR_NULL_POINTER;
168 :
169 : nsresult rv;
170 :
171 : // If we've already queued up a next target, then yep, there are
172 : // more elements.
173 0 : if (mResult) {
174 0 : *aResult = true;
175 0 : return NS_OK;
176 : }
177 :
178 : // Otherwise, we'll need to find a next target, switching cursors
179 : // if necessary.
180 0 : for ( ; mNext < mCompositeDataSource->mDataSources.Count(); ++mNext) {
181 0 : if (! mCurrent) {
182 : // We don't have a current enumerator, so create a new one on
183 : // the next data source.
184 : nsIRDFDataSource* datasource =
185 0 : mCompositeDataSource->mDataSources[mNext];
186 :
187 0 : rv = GetEnumerator(datasource, &mCurrent);
188 0 : if (NS_FAILED(rv)) return rv;
189 0 : if (rv == NS_RDF_NO_VALUE)
190 0 : continue;
191 :
192 0 : NS_ASSERTION(mCurrent != nullptr, "you're always supposed to return an enumerator from GetEnumerator, punk.");
193 0 : if (! mCurrent)
194 0 : continue;
195 : }
196 :
197 : do {
198 : int32_t i;
199 :
200 : bool hasMore;
201 0 : rv = mCurrent->HasMoreElements(&hasMore);
202 0 : if (NS_FAILED(rv)) return rv;
203 :
204 : // Is the current enumerator depleted?
205 0 : if (! hasMore) {
206 0 : NS_RELEASE(mCurrent);
207 0 : break;
208 : }
209 :
210 : // Even if the current enumerator has more elements, we still
211 : // need to check that the current element isn't masked by
212 : // a negation in an earlier data source.
213 :
214 : // "Peek" ahead and pull out the next target.
215 0 : nsCOMPtr<nsISupports> result;
216 0 : rv = mCurrent->GetNext(getter_AddRefs(result));
217 0 : if (NS_FAILED(rv)) return rv;
218 :
219 0 : rv = result->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) &mResult);
220 0 : if (NS_FAILED(rv)) return rv;
221 :
222 0 : if (mAllowNegativeAssertions)
223 : {
224 : // See if any previous data source negates this
225 0 : bool hasNegation = false;
226 0 : for (i = mNext - 1; i >= 0; --i)
227 : {
228 : nsIRDFDataSource* datasource =
229 0 : mCompositeDataSource->mDataSources[i];
230 :
231 0 : rv = HasNegation(datasource, mResult, &hasNegation);
232 0 : if (NS_FAILED(rv)) return rv;
233 :
234 0 : if (hasNegation)
235 0 : break;
236 : }
237 :
238 : // if so, we've gotta keep looking
239 0 : if (hasNegation)
240 : {
241 0 : NS_RELEASE(mResult);
242 0 : continue;
243 : }
244 : }
245 :
246 0 : if (mCoalesceDuplicateArcs)
247 : {
248 : // Now see if we've returned it once already.
249 : // XXX N.B. performance here...may want to hash if things get large?
250 0 : bool alreadyReturned = false;
251 0 : for (i = mAlreadyReturned.Length() - 1; i >= 0; --i)
252 : {
253 0 : if (mAlreadyReturned[i] == mResult)
254 : {
255 0 : alreadyReturned = true;
256 0 : break;
257 : }
258 : }
259 0 : if (alreadyReturned)
260 : {
261 0 : NS_RELEASE(mResult);
262 0 : continue;
263 : }
264 : }
265 :
266 : // If we get here, then we've really found one. It'll
267 : // remain cached in mResult until GetNext() sucks it out.
268 0 : *aResult = true;
269 :
270 : // Remember that we returned it, so we don't return duplicates.
271 :
272 : // XXX I wonder if we should make unique-checking be
273 : // optional. This could get to be pretty expensive (this
274 : // implementation turns iteration into O(n^2)).
275 :
276 0 : if (mCoalesceDuplicateArcs)
277 : {
278 0 : mAlreadyReturned.AppendElement(mResult);
279 : }
280 :
281 0 : return NS_OK;
282 : } while (1);
283 : }
284 :
285 : // if we get here, there aren't any elements left.
286 0 : *aResult = false;
287 0 : return NS_OK;
288 : }
289 :
290 :
291 : NS_IMETHODIMP
292 0 : CompositeEnumeratorImpl::GetNext(nsISupports** aResult)
293 : {
294 : nsresult rv;
295 :
296 : bool hasMore;
297 0 : rv = HasMoreElements(&hasMore);
298 0 : if (NS_FAILED(rv)) return rv;
299 :
300 0 : if (! hasMore)
301 0 : return NS_ERROR_UNEXPECTED;
302 :
303 : // Don't AddRef: we "transfer" ownership to the caller
304 0 : *aResult = mResult;
305 0 : mResult = nullptr;
306 :
307 0 : return NS_OK;
308 : }
309 :
310 : //----------------------------------------------------------------------
311 : //
312 : // CompositeArcsInOutEnumeratorImpl
313 : //
314 : //
315 :
316 : class CompositeArcsInOutEnumeratorImpl : public CompositeEnumeratorImpl
317 : {
318 : public:
319 : enum Type { eArcsIn, eArcsOut };
320 :
321 : virtual ~CompositeArcsInOutEnumeratorImpl();
322 :
323 : virtual nsresult
324 : GetEnumerator(nsIRDFDataSource* aDataSource, nsISimpleEnumerator** aResult);
325 :
326 : virtual nsresult
327 : HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, bool* aResult);
328 :
329 : CompositeArcsInOutEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
330 : nsIRDFNode* aNode,
331 : Type aType,
332 : bool aAllowNegativeAssertions,
333 : bool aCoalesceDuplicateArcs);
334 :
335 : private:
336 : nsIRDFNode* mNode;
337 : Type mType;
338 : };
339 :
340 :
341 0 : CompositeArcsInOutEnumeratorImpl::CompositeArcsInOutEnumeratorImpl(
342 : CompositeDataSourceImpl* aCompositeDataSource,
343 : nsIRDFNode* aNode,
344 : Type aType,
345 : bool aAllowNegativeAssertions,
346 0 : bool aCoalesceDuplicateArcs)
347 : : CompositeEnumeratorImpl(aCompositeDataSource, aAllowNegativeAssertions, aCoalesceDuplicateArcs),
348 : mNode(aNode),
349 0 : mType(aType)
350 : {
351 0 : NS_ADDREF(mNode);
352 0 : }
353 :
354 0 : CompositeArcsInOutEnumeratorImpl::~CompositeArcsInOutEnumeratorImpl()
355 : {
356 0 : NS_RELEASE(mNode);
357 0 : }
358 :
359 :
360 : nsresult
361 0 : CompositeArcsInOutEnumeratorImpl::GetEnumerator(
362 : nsIRDFDataSource* aDataSource,
363 : nsISimpleEnumerator** aResult)
364 : {
365 0 : if (mType == eArcsIn) {
366 0 : return aDataSource->ArcLabelsIn(mNode, aResult);
367 : }
368 : else {
369 0 : nsCOMPtr<nsIRDFResource> resource( do_QueryInterface(mNode) );
370 0 : return aDataSource->ArcLabelsOut(resource, aResult);
371 : }
372 : }
373 :
374 : nsresult
375 0 : CompositeArcsInOutEnumeratorImpl::HasNegation(
376 : nsIRDFDataSource* aDataSource,
377 : nsIRDFNode* aNode,
378 : bool* aResult)
379 : {
380 0 : *aResult = false;
381 0 : return NS_OK;
382 : }
383 :
384 :
385 : //----------------------------------------------------------------------
386 : //
387 : // CompositeAssertionEnumeratorImpl
388 : //
389 :
390 : class CompositeAssertionEnumeratorImpl : public CompositeEnumeratorImpl
391 : {
392 : public:
393 : virtual nsresult
394 : GetEnumerator(nsIRDFDataSource* aDataSource, nsISimpleEnumerator** aResult);
395 :
396 : virtual nsresult
397 : HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, bool* aResult);
398 :
399 : CompositeAssertionEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
400 : nsIRDFResource* aSource,
401 : nsIRDFResource* aProperty,
402 : nsIRDFNode* aTarget,
403 : bool aTruthValue,
404 : bool aAllowNegativeAssertions,
405 : bool aCoalesceDuplicateArcs);
406 :
407 : virtual ~CompositeAssertionEnumeratorImpl();
408 :
409 : private:
410 : nsIRDFResource* mSource;
411 : nsIRDFResource* mProperty;
412 : nsIRDFNode* mTarget;
413 : bool mTruthValue;
414 : };
415 :
416 :
417 0 : CompositeAssertionEnumeratorImpl::CompositeAssertionEnumeratorImpl(
418 : CompositeDataSourceImpl* aCompositeDataSource,
419 : nsIRDFResource* aSource,
420 : nsIRDFResource* aProperty,
421 : nsIRDFNode* aTarget,
422 : bool aTruthValue,
423 : bool aAllowNegativeAssertions,
424 0 : bool aCoalesceDuplicateArcs)
425 : : CompositeEnumeratorImpl(aCompositeDataSource, aAllowNegativeAssertions, aCoalesceDuplicateArcs),
426 : mSource(aSource),
427 : mProperty(aProperty),
428 : mTarget(aTarget),
429 0 : mTruthValue(aTruthValue)
430 : {
431 0 : NS_IF_ADDREF(mSource);
432 0 : NS_ADDREF(mProperty); // always must be specified
433 0 : NS_IF_ADDREF(mTarget);
434 0 : }
435 :
436 0 : CompositeAssertionEnumeratorImpl::~CompositeAssertionEnumeratorImpl()
437 : {
438 0 : NS_IF_RELEASE(mSource);
439 0 : NS_RELEASE(mProperty);
440 0 : NS_IF_RELEASE(mTarget);
441 0 : }
442 :
443 :
444 : nsresult
445 0 : CompositeAssertionEnumeratorImpl::GetEnumerator(
446 : nsIRDFDataSource* aDataSource,
447 : nsISimpleEnumerator** aResult)
448 : {
449 0 : if (mSource) {
450 0 : return aDataSource->GetTargets(mSource, mProperty, mTruthValue, aResult);
451 : }
452 : else {
453 0 : return aDataSource->GetSources(mProperty, mTarget, mTruthValue, aResult);
454 : }
455 : }
456 :
457 : nsresult
458 0 : CompositeAssertionEnumeratorImpl::HasNegation(
459 : nsIRDFDataSource* aDataSource,
460 : nsIRDFNode* aNode,
461 : bool* aResult)
462 : {
463 0 : if (mSource) {
464 0 : return aDataSource->HasAssertion(mSource, mProperty, aNode, !mTruthValue, aResult);
465 : }
466 : else {
467 0 : nsCOMPtr<nsIRDFResource> source( do_QueryInterface(aNode) );
468 0 : return aDataSource->HasAssertion(source, mProperty, mTarget, !mTruthValue, aResult);
469 : }
470 : }
471 :
472 : ////////////////////////////////////////////////////////////////////////
473 :
474 : nsresult
475 0 : NS_NewRDFCompositeDataSource(nsIRDFCompositeDataSource** result)
476 : {
477 0 : CompositeDataSourceImpl* db = new CompositeDataSourceImpl();
478 0 : if (! db)
479 0 : return NS_ERROR_OUT_OF_MEMORY;
480 :
481 0 : *result = db;
482 0 : NS_ADDREF(*result);
483 0 : return NS_OK;
484 : }
485 :
486 :
487 0 : CompositeDataSourceImpl::CompositeDataSourceImpl(void)
488 : : mAllowNegativeAssertions(true),
489 : mCoalesceDuplicateArcs(true),
490 0 : mUpdateBatchNest(0)
491 : {
492 0 : }
493 :
494 : //----------------------------------------------------------------------
495 : //
496 : // nsISupports interface
497 : //
498 :
499 : NS_IMPL_CYCLE_COLLECTION_CLASS(CompositeDataSourceImpl)
500 :
501 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CompositeDataSourceImpl)
502 0 : uint32_t i, count = tmp->mDataSources.Count();
503 0 : for (i = count; i > 0; --i) {
504 0 : tmp->mDataSources[i - 1]->RemoveObserver(tmp);
505 0 : tmp->mDataSources.RemoveObjectAt(i - 1);
506 : }
507 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mObservers);
508 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
509 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CompositeDataSourceImpl)
510 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObservers)
511 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDataSources)
512 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
513 :
514 :
515 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(CompositeDataSourceImpl)
516 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(CompositeDataSourceImpl)
517 :
518 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CompositeDataSourceImpl)
519 0 : NS_INTERFACE_MAP_ENTRY(nsIRDFCompositeDataSource)
520 0 : NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
521 0 : NS_INTERFACE_MAP_ENTRY(nsIRDFObserver)
522 0 : NS_INTERFACE_MAP_ENTRY(nsIRDFCompositeDataSource)
523 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFCompositeDataSource)
524 0 : NS_INTERFACE_MAP_END
525 :
526 :
527 : //----------------------------------------------------------------------
528 : //
529 : // nsIRDFDataSource interface
530 : //
531 :
532 : NS_IMETHODIMP
533 0 : CompositeDataSourceImpl::GetURI(char* *uri)
534 : {
535 0 : *uri = nullptr;
536 0 : return NS_OK;
537 : }
538 :
539 : NS_IMETHODIMP
540 0 : CompositeDataSourceImpl::GetSource(nsIRDFResource* property,
541 : nsIRDFNode* target,
542 : bool tv,
543 : nsIRDFResource** source)
544 : {
545 0 : if (!mAllowNegativeAssertions && !tv)
546 0 : return(NS_RDF_NO_VALUE);
547 :
548 0 : int32_t count = mDataSources.Count();
549 0 : for (int32_t i = 0; i < count; ++i) {
550 : nsresult rv;
551 0 : rv = mDataSources[i]->GetSource(property, target, tv, source);
552 0 : if (NS_FAILED(rv)) return rv;
553 :
554 0 : if (rv == NS_RDF_NO_VALUE)
555 0 : continue;
556 :
557 0 : if (!mAllowNegativeAssertions) return(NS_OK);
558 :
559 : // okay, found it. make sure we don't have the opposite
560 : // asserted in a more local data source
561 0 : if (!HasAssertionN(count-1, *source, property, target, !tv))
562 0 : return NS_OK;
563 :
564 0 : NS_RELEASE(*source);
565 0 : return NS_RDF_NO_VALUE;
566 : }
567 0 : return NS_RDF_NO_VALUE;
568 : }
569 :
570 : NS_IMETHODIMP
571 0 : CompositeDataSourceImpl::GetSources(nsIRDFResource* aProperty,
572 : nsIRDFNode* aTarget,
573 : bool aTruthValue,
574 : nsISimpleEnumerator** aResult)
575 : {
576 0 : NS_PRECONDITION(aProperty != nullptr, "null ptr");
577 0 : if (! aProperty)
578 0 : return NS_ERROR_NULL_POINTER;
579 :
580 0 : NS_PRECONDITION(aTarget != nullptr, "null ptr");
581 0 : if (! aTarget)
582 0 : return NS_ERROR_NULL_POINTER;
583 :
584 0 : NS_PRECONDITION(aResult != nullptr, "null ptr");
585 0 : if (! aResult)
586 0 : return NS_ERROR_NULL_POINTER;
587 :
588 0 : if (! mAllowNegativeAssertions && ! aTruthValue)
589 0 : return(NS_RDF_NO_VALUE);
590 :
591 0 : *aResult = new CompositeAssertionEnumeratorImpl(this, nullptr, aProperty,
592 : aTarget, aTruthValue,
593 0 : mAllowNegativeAssertions,
594 0 : mCoalesceDuplicateArcs);
595 :
596 0 : if (! *aResult)
597 0 : return NS_ERROR_OUT_OF_MEMORY;
598 :
599 0 : NS_ADDREF(*aResult);
600 0 : return NS_OK;
601 : }
602 :
603 : NS_IMETHODIMP
604 0 : CompositeDataSourceImpl::GetTarget(nsIRDFResource* aSource,
605 : nsIRDFResource* aProperty,
606 : bool aTruthValue,
607 : nsIRDFNode** aResult)
608 : {
609 0 : NS_PRECONDITION(aSource != nullptr, "null ptr");
610 0 : if (! aSource)
611 0 : return NS_ERROR_NULL_POINTER;
612 :
613 0 : NS_PRECONDITION(aProperty != nullptr, "null ptr");
614 0 : if (! aProperty)
615 0 : return NS_ERROR_NULL_POINTER;
616 :
617 0 : NS_PRECONDITION(aResult != nullptr, "null ptr");
618 0 : if (! aResult)
619 0 : return NS_ERROR_NULL_POINTER;
620 :
621 0 : if (! mAllowNegativeAssertions && ! aTruthValue)
622 0 : return(NS_RDF_NO_VALUE);
623 :
624 0 : int32_t count = mDataSources.Count();
625 0 : for (int32_t i = 0; i < count; ++i) {
626 : nsresult rv;
627 0 : rv = mDataSources[i]->GetTarget(aSource, aProperty, aTruthValue,
628 0 : aResult);
629 0 : if (NS_FAILED(rv))
630 0 : return rv;
631 :
632 0 : if (rv == NS_OK) {
633 : // okay, found it. make sure we don't have the opposite
634 : // asserted in an earlier data source
635 :
636 0 : if (mAllowNegativeAssertions) {
637 0 : if (HasAssertionN(count-1, aSource, aProperty, *aResult, !aTruthValue)) {
638 : // whoops, it's been negated.
639 0 : NS_RELEASE(*aResult);
640 0 : return NS_RDF_NO_VALUE;
641 : }
642 : }
643 0 : return NS_OK;
644 : }
645 : }
646 :
647 : // Otherwise, we couldn't find it at all.
648 0 : return NS_RDF_NO_VALUE;
649 : }
650 :
651 : bool
652 0 : CompositeDataSourceImpl::HasAssertionN(int n,
653 : nsIRDFResource* aSource,
654 : nsIRDFResource* aProperty,
655 : nsIRDFNode* aTarget,
656 : bool aTruthValue)
657 : {
658 : nsresult rv;
659 0 : for (int32_t m = 0; m < n; ++m) {
660 : bool result;
661 0 : rv = mDataSources[m]->HasAssertion(aSource, aProperty, aTarget,
662 0 : aTruthValue, &result);
663 0 : if (NS_FAILED(rv))
664 0 : return false;
665 :
666 : // found it!
667 0 : if (result)
668 0 : return true;
669 : }
670 0 : return false;
671 : }
672 :
673 :
674 :
675 : NS_IMETHODIMP
676 0 : CompositeDataSourceImpl::GetTargets(nsIRDFResource* aSource,
677 : nsIRDFResource* aProperty,
678 : bool aTruthValue,
679 : nsISimpleEnumerator** aResult)
680 : {
681 0 : NS_PRECONDITION(aSource != nullptr, "null ptr");
682 0 : if (! aSource)
683 0 : return NS_ERROR_NULL_POINTER;
684 :
685 0 : NS_PRECONDITION(aProperty != nullptr, "null ptr");
686 0 : if (! aProperty)
687 0 : return NS_ERROR_NULL_POINTER;
688 :
689 0 : NS_PRECONDITION(aResult != nullptr, "null ptr");
690 0 : if (! aResult)
691 0 : return NS_ERROR_NULL_POINTER;
692 :
693 0 : if (! mAllowNegativeAssertions && ! aTruthValue)
694 0 : return(NS_RDF_NO_VALUE);
695 :
696 0 : *aResult =
697 : new CompositeAssertionEnumeratorImpl(this,
698 : aSource, aProperty, nullptr,
699 : aTruthValue,
700 0 : mAllowNegativeAssertions,
701 0 : mCoalesceDuplicateArcs);
702 :
703 0 : if (! *aResult)
704 0 : return NS_ERROR_OUT_OF_MEMORY;
705 :
706 0 : NS_ADDREF(*aResult);
707 0 : return NS_OK;
708 : }
709 :
710 : NS_IMETHODIMP
711 0 : CompositeDataSourceImpl::Assert(nsIRDFResource* aSource,
712 : nsIRDFResource* aProperty,
713 : nsIRDFNode* aTarget,
714 : bool aTruthValue)
715 : {
716 0 : NS_PRECONDITION(aSource != nullptr, "null ptr");
717 0 : if (! aSource)
718 0 : return NS_ERROR_NULL_POINTER;
719 :
720 0 : NS_PRECONDITION(aProperty != nullptr, "null ptr");
721 0 : if (! aProperty)
722 0 : return NS_ERROR_NULL_POINTER;
723 :
724 0 : NS_PRECONDITION(aTarget != nullptr, "null ptr");
725 0 : if (! aTarget)
726 0 : return NS_ERROR_NULL_POINTER;
727 :
728 0 : if (! mAllowNegativeAssertions && ! aTruthValue)
729 0 : return(NS_RDF_ASSERTION_REJECTED);
730 :
731 : nsresult rv;
732 :
733 : // XXX Need to add back the stuff for unblocking ...
734 :
735 : // We iterate backwards from the last data source which was added
736 : // ("the most remote") to the first ("the most local"), trying to
737 : // apply the assertion in each.
738 0 : for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
739 0 : rv = mDataSources[i]->Assert(aSource, aProperty, aTarget, aTruthValue);
740 0 : if (NS_RDF_ASSERTION_ACCEPTED == rv)
741 0 : return rv;
742 :
743 0 : if (NS_FAILED(rv))
744 0 : return rv;
745 : }
746 :
747 : // nobody wanted to accept it
748 0 : return NS_RDF_ASSERTION_REJECTED;
749 : }
750 :
751 : NS_IMETHODIMP
752 0 : CompositeDataSourceImpl::Unassert(nsIRDFResource* aSource,
753 : nsIRDFResource* aProperty,
754 : nsIRDFNode* aTarget)
755 : {
756 0 : NS_PRECONDITION(aSource != nullptr, "null ptr");
757 0 : if (! aSource)
758 0 : return NS_ERROR_NULL_POINTER;
759 :
760 0 : NS_PRECONDITION(aProperty != nullptr, "null ptr");
761 0 : if (! aProperty)
762 0 : return NS_ERROR_NULL_POINTER;
763 :
764 0 : NS_PRECONDITION(aTarget != nullptr, "null ptr");
765 0 : if (! aTarget)
766 0 : return NS_ERROR_NULL_POINTER;
767 :
768 : nsresult rv;
769 :
770 : // Iterate through each of the datasources, starting with "the
771 : // most local" and moving to "the most remote". If _any_ of the
772 : // datasources have the assertion, attempt to unassert it.
773 0 : bool unasserted = true;
774 : int32_t i;
775 0 : int32_t count = mDataSources.Count();
776 0 : for (i = 0; i < count; ++i) {
777 0 : nsIRDFDataSource* ds = mDataSources[i];
778 :
779 : bool hasAssertion;
780 0 : rv = ds->HasAssertion(aSource, aProperty, aTarget, true, &hasAssertion);
781 0 : if (NS_FAILED(rv)) return rv;
782 :
783 0 : if (hasAssertion) {
784 0 : rv = ds->Unassert(aSource, aProperty, aTarget);
785 0 : if (NS_FAILED(rv)) return rv;
786 :
787 0 : if (rv != NS_RDF_ASSERTION_ACCEPTED) {
788 0 : unasserted = false;
789 0 : break;
790 : }
791 : }
792 : }
793 :
794 : // Either none of the datasources had it, or they were all willing
795 : // to let it be unasserted.
796 0 : if (unasserted)
797 0 : return NS_RDF_ASSERTION_ACCEPTED;
798 :
799 : // If we get here, one of the datasources already had the
800 : // assertion, and was adamant about not letting us remove
801 : // it. Iterate from the "most local" to the "most remote"
802 : // attempting to assert the negation...
803 0 : for (i = 0; i < count; ++i) {
804 0 : rv = mDataSources[i]->Assert(aSource, aProperty, aTarget, false);
805 0 : if (NS_FAILED(rv)) return rv;
806 :
807 : // Did it take?
808 0 : if (rv == NS_RDF_ASSERTION_ACCEPTED)
809 0 : return rv;
810 : }
811 :
812 : // Couln't get anyone to accept the negation, either.
813 0 : return NS_RDF_ASSERTION_REJECTED;
814 : }
815 :
816 : NS_IMETHODIMP
817 0 : CompositeDataSourceImpl::Change(nsIRDFResource* aSource,
818 : nsIRDFResource* aProperty,
819 : nsIRDFNode* aOldTarget,
820 : nsIRDFNode* aNewTarget)
821 : {
822 0 : NS_PRECONDITION(aSource != nullptr, "null ptr");
823 0 : if (! aSource)
824 0 : return NS_ERROR_NULL_POINTER;
825 :
826 0 : NS_PRECONDITION(aProperty != nullptr, "null ptr");
827 0 : if (! aProperty)
828 0 : return NS_ERROR_NULL_POINTER;
829 :
830 0 : NS_PRECONDITION(aOldTarget != nullptr, "null ptr");
831 0 : if (! aOldTarget)
832 0 : return NS_ERROR_NULL_POINTER;
833 :
834 0 : NS_PRECONDITION(aNewTarget != nullptr, "null ptr");
835 0 : if (! aNewTarget)
836 0 : return NS_ERROR_NULL_POINTER;
837 :
838 : nsresult rv;
839 :
840 : // XXX So we're assuming that a datasource _must_ accept the
841 : // atomic change; i.e., we can't split it up across two
842 : // datasources. That sucks.
843 :
844 : // We iterate backwards from the last data source which was added
845 : // ("the most remote") to the first ("the most local"), trying to
846 : // apply the change in each.
847 0 : for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
848 0 : rv = mDataSources[i]->Change(aSource, aProperty, aOldTarget, aNewTarget);
849 0 : if (NS_RDF_ASSERTION_ACCEPTED == rv)
850 0 : return rv;
851 :
852 0 : if (NS_FAILED(rv))
853 0 : return rv;
854 : }
855 :
856 : // nobody wanted to accept it
857 0 : return NS_RDF_ASSERTION_REJECTED;
858 : }
859 :
860 : NS_IMETHODIMP
861 0 : CompositeDataSourceImpl::Move(nsIRDFResource* aOldSource,
862 : nsIRDFResource* aNewSource,
863 : nsIRDFResource* aProperty,
864 : nsIRDFNode* aTarget)
865 : {
866 0 : NS_PRECONDITION(aOldSource != nullptr, "null ptr");
867 0 : if (! aOldSource)
868 0 : return NS_ERROR_NULL_POINTER;
869 :
870 0 : NS_PRECONDITION(aNewSource != nullptr, "null ptr");
871 0 : if (! aNewSource)
872 0 : return NS_ERROR_NULL_POINTER;
873 :
874 0 : NS_PRECONDITION(aProperty != nullptr, "null ptr");
875 0 : if (! aProperty)
876 0 : return NS_ERROR_NULL_POINTER;
877 :
878 0 : NS_PRECONDITION(aTarget != nullptr, "null ptr");
879 0 : if (! aTarget)
880 0 : return NS_ERROR_NULL_POINTER;
881 :
882 : nsresult rv;
883 :
884 : // XXX So we're assuming that a datasource _must_ accept the
885 : // atomic move; i.e., we can't split it up across two
886 : // datasources. That sucks.
887 :
888 : // We iterate backwards from the last data source which was added
889 : // ("the most remote") to the first ("the most local"), trying to
890 : // apply the assertion in each.
891 0 : for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
892 0 : rv = mDataSources[i]->Move(aOldSource, aNewSource, aProperty, aTarget);
893 0 : if (NS_RDF_ASSERTION_ACCEPTED == rv)
894 0 : return rv;
895 :
896 0 : if (NS_FAILED(rv))
897 0 : return rv;
898 : }
899 :
900 : // nobody wanted to accept it
901 0 : return NS_RDF_ASSERTION_REJECTED;
902 : }
903 :
904 :
905 : NS_IMETHODIMP
906 0 : CompositeDataSourceImpl::HasAssertion(nsIRDFResource* aSource,
907 : nsIRDFResource* aProperty,
908 : nsIRDFNode* aTarget,
909 : bool aTruthValue,
910 : bool* aResult)
911 : {
912 0 : NS_PRECONDITION(aSource != nullptr, "null ptr");
913 0 : if (! aSource)
914 0 : return NS_ERROR_NULL_POINTER;
915 :
916 0 : NS_PRECONDITION(aProperty != nullptr, "null ptr");
917 0 : if (! aProperty)
918 0 : return NS_ERROR_NULL_POINTER;
919 :
920 0 : NS_PRECONDITION(aResult != nullptr, "null ptr");
921 0 : if (! aResult)
922 0 : return NS_ERROR_NULL_POINTER;
923 :
924 0 : if (! mAllowNegativeAssertions && ! aTruthValue)
925 : {
926 0 : *aResult = false;
927 0 : return(NS_OK);
928 : }
929 :
930 : nsresult rv;
931 :
932 : // Otherwise, look through all the data sources to see if anyone
933 : // has the positive...
934 0 : int32_t count = mDataSources.Count();
935 0 : for (int32_t i = 0; i < count; ++i) {
936 0 : nsIRDFDataSource* datasource = mDataSources[i];
937 0 : rv = datasource->HasAssertion(aSource, aProperty, aTarget, aTruthValue, aResult);
938 0 : if (NS_FAILED(rv)) return rv;
939 :
940 0 : if (*aResult)
941 0 : return NS_OK;
942 :
943 0 : if (mAllowNegativeAssertions)
944 : {
945 : bool hasNegation;
946 0 : rv = datasource->HasAssertion(aSource, aProperty, aTarget, !aTruthValue, &hasNegation);
947 0 : if (NS_FAILED(rv)) return rv;
948 :
949 0 : if (hasNegation)
950 : {
951 0 : *aResult = false;
952 0 : return NS_OK;
953 : }
954 : }
955 : }
956 :
957 : // If we get here, nobody had the assertion at all
958 0 : *aResult = false;
959 0 : return NS_OK;
960 : }
961 :
962 : NS_IMETHODIMP
963 0 : CompositeDataSourceImpl::AddObserver(nsIRDFObserver* aObserver)
964 : {
965 0 : NS_PRECONDITION(aObserver != nullptr, "null ptr");
966 0 : if (! aObserver)
967 0 : return NS_ERROR_NULL_POINTER;
968 :
969 : // XXX ensure uniqueness?
970 0 : mObservers.AppendObject(aObserver);
971 :
972 0 : return NS_OK;
973 : }
974 :
975 : NS_IMETHODIMP
976 0 : CompositeDataSourceImpl::RemoveObserver(nsIRDFObserver* aObserver)
977 : {
978 0 : NS_PRECONDITION(aObserver != nullptr, "null ptr");
979 0 : if (! aObserver)
980 0 : return NS_ERROR_NULL_POINTER;
981 :
982 0 : mObservers.RemoveObject(aObserver);
983 :
984 0 : return NS_OK;
985 : }
986 :
987 : NS_IMETHODIMP
988 0 : CompositeDataSourceImpl::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
989 : {
990 : nsresult rv;
991 0 : *result = false;
992 0 : int32_t count = mDataSources.Count();
993 0 : for (int32_t i = 0; i < count; ++i) {
994 0 : rv = mDataSources[i]->HasArcIn(aNode, aArc, result);
995 0 : if (NS_FAILED(rv)) return rv;
996 0 : if (*result)
997 0 : return NS_OK;
998 : }
999 0 : return NS_OK;
1000 : }
1001 :
1002 : NS_IMETHODIMP
1003 0 : CompositeDataSourceImpl::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *result)
1004 : {
1005 : nsresult rv;
1006 0 : *result = false;
1007 0 : int32_t count = mDataSources.Count();
1008 0 : for (int32_t i = 0; i < count; ++i) {
1009 0 : rv = mDataSources[i]->HasArcOut(aSource, aArc, result);
1010 0 : if (NS_FAILED(rv)) return rv;
1011 0 : if (*result)
1012 0 : return NS_OK;
1013 : }
1014 0 : return NS_OK;
1015 : }
1016 :
1017 : NS_IMETHODIMP
1018 0 : CompositeDataSourceImpl::ArcLabelsIn(nsIRDFNode* aTarget, nsISimpleEnumerator** aResult)
1019 : {
1020 0 : NS_PRECONDITION(aTarget != nullptr, "null ptr");
1021 0 : if (! aTarget)
1022 0 : return NS_ERROR_NULL_POINTER;
1023 :
1024 0 : NS_PRECONDITION(aResult != nullptr, "null ptr");
1025 0 : if (! aResult)
1026 0 : return NS_ERROR_NULL_POINTER;
1027 :
1028 : nsISimpleEnumerator* result =
1029 : new CompositeArcsInOutEnumeratorImpl(this, aTarget,
1030 : CompositeArcsInOutEnumeratorImpl::eArcsIn,
1031 0 : mAllowNegativeAssertions,
1032 0 : mCoalesceDuplicateArcs);
1033 :
1034 0 : if (! result)
1035 0 : return NS_ERROR_OUT_OF_MEMORY;
1036 :
1037 0 : NS_ADDREF(result);
1038 0 : *aResult = result;
1039 0 : return NS_OK;
1040 : }
1041 :
1042 : NS_IMETHODIMP
1043 0 : CompositeDataSourceImpl::ArcLabelsOut(nsIRDFResource* aSource,
1044 : nsISimpleEnumerator** aResult)
1045 : {
1046 0 : NS_PRECONDITION(aSource != nullptr, "null ptr");
1047 0 : if (! aSource)
1048 0 : return NS_ERROR_NULL_POINTER;
1049 :
1050 0 : NS_PRECONDITION(aResult != nullptr, "null ptr");
1051 0 : if (! aResult)
1052 0 : return NS_ERROR_NULL_POINTER;
1053 :
1054 : nsISimpleEnumerator* result =
1055 : new CompositeArcsInOutEnumeratorImpl(this, aSource,
1056 : CompositeArcsInOutEnumeratorImpl::eArcsOut,
1057 0 : mAllowNegativeAssertions,
1058 0 : mCoalesceDuplicateArcs);
1059 :
1060 0 : if (! result)
1061 0 : return NS_ERROR_OUT_OF_MEMORY;
1062 :
1063 0 : NS_ADDREF(result);
1064 0 : *aResult = result;
1065 0 : return NS_OK;
1066 : }
1067 :
1068 : NS_IMETHODIMP
1069 0 : CompositeDataSourceImpl::GetAllResources(nsISimpleEnumerator** aResult)
1070 : {
1071 0 : NS_NOTYETIMPLEMENTED("CompositeDataSourceImpl::GetAllResources");
1072 0 : return NS_ERROR_NOT_IMPLEMENTED;
1073 : }
1074 :
1075 : NS_IMETHODIMP
1076 0 : CompositeDataSourceImpl::GetAllCmds(nsIRDFResource* source,
1077 : nsISimpleEnumerator/*<nsIRDFResource>*/** result)
1078 : {
1079 : nsresult rv;
1080 0 : nsCOMPtr<nsISimpleEnumerator> set;
1081 :
1082 0 : for (int32_t i = 0; i < mDataSources.Count(); i++)
1083 : {
1084 0 : nsCOMPtr<nsISimpleEnumerator> dsCmds;
1085 :
1086 0 : rv = mDataSources[i]->GetAllCmds(source, getter_AddRefs(dsCmds));
1087 0 : if (NS_SUCCEEDED(rv))
1088 : {
1089 0 : nsCOMPtr<nsISimpleEnumerator> tmp;
1090 0 : rv = NS_NewUnionEnumerator(getter_AddRefs(tmp), set, dsCmds);
1091 0 : set.swap(tmp);
1092 0 : if (NS_FAILED(rv)) return(rv);
1093 : }
1094 : }
1095 :
1096 0 : set.forget(result);
1097 0 : return NS_OK;
1098 : }
1099 :
1100 : NS_IMETHODIMP
1101 0 : CompositeDataSourceImpl::IsCommandEnabled(nsISupports/* nsIRDFResource container */* aSources,
1102 : nsIRDFResource* aCommand,
1103 : nsISupports/* nsIRDFResource container */* aArguments,
1104 : bool* aResult)
1105 : {
1106 : nsresult rv;
1107 0 : for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
1108 0 : bool enabled = true;
1109 0 : rv = mDataSources[i]->IsCommandEnabled(aSources, aCommand, aArguments, &enabled);
1110 0 : if (NS_FAILED(rv) && (rv != NS_ERROR_NOT_IMPLEMENTED))
1111 : {
1112 0 : return(rv);
1113 : }
1114 :
1115 0 : if (! enabled) {
1116 0 : *aResult = false;
1117 0 : return(NS_OK);
1118 : }
1119 : }
1120 0 : *aResult = true;
1121 0 : return(NS_OK);
1122 : }
1123 :
1124 : NS_IMETHODIMP
1125 0 : CompositeDataSourceImpl::DoCommand(nsISupports/* nsIRDFResource container */* aSources,
1126 : nsIRDFResource* aCommand,
1127 : nsISupports/* nsIRDFResource container */* aArguments)
1128 : {
1129 0 : for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
1130 0 : nsresult rv = mDataSources[i]->DoCommand(aSources, aCommand, aArguments);
1131 0 : if (NS_FAILED(rv) && (rv != NS_ERROR_NOT_IMPLEMENTED))
1132 : {
1133 0 : return(rv); // all datasources must succeed
1134 : }
1135 : }
1136 0 : return(NS_OK);
1137 : }
1138 :
1139 : NS_IMETHODIMP
1140 0 : CompositeDataSourceImpl::BeginUpdateBatch()
1141 : {
1142 0 : for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
1143 0 : mDataSources[i]->BeginUpdateBatch();
1144 : }
1145 0 : return NS_OK;
1146 : }
1147 :
1148 : NS_IMETHODIMP
1149 0 : CompositeDataSourceImpl::EndUpdateBatch()
1150 : {
1151 0 : for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
1152 0 : mDataSources[i]->EndUpdateBatch();
1153 : }
1154 0 : return NS_OK;
1155 : }
1156 :
1157 : ////////////////////////////////////////////////////////////////////////
1158 : // nsIRDFCompositeDataSource methods
1159 : // XXX rvg We should make this take an additional argument specifying where
1160 : // in the sequence of data sources (of the db), the new data source should
1161 : // fit in. Right now, the new datasource gets stuck at the end.
1162 : // need to add the observers of the CompositeDataSourceImpl to the new data source.
1163 :
1164 : NS_IMETHODIMP
1165 0 : CompositeDataSourceImpl::GetAllowNegativeAssertions(bool *aAllowNegativeAssertions)
1166 : {
1167 0 : *aAllowNegativeAssertions = mAllowNegativeAssertions;
1168 0 : return(NS_OK);
1169 : }
1170 :
1171 : NS_IMETHODIMP
1172 0 : CompositeDataSourceImpl::SetAllowNegativeAssertions(bool aAllowNegativeAssertions)
1173 : {
1174 0 : mAllowNegativeAssertions = aAllowNegativeAssertions;
1175 0 : return(NS_OK);
1176 : }
1177 :
1178 : NS_IMETHODIMP
1179 0 : CompositeDataSourceImpl::GetCoalesceDuplicateArcs(bool *aCoalesceDuplicateArcs)
1180 : {
1181 0 : *aCoalesceDuplicateArcs = mCoalesceDuplicateArcs;
1182 0 : return(NS_OK);
1183 : }
1184 :
1185 : NS_IMETHODIMP
1186 0 : CompositeDataSourceImpl::SetCoalesceDuplicateArcs(bool aCoalesceDuplicateArcs)
1187 : {
1188 0 : mCoalesceDuplicateArcs = aCoalesceDuplicateArcs;
1189 0 : return(NS_OK);
1190 : }
1191 :
1192 : NS_IMETHODIMP
1193 0 : CompositeDataSourceImpl::AddDataSource(nsIRDFDataSource* aDataSource)
1194 : {
1195 0 : NS_ASSERTION(aDataSource != nullptr, "null ptr");
1196 0 : if (! aDataSource)
1197 0 : return NS_ERROR_NULL_POINTER;
1198 :
1199 0 : mDataSources.AppendObject(aDataSource);
1200 0 : aDataSource->AddObserver(this);
1201 0 : return NS_OK;
1202 : }
1203 :
1204 :
1205 :
1206 : NS_IMETHODIMP
1207 0 : CompositeDataSourceImpl::RemoveDataSource(nsIRDFDataSource* aDataSource)
1208 : {
1209 0 : NS_ASSERTION(aDataSource != nullptr, "null ptr");
1210 0 : if (! aDataSource)
1211 0 : return NS_ERROR_NULL_POINTER;
1212 :
1213 :
1214 0 : if (mDataSources.IndexOf(aDataSource) >= 0) {
1215 0 : aDataSource->RemoveObserver(this);
1216 0 : mDataSources.RemoveObject(aDataSource);
1217 : }
1218 0 : return NS_OK;
1219 : }
1220 :
1221 :
1222 : NS_IMETHODIMP
1223 0 : CompositeDataSourceImpl::GetDataSources(nsISimpleEnumerator** _result)
1224 : {
1225 : // NS_NewArrayEnumerator for an nsCOMArray takes a snapshot of the
1226 : // current state.
1227 0 : return NS_NewArrayEnumerator(_result, mDataSources);
1228 : }
1229 :
1230 : NS_IMETHODIMP
1231 0 : CompositeDataSourceImpl::OnAssert(nsIRDFDataSource* aDataSource,
1232 : nsIRDFResource* aSource,
1233 : nsIRDFResource* aProperty,
1234 : nsIRDFNode* aTarget)
1235 : {
1236 : // Make sure that the assertion isn't masked by another
1237 : // datasource.
1238 : //
1239 : // XXX We could make this more efficient if we knew _which_
1240 : // datasource actually served up the OnAssert(): we could use
1241 : // HasAssertionN() to only search datasources _before_ the
1242 : // datasource that coughed up the assertion.
1243 0 : nsresult rv = NS_OK;
1244 :
1245 0 : if (mAllowNegativeAssertions)
1246 : {
1247 : bool hasAssertion;
1248 0 : rv = HasAssertion(aSource, aProperty, aTarget, true, &hasAssertion);
1249 0 : if (NS_FAILED(rv)) return rv;
1250 :
1251 0 : if (! hasAssertion)
1252 0 : return(NS_OK);
1253 : }
1254 :
1255 0 : for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
1256 0 : mObservers[i]->OnAssert(this, aSource, aProperty, aTarget);
1257 : }
1258 0 : return NS_OK;
1259 : }
1260 :
1261 : NS_IMETHODIMP
1262 0 : CompositeDataSourceImpl::OnUnassert(nsIRDFDataSource* aDataSource,
1263 : nsIRDFResource* aSource,
1264 : nsIRDFResource* aProperty,
1265 : nsIRDFNode* aTarget)
1266 : {
1267 : // Make sure that the un-assertion doesn't just unmask the
1268 : // same assertion in a different datasource.
1269 : //
1270 : // XXX We could make this more efficient if we knew _which_
1271 : // datasource actually served up the OnAssert(): we could use
1272 : // HasAssertionN() to only search datasources _before_ the
1273 : // datasource that coughed up the assertion.
1274 : nsresult rv;
1275 :
1276 0 : if (mAllowNegativeAssertions)
1277 : {
1278 : bool hasAssertion;
1279 0 : rv = HasAssertion(aSource, aProperty, aTarget, true, &hasAssertion);
1280 0 : if (NS_FAILED(rv)) return rv;
1281 :
1282 0 : if (hasAssertion)
1283 0 : return NS_OK;
1284 : }
1285 :
1286 0 : for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
1287 0 : mObservers[i]->OnUnassert(this, aSource, aProperty, aTarget);
1288 : }
1289 0 : return NS_OK;
1290 : }
1291 :
1292 :
1293 : NS_IMETHODIMP
1294 0 : CompositeDataSourceImpl::OnChange(nsIRDFDataSource* aDataSource,
1295 : nsIRDFResource* aSource,
1296 : nsIRDFResource* aProperty,
1297 : nsIRDFNode* aOldTarget,
1298 : nsIRDFNode* aNewTarget)
1299 : {
1300 : // Make sure that the change is actually visible, and not hidden
1301 : // by an assertion in a different datasource.
1302 : //
1303 : // XXX Because of aggregation, this could actually mutate into a
1304 : // variety of OnAssert or OnChange notifications, which we'll
1305 : // ignore for now :-/.
1306 0 : for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
1307 0 : mObservers[i]->OnChange(this, aSource, aProperty,
1308 0 : aOldTarget, aNewTarget);
1309 : }
1310 0 : return NS_OK;
1311 : }
1312 :
1313 :
1314 : NS_IMETHODIMP
1315 0 : CompositeDataSourceImpl::OnMove(nsIRDFDataSource* aDataSource,
1316 : nsIRDFResource* aOldSource,
1317 : nsIRDFResource* aNewSource,
1318 : nsIRDFResource* aProperty,
1319 : nsIRDFNode* aTarget)
1320 : {
1321 : // Make sure that the move is actually visible, and not hidden
1322 : // by an assertion in a different datasource.
1323 : //
1324 : // XXX Because of aggregation, this could actually mutate into a
1325 : // variety of OnAssert or OnMove notifications, which we'll
1326 : // ignore for now :-/.
1327 0 : for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
1328 0 : mObservers[i]->OnMove(this, aOldSource, aNewSource,
1329 0 : aProperty, aTarget);
1330 : }
1331 0 : return NS_OK;
1332 : }
1333 :
1334 :
1335 : NS_IMETHODIMP
1336 0 : CompositeDataSourceImpl::OnBeginUpdateBatch(nsIRDFDataSource* aDataSource)
1337 : {
1338 0 : if (mUpdateBatchNest++ == 0) {
1339 0 : for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
1340 0 : mObservers[i]->OnBeginUpdateBatch(this);
1341 : }
1342 : }
1343 0 : return NS_OK;
1344 : }
1345 :
1346 :
1347 : NS_IMETHODIMP
1348 0 : CompositeDataSourceImpl::OnEndUpdateBatch(nsIRDFDataSource* aDataSource)
1349 : {
1350 0 : NS_ASSERTION(mUpdateBatchNest > 0, "badly nested update batch");
1351 0 : if (--mUpdateBatchNest == 0) {
1352 0 : for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
1353 0 : mObservers[i]->OnEndUpdateBatch(this);
1354 : }
1355 : }
1356 0 : return NS_OK;
1357 : }
|