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