nsCompositeDataSource.cpp 40 KB

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