123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /*
- A simple composite data source implementation. A composit data
- source is just a strategy for combining individual data sources into
- a collective graph.
- 1) A composite data source holds a sequence of data sources. The set
- of data sources can be specified during creation of the
- database. Data sources can also be added/deleted from a database
- later.
- 2) The aggregation mechanism is based on simple super-positioning of
- the graphs from the datasources. If there is a conflict (i.e.,
- data source A has a true arc from foo to bar while data source B
- has a false arc from foo to bar), the data source that it earlier
- in the sequence wins.
- The implementation below doesn't really do this and needs to be
- fixed.
- */
- #include "xpcom-config.h"
- #include "nsCOMPtr.h"
- #include "nsIComponentManager.h"
- #include "nsIRDFCompositeDataSource.h"
- #include "nsIRDFNode.h"
- #include "nsIRDFObserver.h"
- #include "nsIRDFRemoteDataSource.h"
- #include "nsTArray.h"
- #include "nsCOMArray.h"
- #include "nsArrayEnumerator.h"
- #include "nsXPIDLString.h"
- #include "rdf.h"
- #include "nsCycleCollectionParticipant.h"
- #include "nsEnumeratorUtils.h"
- #include "mozilla/Logging.h"
- #include "prprf.h"
- #include <stdio.h>
- mozilla::LazyLogModule nsRDFLog("RDF");
- //----------------------------------------------------------------------
- //
- // CompositeDataSourceImpl
- //
- class CompositeEnumeratorImpl;
- class CompositeArcsInOutEnumeratorImpl;
- class CompositeAssertionEnumeratorImpl;
- class CompositeDataSourceImpl : public nsIRDFCompositeDataSource,
- public nsIRDFObserver
- {
- public:
- CompositeDataSourceImpl(void);
- explicit CompositeDataSourceImpl(char** dataSources);
- // nsISupports interface
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(CompositeDataSourceImpl,
- nsIRDFCompositeDataSource)
- // nsIRDFDataSource interface
- NS_DECL_NSIRDFDATASOURCE
- // nsIRDFCompositeDataSource interface
- NS_DECL_NSIRDFCOMPOSITEDATASOURCE
- // nsIRDFObserver interface
- NS_DECL_NSIRDFOBSERVER
- bool HasAssertionN(int n, nsIRDFResource* source,
- nsIRDFResource* property,
- nsIRDFNode* target,
- bool tv);
- protected:
- nsCOMArray<nsIRDFObserver> mObservers;
- nsCOMArray<nsIRDFDataSource> mDataSources;
- bool mAllowNegativeAssertions;
- bool mCoalesceDuplicateArcs;
- int32_t mUpdateBatchNest;
- virtual ~CompositeDataSourceImpl() {}
- friend class CompositeEnumeratorImpl;
- friend class CompositeArcsInOutEnumeratorImpl;
- friend class CompositeAssertionEnumeratorImpl;
- };
- //----------------------------------------------------------------------
- //
- // CompositeEnumeratorImpl
- //
- class CompositeEnumeratorImpl : public nsISimpleEnumerator
- {
- // nsISupports
- NS_DECL_ISUPPORTS
- // nsISimpleEnumerator interface
- NS_DECL_NSISIMPLEENUMERATOR
- // pure abstract methods to be overridden
- virtual nsresult
- GetEnumerator(nsIRDFDataSource* aDataSource, nsISimpleEnumerator** aResult) = 0;
- virtual nsresult
- HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, bool* aResult) = 0;
- protected:
- CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
- bool aAllowNegativeAssertions,
- bool aCoalesceDuplicateArcs);
- virtual ~CompositeEnumeratorImpl();
- CompositeDataSourceImpl* mCompositeDataSource;
- nsISimpleEnumerator* mCurrent;
- nsIRDFNode* mResult;
- int32_t mNext;
- AutoTArray<nsCOMPtr<nsIRDFNode>, 8> mAlreadyReturned;
- bool mAllowNegativeAssertions;
- bool mCoalesceDuplicateArcs;
- };
- CompositeEnumeratorImpl::CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
- bool aAllowNegativeAssertions,
- bool aCoalesceDuplicateArcs)
- : mCompositeDataSource(aCompositeDataSource),
- mCurrent(nullptr),
- mResult(nullptr),
- mNext(0),
- mAllowNegativeAssertions(aAllowNegativeAssertions),
- mCoalesceDuplicateArcs(aCoalesceDuplicateArcs)
- {
- NS_ADDREF(mCompositeDataSource);
- }
- CompositeEnumeratorImpl::~CompositeEnumeratorImpl(void)
- {
- NS_IF_RELEASE(mCurrent);
- NS_IF_RELEASE(mResult);
- NS_RELEASE(mCompositeDataSource);
- }
- NS_IMPL_ADDREF(CompositeEnumeratorImpl)
- NS_IMPL_RELEASE(CompositeEnumeratorImpl)
- NS_IMPL_QUERY_INTERFACE(CompositeEnumeratorImpl, nsISimpleEnumerator)
- NS_IMETHODIMP
- CompositeEnumeratorImpl::HasMoreElements(bool* aResult)
- {
- NS_PRECONDITION(aResult != nullptr, "null ptr");
- if (! aResult)
- return NS_ERROR_NULL_POINTER;
- nsresult rv;
- // If we've already queued up a next target, then yep, there are
- // more elements.
- if (mResult) {
- *aResult = true;
- return NS_OK;
- }
- // Otherwise, we'll need to find a next target, switching cursors
- // if necessary.
- for ( ; mNext < mCompositeDataSource->mDataSources.Count(); ++mNext) {
- if (! mCurrent) {
- // We don't have a current enumerator, so create a new one on
- // the next data source.
- nsIRDFDataSource* datasource =
- mCompositeDataSource->mDataSources[mNext];
- rv = GetEnumerator(datasource, &mCurrent);
- if (NS_FAILED(rv)) return rv;
- if (rv == NS_RDF_NO_VALUE)
- continue;
- NS_ASSERTION(mCurrent != nullptr, "you're always supposed to return an enumerator from GetEnumerator, punk.");
- if (! mCurrent)
- continue;
- }
- do {
- int32_t i;
- bool hasMore;
- rv = mCurrent->HasMoreElements(&hasMore);
- if (NS_FAILED(rv)) return rv;
- // Is the current enumerator depleted?
- if (! hasMore) {
- NS_RELEASE(mCurrent);
- break;
- }
- // Even if the current enumerator has more elements, we still
- // need to check that the current element isn't masked by
- // a negation in an earlier data source.
- // "Peek" ahead and pull out the next target.
- nsCOMPtr<nsISupports> result;
- rv = mCurrent->GetNext(getter_AddRefs(result));
- if (NS_FAILED(rv)) return rv;
- rv = result->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) &mResult);
- if (NS_FAILED(rv)) return rv;
- if (mAllowNegativeAssertions)
- {
- // See if any previous data source negates this
- bool hasNegation = false;
- for (i = mNext - 1; i >= 0; --i)
- {
- nsIRDFDataSource* datasource =
- mCompositeDataSource->mDataSources[i];
- rv = HasNegation(datasource, mResult, &hasNegation);
- if (NS_FAILED(rv)) return rv;
- if (hasNegation)
- break;
- }
- // if so, we've gotta keep looking
- if (hasNegation)
- {
- NS_RELEASE(mResult);
- continue;
- }
- }
- if (mCoalesceDuplicateArcs)
- {
- // Now see if we've returned it once already.
- // XXX N.B. performance here...may want to hash if things get large?
- bool alreadyReturned = false;
- for (i = mAlreadyReturned.Length() - 1; i >= 0; --i)
- {
- if (mAlreadyReturned[i] == mResult)
- {
- alreadyReturned = true;
- break;
- }
- }
- if (alreadyReturned)
- {
- NS_RELEASE(mResult);
- continue;
- }
- }
- // If we get here, then we've really found one. It'll
- // remain cached in mResult until GetNext() sucks it out.
- *aResult = true;
- // Remember that we returned it, so we don't return duplicates.
- // XXX I wonder if we should make unique-checking be
- // optional. This could get to be pretty expensive (this
- // implementation turns iteration into O(n^2)).
- if (mCoalesceDuplicateArcs)
- {
- mAlreadyReturned.AppendElement(mResult);
- }
- return NS_OK;
- } while (1);
- }
- // if we get here, there aren't any elements left.
- *aResult = false;
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeEnumeratorImpl::GetNext(nsISupports** aResult)
- {
- nsresult rv;
- bool hasMore;
- rv = HasMoreElements(&hasMore);
- if (NS_FAILED(rv)) return rv;
- if (! hasMore)
- return NS_ERROR_UNEXPECTED;
- // Don't AddRef: we "transfer" ownership to the caller
- *aResult = mResult;
- mResult = nullptr;
- return NS_OK;
- }
- //----------------------------------------------------------------------
- //
- // CompositeArcsInOutEnumeratorImpl
- //
- //
- class CompositeArcsInOutEnumeratorImpl : public CompositeEnumeratorImpl
- {
- public:
- enum Type { eArcsIn, eArcsOut };
- virtual ~CompositeArcsInOutEnumeratorImpl();
- virtual nsresult
- GetEnumerator(nsIRDFDataSource* aDataSource, nsISimpleEnumerator** aResult);
- virtual nsresult
- HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, bool* aResult);
- CompositeArcsInOutEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
- nsIRDFNode* aNode,
- Type aType,
- bool aAllowNegativeAssertions,
- bool aCoalesceDuplicateArcs);
- private:
- nsIRDFNode* mNode;
- Type mType;
- };
- CompositeArcsInOutEnumeratorImpl::CompositeArcsInOutEnumeratorImpl(
- CompositeDataSourceImpl* aCompositeDataSource,
- nsIRDFNode* aNode,
- Type aType,
- bool aAllowNegativeAssertions,
- bool aCoalesceDuplicateArcs)
- : CompositeEnumeratorImpl(aCompositeDataSource, aAllowNegativeAssertions, aCoalesceDuplicateArcs),
- mNode(aNode),
- mType(aType)
- {
- NS_ADDREF(mNode);
- }
- CompositeArcsInOutEnumeratorImpl::~CompositeArcsInOutEnumeratorImpl()
- {
- NS_RELEASE(mNode);
- }
- nsresult
- CompositeArcsInOutEnumeratorImpl::GetEnumerator(
- nsIRDFDataSource* aDataSource,
- nsISimpleEnumerator** aResult)
- {
- if (mType == eArcsIn) {
- return aDataSource->ArcLabelsIn(mNode, aResult);
- }
- else {
- nsCOMPtr<nsIRDFResource> resource( do_QueryInterface(mNode) );
- return aDataSource->ArcLabelsOut(resource, aResult);
- }
- }
- nsresult
- CompositeArcsInOutEnumeratorImpl::HasNegation(
- nsIRDFDataSource* aDataSource,
- nsIRDFNode* aNode,
- bool* aResult)
- {
- *aResult = false;
- return NS_OK;
- }
- //----------------------------------------------------------------------
- //
- // CompositeAssertionEnumeratorImpl
- //
- class CompositeAssertionEnumeratorImpl : public CompositeEnumeratorImpl
- {
- public:
- virtual nsresult
- GetEnumerator(nsIRDFDataSource* aDataSource, nsISimpleEnumerator** aResult);
- virtual nsresult
- HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, bool* aResult);
- CompositeAssertionEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
- nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget,
- bool aTruthValue,
- bool aAllowNegativeAssertions,
- bool aCoalesceDuplicateArcs);
- virtual ~CompositeAssertionEnumeratorImpl();
- private:
- nsIRDFResource* mSource;
- nsIRDFResource* mProperty;
- nsIRDFNode* mTarget;
- bool mTruthValue;
- };
- CompositeAssertionEnumeratorImpl::CompositeAssertionEnumeratorImpl(
- CompositeDataSourceImpl* aCompositeDataSource,
- nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget,
- bool aTruthValue,
- bool aAllowNegativeAssertions,
- bool aCoalesceDuplicateArcs)
- : CompositeEnumeratorImpl(aCompositeDataSource, aAllowNegativeAssertions, aCoalesceDuplicateArcs),
- mSource(aSource),
- mProperty(aProperty),
- mTarget(aTarget),
- mTruthValue(aTruthValue)
- {
- NS_IF_ADDREF(mSource);
- NS_ADDREF(mProperty); // always must be specified
- NS_IF_ADDREF(mTarget);
- }
- CompositeAssertionEnumeratorImpl::~CompositeAssertionEnumeratorImpl()
- {
- NS_IF_RELEASE(mSource);
- NS_RELEASE(mProperty);
- NS_IF_RELEASE(mTarget);
- }
- nsresult
- CompositeAssertionEnumeratorImpl::GetEnumerator(
- nsIRDFDataSource* aDataSource,
- nsISimpleEnumerator** aResult)
- {
- if (mSource) {
- return aDataSource->GetTargets(mSource, mProperty, mTruthValue, aResult);
- }
- else {
- return aDataSource->GetSources(mProperty, mTarget, mTruthValue, aResult);
- }
- }
- nsresult
- CompositeAssertionEnumeratorImpl::HasNegation(
- nsIRDFDataSource* aDataSource,
- nsIRDFNode* aNode,
- bool* aResult)
- {
- if (mSource) {
- return aDataSource->HasAssertion(mSource, mProperty, aNode, !mTruthValue, aResult);
- }
- else {
- nsCOMPtr<nsIRDFResource> source( do_QueryInterface(aNode) );
- return aDataSource->HasAssertion(source, mProperty, mTarget, !mTruthValue, aResult);
- }
- }
- ////////////////////////////////////////////////////////////////////////
- nsresult
- NS_NewRDFCompositeDataSource(nsIRDFCompositeDataSource** result)
- {
- CompositeDataSourceImpl* db = new CompositeDataSourceImpl();
- if (! db)
- return NS_ERROR_OUT_OF_MEMORY;
- *result = db;
- NS_ADDREF(*result);
- return NS_OK;
- }
- CompositeDataSourceImpl::CompositeDataSourceImpl(void)
- : mAllowNegativeAssertions(true),
- mCoalesceDuplicateArcs(true),
- mUpdateBatchNest(0)
- {
- }
- //----------------------------------------------------------------------
- //
- // nsISupports interface
- //
- NS_IMPL_CYCLE_COLLECTION_CLASS(CompositeDataSourceImpl)
- NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CompositeDataSourceImpl)
- uint32_t i, count = tmp->mDataSources.Count();
- for (i = count; i > 0; --i) {
- tmp->mDataSources[i - 1]->RemoveObserver(tmp);
- tmp->mDataSources.RemoveObjectAt(i - 1);
- }
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mObservers);
- NS_IMPL_CYCLE_COLLECTION_UNLINK_END
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CompositeDataSourceImpl)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObservers)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDataSources)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
- NS_IMPL_CYCLE_COLLECTING_ADDREF(CompositeDataSourceImpl)
- NS_IMPL_CYCLE_COLLECTING_RELEASE(CompositeDataSourceImpl)
- NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CompositeDataSourceImpl)
- NS_INTERFACE_MAP_ENTRY(nsIRDFCompositeDataSource)
- NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
- NS_INTERFACE_MAP_ENTRY(nsIRDFObserver)
- NS_INTERFACE_MAP_ENTRY(nsIRDFCompositeDataSource)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFCompositeDataSource)
- NS_INTERFACE_MAP_END
- //----------------------------------------------------------------------
- //
- // nsIRDFDataSource interface
- //
- NS_IMETHODIMP
- CompositeDataSourceImpl::GetURI(char* *uri)
- {
- *uri = nullptr;
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::GetSource(nsIRDFResource* property,
- nsIRDFNode* target,
- bool tv,
- nsIRDFResource** source)
- {
- if (!mAllowNegativeAssertions && !tv)
- return(NS_RDF_NO_VALUE);
- int32_t count = mDataSources.Count();
- for (int32_t i = 0; i < count; ++i) {
- nsresult rv;
- rv = mDataSources[i]->GetSource(property, target, tv, source);
- if (NS_FAILED(rv)) return rv;
- if (rv == NS_RDF_NO_VALUE)
- continue;
- if (!mAllowNegativeAssertions) return(NS_OK);
- // okay, found it. make sure we don't have the opposite
- // asserted in a more local data source
- if (!HasAssertionN(count-1, *source, property, target, !tv))
- return NS_OK;
- NS_RELEASE(*source);
- return NS_RDF_NO_VALUE;
- }
- return NS_RDF_NO_VALUE;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::GetSources(nsIRDFResource* aProperty,
- nsIRDFNode* aTarget,
- bool aTruthValue,
- nsISimpleEnumerator** aResult)
- {
- NS_PRECONDITION(aProperty != nullptr, "null ptr");
- if (! aProperty)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aTarget != nullptr, "null ptr");
- if (! aTarget)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aResult != nullptr, "null ptr");
- if (! aResult)
- return NS_ERROR_NULL_POINTER;
- if (! mAllowNegativeAssertions && ! aTruthValue)
- return(NS_RDF_NO_VALUE);
- *aResult = new CompositeAssertionEnumeratorImpl(this, nullptr, aProperty,
- aTarget, aTruthValue,
- mAllowNegativeAssertions,
- mCoalesceDuplicateArcs);
- if (! *aResult)
- return NS_ERROR_OUT_OF_MEMORY;
- NS_ADDREF(*aResult);
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::GetTarget(nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- bool aTruthValue,
- nsIRDFNode** aResult)
- {
- NS_PRECONDITION(aSource != nullptr, "null ptr");
- if (! aSource)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aProperty != nullptr, "null ptr");
- if (! aProperty)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aResult != nullptr, "null ptr");
- if (! aResult)
- return NS_ERROR_NULL_POINTER;
- if (! mAllowNegativeAssertions && ! aTruthValue)
- return(NS_RDF_NO_VALUE);
- int32_t count = mDataSources.Count();
- for (int32_t i = 0; i < count; ++i) {
- nsresult rv;
- rv = mDataSources[i]->GetTarget(aSource, aProperty, aTruthValue,
- aResult);
- if (NS_FAILED(rv))
- return rv;
- if (rv == NS_OK) {
- // okay, found it. make sure we don't have the opposite
- // asserted in an earlier data source
- if (mAllowNegativeAssertions) {
- if (HasAssertionN(count-1, aSource, aProperty, *aResult, !aTruthValue)) {
- // whoops, it's been negated.
- NS_RELEASE(*aResult);
- return NS_RDF_NO_VALUE;
- }
- }
- return NS_OK;
- }
- }
- // Otherwise, we couldn't find it at all.
- return NS_RDF_NO_VALUE;
- }
- bool
- CompositeDataSourceImpl::HasAssertionN(int n,
- nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget,
- bool aTruthValue)
- {
- nsresult rv;
- for (int32_t m = 0; m < n; ++m) {
- bool result;
- rv = mDataSources[m]->HasAssertion(aSource, aProperty, aTarget,
- aTruthValue, &result);
- if (NS_FAILED(rv))
- return false;
- // found it!
- if (result)
- return true;
- }
- return false;
- }
-
- NS_IMETHODIMP
- CompositeDataSourceImpl::GetTargets(nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- bool aTruthValue,
- nsISimpleEnumerator** aResult)
- {
- NS_PRECONDITION(aSource != nullptr, "null ptr");
- if (! aSource)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aProperty != nullptr, "null ptr");
- if (! aProperty)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aResult != nullptr, "null ptr");
- if (! aResult)
- return NS_ERROR_NULL_POINTER;
- if (! mAllowNegativeAssertions && ! aTruthValue)
- return(NS_RDF_NO_VALUE);
- *aResult =
- new CompositeAssertionEnumeratorImpl(this,
- aSource, aProperty, nullptr,
- aTruthValue,
- mAllowNegativeAssertions,
- mCoalesceDuplicateArcs);
- if (! *aResult)
- return NS_ERROR_OUT_OF_MEMORY;
- NS_ADDREF(*aResult);
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::Assert(nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget,
- bool aTruthValue)
- {
- NS_PRECONDITION(aSource != nullptr, "null ptr");
- if (! aSource)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aProperty != nullptr, "null ptr");
- if (! aProperty)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aTarget != nullptr, "null ptr");
- if (! aTarget)
- return NS_ERROR_NULL_POINTER;
- if (! mAllowNegativeAssertions && ! aTruthValue)
- return(NS_RDF_ASSERTION_REJECTED);
- nsresult rv;
- // XXX Need to add back the stuff for unblocking ...
- // We iterate backwards from the last data source which was added
- // ("the most remote") to the first ("the most local"), trying to
- // apply the assertion in each.
- for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
- rv = mDataSources[i]->Assert(aSource, aProperty, aTarget, aTruthValue);
- if (NS_RDF_ASSERTION_ACCEPTED == rv)
- return rv;
- if (NS_FAILED(rv))
- return rv;
- }
- // nobody wanted to accept it
- return NS_RDF_ASSERTION_REJECTED;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::Unassert(nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget)
- {
- NS_PRECONDITION(aSource != nullptr, "null ptr");
- if (! aSource)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aProperty != nullptr, "null ptr");
- if (! aProperty)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aTarget != nullptr, "null ptr");
- if (! aTarget)
- return NS_ERROR_NULL_POINTER;
- nsresult rv;
- // Iterate through each of the datasources, starting with "the
- // most local" and moving to "the most remote". If _any_ of the
- // datasources have the assertion, attempt to unassert it.
- bool unasserted = true;
- int32_t i;
- int32_t count = mDataSources.Count();
- for (i = 0; i < count; ++i) {
- nsIRDFDataSource* ds = mDataSources[i];
- bool hasAssertion;
- rv = ds->HasAssertion(aSource, aProperty, aTarget, true, &hasAssertion);
- if (NS_FAILED(rv)) return rv;
- if (hasAssertion) {
- rv = ds->Unassert(aSource, aProperty, aTarget);
- if (NS_FAILED(rv)) return rv;
- if (rv != NS_RDF_ASSERTION_ACCEPTED) {
- unasserted = false;
- break;
- }
- }
- }
- // Either none of the datasources had it, or they were all willing
- // to let it be unasserted.
- if (unasserted)
- return NS_RDF_ASSERTION_ACCEPTED;
- // If we get here, one of the datasources already had the
- // assertion, and was adamant about not letting us remove
- // it. Iterate from the "most local" to the "most remote"
- // attempting to assert the negation...
- for (i = 0; i < count; ++i) {
- rv = mDataSources[i]->Assert(aSource, aProperty, aTarget, false);
- if (NS_FAILED(rv)) return rv;
- // Did it take?
- if (rv == NS_RDF_ASSERTION_ACCEPTED)
- return rv;
- }
- // Couln't get anyone to accept the negation, either.
- return NS_RDF_ASSERTION_REJECTED;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::Change(nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aOldTarget,
- nsIRDFNode* aNewTarget)
- {
- NS_PRECONDITION(aSource != nullptr, "null ptr");
- if (! aSource)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aProperty != nullptr, "null ptr");
- if (! aProperty)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aOldTarget != nullptr, "null ptr");
- if (! aOldTarget)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aNewTarget != nullptr, "null ptr");
- if (! aNewTarget)
- return NS_ERROR_NULL_POINTER;
- nsresult rv;
- // XXX So we're assuming that a datasource _must_ accept the
- // atomic change; i.e., we can't split it up across two
- // datasources. That sucks.
- // We iterate backwards from the last data source which was added
- // ("the most remote") to the first ("the most local"), trying to
- // apply the change in each.
- for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
- rv = mDataSources[i]->Change(aSource, aProperty, aOldTarget, aNewTarget);
- if (NS_RDF_ASSERTION_ACCEPTED == rv)
- return rv;
- if (NS_FAILED(rv))
- return rv;
- }
- // nobody wanted to accept it
- return NS_RDF_ASSERTION_REJECTED;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::Move(nsIRDFResource* aOldSource,
- nsIRDFResource* aNewSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget)
- {
- NS_PRECONDITION(aOldSource != nullptr, "null ptr");
- if (! aOldSource)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aNewSource != nullptr, "null ptr");
- if (! aNewSource)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aProperty != nullptr, "null ptr");
- if (! aProperty)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aTarget != nullptr, "null ptr");
- if (! aTarget)
- return NS_ERROR_NULL_POINTER;
- nsresult rv;
- // XXX So we're assuming that a datasource _must_ accept the
- // atomic move; i.e., we can't split it up across two
- // datasources. That sucks.
- // We iterate backwards from the last data source which was added
- // ("the most remote") to the first ("the most local"), trying to
- // apply the assertion in each.
- for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
- rv = mDataSources[i]->Move(aOldSource, aNewSource, aProperty, aTarget);
- if (NS_RDF_ASSERTION_ACCEPTED == rv)
- return rv;
- if (NS_FAILED(rv))
- return rv;
- }
- // nobody wanted to accept it
- return NS_RDF_ASSERTION_REJECTED;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::HasAssertion(nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget,
- bool aTruthValue,
- bool* aResult)
- {
- NS_PRECONDITION(aSource != nullptr, "null ptr");
- if (! aSource)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aProperty != nullptr, "null ptr");
- if (! aProperty)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aResult != nullptr, "null ptr");
- if (! aResult)
- return NS_ERROR_NULL_POINTER;
- if (! mAllowNegativeAssertions && ! aTruthValue)
- {
- *aResult = false;
- return(NS_OK);
- }
- nsresult rv;
- // Otherwise, look through all the data sources to see if anyone
- // has the positive...
- int32_t count = mDataSources.Count();
- for (int32_t i = 0; i < count; ++i) {
- nsIRDFDataSource* datasource = mDataSources[i];
- rv = datasource->HasAssertion(aSource, aProperty, aTarget, aTruthValue, aResult);
- if (NS_FAILED(rv)) return rv;
- if (*aResult)
- return NS_OK;
- if (mAllowNegativeAssertions)
- {
- bool hasNegation;
- rv = datasource->HasAssertion(aSource, aProperty, aTarget, !aTruthValue, &hasNegation);
- if (NS_FAILED(rv)) return rv;
- if (hasNegation)
- {
- *aResult = false;
- return NS_OK;
- }
- }
- }
- // If we get here, nobody had the assertion at all
- *aResult = false;
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::AddObserver(nsIRDFObserver* aObserver)
- {
- NS_PRECONDITION(aObserver != nullptr, "null ptr");
- if (! aObserver)
- return NS_ERROR_NULL_POINTER;
- // XXX ensure uniqueness?
- mObservers.AppendObject(aObserver);
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::RemoveObserver(nsIRDFObserver* aObserver)
- {
- NS_PRECONDITION(aObserver != nullptr, "null ptr");
- if (! aObserver)
- return NS_ERROR_NULL_POINTER;
- mObservers.RemoveObject(aObserver);
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
- {
- nsresult rv;
- *result = false;
- int32_t count = mDataSources.Count();
- for (int32_t i = 0; i < count; ++i) {
- rv = mDataSources[i]->HasArcIn(aNode, aArc, result);
- if (NS_FAILED(rv)) return rv;
- if (*result)
- return NS_OK;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *result)
- {
- nsresult rv;
- *result = false;
- int32_t count = mDataSources.Count();
- for (int32_t i = 0; i < count; ++i) {
- rv = mDataSources[i]->HasArcOut(aSource, aArc, result);
- if (NS_FAILED(rv)) return rv;
- if (*result)
- return NS_OK;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::ArcLabelsIn(nsIRDFNode* aTarget, nsISimpleEnumerator** aResult)
- {
- NS_PRECONDITION(aTarget != nullptr, "null ptr");
- if (! aTarget)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aResult != nullptr, "null ptr");
- if (! aResult)
- return NS_ERROR_NULL_POINTER;
- nsISimpleEnumerator* result =
- new CompositeArcsInOutEnumeratorImpl(this, aTarget,
- CompositeArcsInOutEnumeratorImpl::eArcsIn,
- mAllowNegativeAssertions,
- mCoalesceDuplicateArcs);
- if (! result)
- return NS_ERROR_OUT_OF_MEMORY;
- NS_ADDREF(result);
- *aResult = result;
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::ArcLabelsOut(nsIRDFResource* aSource,
- nsISimpleEnumerator** aResult)
- {
- NS_PRECONDITION(aSource != nullptr, "null ptr");
- if (! aSource)
- return NS_ERROR_NULL_POINTER;
- NS_PRECONDITION(aResult != nullptr, "null ptr");
- if (! aResult)
- return NS_ERROR_NULL_POINTER;
- nsISimpleEnumerator* result =
- new CompositeArcsInOutEnumeratorImpl(this, aSource,
- CompositeArcsInOutEnumeratorImpl::eArcsOut,
- mAllowNegativeAssertions,
- mCoalesceDuplicateArcs);
- if (! result)
- return NS_ERROR_OUT_OF_MEMORY;
- NS_ADDREF(result);
- *aResult = result;
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::GetAllResources(nsISimpleEnumerator** aResult)
- {
- NS_NOTYETIMPLEMENTED("CompositeDataSourceImpl::GetAllResources");
- return NS_ERROR_NOT_IMPLEMENTED;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::GetAllCmds(nsIRDFResource* source,
- nsISimpleEnumerator/*<nsIRDFResource>*/** result)
- {
- nsresult rv;
- nsCOMPtr<nsISimpleEnumerator> set;
- for (int32_t i = 0; i < mDataSources.Count(); i++)
- {
- nsCOMPtr<nsISimpleEnumerator> dsCmds;
- rv = mDataSources[i]->GetAllCmds(source, getter_AddRefs(dsCmds));
- if (NS_SUCCEEDED(rv))
- {
- nsCOMPtr<nsISimpleEnumerator> tmp;
- rv = NS_NewUnionEnumerator(getter_AddRefs(tmp), set, dsCmds);
- set.swap(tmp);
- if (NS_FAILED(rv)) return(rv);
- }
- }
- set.forget(result);
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::IsCommandEnabled(nsISupports/* nsIRDFResource container */* aSources,
- nsIRDFResource* aCommand,
- nsISupports/* nsIRDFResource container */* aArguments,
- bool* aResult)
- {
- nsresult rv;
- for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
- bool enabled = true;
- rv = mDataSources[i]->IsCommandEnabled(aSources, aCommand, aArguments, &enabled);
- if (NS_FAILED(rv) && (rv != NS_ERROR_NOT_IMPLEMENTED))
- {
- return(rv);
- }
- if (! enabled) {
- *aResult = false;
- return(NS_OK);
- }
- }
- *aResult = true;
- return(NS_OK);
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::DoCommand(nsISupports/* nsIRDFResource container */* aSources,
- nsIRDFResource* aCommand,
- nsISupports/* nsIRDFResource container */* aArguments)
- {
- for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
- nsresult rv = mDataSources[i]->DoCommand(aSources, aCommand, aArguments);
- if (NS_FAILED(rv) && (rv != NS_ERROR_NOT_IMPLEMENTED))
- {
- return(rv); // all datasources must succeed
- }
- }
- return(NS_OK);
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::BeginUpdateBatch()
- {
- for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
- mDataSources[i]->BeginUpdateBatch();
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::EndUpdateBatch()
- {
- for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) {
- mDataSources[i]->EndUpdateBatch();
- }
- return NS_OK;
- }
- ////////////////////////////////////////////////////////////////////////
- // nsIRDFCompositeDataSource methods
- // XXX rvg We should make this take an additional argument specifying where
- // in the sequence of data sources (of the db), the new data source should
- // fit in. Right now, the new datasource gets stuck at the end.
- // need to add the observers of the CompositeDataSourceImpl to the new data source.
- NS_IMETHODIMP
- CompositeDataSourceImpl::GetAllowNegativeAssertions(bool *aAllowNegativeAssertions)
- {
- *aAllowNegativeAssertions = mAllowNegativeAssertions;
- return(NS_OK);
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::SetAllowNegativeAssertions(bool aAllowNegativeAssertions)
- {
- mAllowNegativeAssertions = aAllowNegativeAssertions;
- return(NS_OK);
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::GetCoalesceDuplicateArcs(bool *aCoalesceDuplicateArcs)
- {
- *aCoalesceDuplicateArcs = mCoalesceDuplicateArcs;
- return(NS_OK);
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::SetCoalesceDuplicateArcs(bool aCoalesceDuplicateArcs)
- {
- mCoalesceDuplicateArcs = aCoalesceDuplicateArcs;
- return(NS_OK);
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::AddDataSource(nsIRDFDataSource* aDataSource)
- {
- NS_ASSERTION(aDataSource != nullptr, "null ptr");
- if (! aDataSource)
- return NS_ERROR_NULL_POINTER;
- mDataSources.AppendObject(aDataSource);
- aDataSource->AddObserver(this);
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::RemoveDataSource(nsIRDFDataSource* aDataSource)
- {
- NS_ASSERTION(aDataSource != nullptr, "null ptr");
- if (! aDataSource)
- return NS_ERROR_NULL_POINTER;
- if (mDataSources.IndexOf(aDataSource) >= 0) {
- aDataSource->RemoveObserver(this);
- mDataSources.RemoveObject(aDataSource);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::GetDataSources(nsISimpleEnumerator** _result)
- {
- // NS_NewArrayEnumerator for an nsCOMArray takes a snapshot of the
- // current state.
- return NS_NewArrayEnumerator(_result, mDataSources);
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::OnAssert(nsIRDFDataSource* aDataSource,
- nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget)
- {
- // Make sure that the assertion isn't masked by another
- // datasource.
- //
- // XXX We could make this more efficient if we knew _which_
- // datasource actually served up the OnAssert(): we could use
- // HasAssertionN() to only search datasources _before_ the
- // datasource that coughed up the assertion.
- nsresult rv = NS_OK;
- if (mAllowNegativeAssertions)
- {
- bool hasAssertion;
- rv = HasAssertion(aSource, aProperty, aTarget, true, &hasAssertion);
- if (NS_FAILED(rv)) return rv;
- if (! hasAssertion)
- return(NS_OK);
- }
- for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
- mObservers[i]->OnAssert(this, aSource, aProperty, aTarget);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::OnUnassert(nsIRDFDataSource* aDataSource,
- nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget)
- {
- // Make sure that the un-assertion doesn't just unmask the
- // same assertion in a different datasource.
- //
- // XXX We could make this more efficient if we knew _which_
- // datasource actually served up the OnAssert(): we could use
- // HasAssertionN() to only search datasources _before_ the
- // datasource that coughed up the assertion.
- nsresult rv;
- if (mAllowNegativeAssertions)
- {
- bool hasAssertion;
- rv = HasAssertion(aSource, aProperty, aTarget, true, &hasAssertion);
- if (NS_FAILED(rv)) return rv;
- if (hasAssertion)
- return NS_OK;
- }
- for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
- mObservers[i]->OnUnassert(this, aSource, aProperty, aTarget);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::OnChange(nsIRDFDataSource* aDataSource,
- nsIRDFResource* aSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aOldTarget,
- nsIRDFNode* aNewTarget)
- {
- // Make sure that the change is actually visible, and not hidden
- // by an assertion in a different datasource.
- //
- // XXX Because of aggregation, this could actually mutate into a
- // variety of OnAssert or OnChange notifications, which we'll
- // ignore for now :-/.
- for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
- mObservers[i]->OnChange(this, aSource, aProperty,
- aOldTarget, aNewTarget);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::OnMove(nsIRDFDataSource* aDataSource,
- nsIRDFResource* aOldSource,
- nsIRDFResource* aNewSource,
- nsIRDFResource* aProperty,
- nsIRDFNode* aTarget)
- {
- // Make sure that the move is actually visible, and not hidden
- // by an assertion in a different datasource.
- //
- // XXX Because of aggregation, this could actually mutate into a
- // variety of OnAssert or OnMove notifications, which we'll
- // ignore for now :-/.
- for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
- mObservers[i]->OnMove(this, aOldSource, aNewSource,
- aProperty, aTarget);
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::OnBeginUpdateBatch(nsIRDFDataSource* aDataSource)
- {
- if (mUpdateBatchNest++ == 0) {
- for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
- mObservers[i]->OnBeginUpdateBatch(this);
- }
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- CompositeDataSourceImpl::OnEndUpdateBatch(nsIRDFDataSource* aDataSource)
- {
- NS_ASSERTION(mUpdateBatchNest > 0, "badly nested update batch");
- if (--mUpdateBatchNest == 0) {
- for (int32_t i = mObservers.Count() - 1; i >= 0; --i) {
- mObservers[i]->OnEndUpdateBatch(this);
- }
- }
- return NS_OK;
- }
|