rdf/base/src/nsCompositeDataSource.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial