1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/rdf/base/src/nsCompositeDataSource.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1364 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + 1.11 + A simple composite data source implementation. A composit data 1.12 + source is just a strategy for combining individual data sources into 1.13 + a collective graph. 1.14 + 1.15 + 1.16 + 1) A composite data source holds a sequence of data sources. The set 1.17 + of data sources can be specified during creation of the 1.18 + database. Data sources can also be added/deleted from a database 1.19 + later. 1.20 + 1.21 + 2) The aggregation mechanism is based on simple super-positioning of 1.22 + the graphs from the datasources. If there is a conflict (i.e., 1.23 + data source A has a true arc from foo to bar while data source B 1.24 + has a false arc from foo to bar), the data source that it earlier 1.25 + in the sequence wins. 1.26 + 1.27 + The implementation below doesn't really do this and needs to be 1.28 + fixed. 1.29 + 1.30 +*/ 1.31 + 1.32 +#include "xpcom-config.h" 1.33 +#include "nsCOMPtr.h" 1.34 +#include "nsIComponentManager.h" 1.35 +#include "nsIRDFCompositeDataSource.h" 1.36 +#include "nsIRDFNode.h" 1.37 +#include "nsIRDFObserver.h" 1.38 +#include "nsIRDFRemoteDataSource.h" 1.39 +#include "nsTArray.h" 1.40 +#include "nsCOMArray.h" 1.41 +#include "nsArrayEnumerator.h" 1.42 +#include "nsXPIDLString.h" 1.43 +#include "rdf.h" 1.44 +#include "nsCycleCollectionParticipant.h" 1.45 + 1.46 +#include "nsEnumeratorUtils.h" 1.47 + 1.48 +#ifdef PR_LOGGING 1.49 +#include "prlog.h" 1.50 +#include "prprf.h" 1.51 +#include <stdio.h> 1.52 +PRLogModuleInfo* nsRDFLog = nullptr; 1.53 +#endif 1.54 + 1.55 +//---------------------------------------------------------------------- 1.56 +// 1.57 +// CompositeDataSourceImpl 1.58 +// 1.59 + 1.60 +class CompositeEnumeratorImpl; 1.61 +class CompositeArcsInOutEnumeratorImpl; 1.62 +class CompositeAssertionEnumeratorImpl; 1.63 + 1.64 +class CompositeDataSourceImpl : public nsIRDFCompositeDataSource, 1.65 + public nsIRDFObserver 1.66 +{ 1.67 +public: 1.68 + CompositeDataSourceImpl(void); 1.69 + CompositeDataSourceImpl(char** dataSources); 1.70 + 1.71 + // nsISupports interface 1.72 + NS_DECL_CYCLE_COLLECTING_ISUPPORTS 1.73 + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(CompositeDataSourceImpl, 1.74 + nsIRDFCompositeDataSource) 1.75 + 1.76 + // nsIRDFDataSource interface 1.77 + NS_DECL_NSIRDFDATASOURCE 1.78 + 1.79 + // nsIRDFCompositeDataSource interface 1.80 + NS_DECL_NSIRDFCOMPOSITEDATASOURCE 1.81 + 1.82 + // nsIRDFObserver interface 1.83 + NS_DECL_NSIRDFOBSERVER 1.84 + 1.85 + bool HasAssertionN(int n, nsIRDFResource* source, 1.86 + nsIRDFResource* property, 1.87 + nsIRDFNode* target, 1.88 + bool tv); 1.89 + 1.90 +protected: 1.91 + nsCOMArray<nsIRDFObserver> mObservers; 1.92 + nsCOMArray<nsIRDFDataSource> mDataSources; 1.93 + 1.94 + bool mAllowNegativeAssertions; 1.95 + bool mCoalesceDuplicateArcs; 1.96 + int32_t mUpdateBatchNest; 1.97 + 1.98 + virtual ~CompositeDataSourceImpl() {} 1.99 + 1.100 + friend class CompositeEnumeratorImpl; 1.101 + friend class CompositeArcsInOutEnumeratorImpl; 1.102 + friend class CompositeAssertionEnumeratorImpl; 1.103 +}; 1.104 + 1.105 +//---------------------------------------------------------------------- 1.106 +// 1.107 +// CompositeEnumeratorImpl 1.108 +// 1.109 + 1.110 +class CompositeEnumeratorImpl : public nsISimpleEnumerator 1.111 +{ 1.112 + // nsISupports 1.113 + NS_DECL_ISUPPORTS 1.114 + 1.115 + // nsISimpleEnumerator interface 1.116 + NS_DECL_NSISIMPLEENUMERATOR 1.117 + 1.118 + // pure abstract methods to be overridden 1.119 + virtual nsresult 1.120 + GetEnumerator(nsIRDFDataSource* aDataSource, nsISimpleEnumerator** aResult) = 0; 1.121 + 1.122 + virtual nsresult 1.123 + HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, bool* aResult) = 0; 1.124 + 1.125 +protected: 1.126 + CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource, 1.127 + bool aAllowNegativeAssertions, 1.128 + bool aCoalesceDuplicateArcs); 1.129 + 1.130 + virtual ~CompositeEnumeratorImpl(); 1.131 + 1.132 + CompositeDataSourceImpl* mCompositeDataSource; 1.133 + 1.134 + nsISimpleEnumerator* mCurrent; 1.135 + nsIRDFNode* mResult; 1.136 + int32_t mNext; 1.137 + nsAutoTArray<nsCOMPtr<nsIRDFNode>, 8> mAlreadyReturned; 1.138 + bool mAllowNegativeAssertions; 1.139 + bool mCoalesceDuplicateArcs; 1.140 +}; 1.141 + 1.142 + 1.143 +CompositeEnumeratorImpl::CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource, 1.144 + bool aAllowNegativeAssertions, 1.145 + bool aCoalesceDuplicateArcs) 1.146 + : mCompositeDataSource(aCompositeDataSource), 1.147 + mCurrent(nullptr), 1.148 + mResult(nullptr), 1.149 + mNext(0), 1.150 + mAllowNegativeAssertions(aAllowNegativeAssertions), 1.151 + mCoalesceDuplicateArcs(aCoalesceDuplicateArcs) 1.152 +{ 1.153 + NS_ADDREF(mCompositeDataSource); 1.154 +} 1.155 + 1.156 + 1.157 +CompositeEnumeratorImpl::~CompositeEnumeratorImpl(void) 1.158 +{ 1.159 + NS_IF_RELEASE(mCurrent); 1.160 + NS_IF_RELEASE(mResult); 1.161 + NS_RELEASE(mCompositeDataSource); 1.162 +} 1.163 + 1.164 +NS_IMPL_ADDREF(CompositeEnumeratorImpl) 1.165 +NS_IMPL_RELEASE(CompositeEnumeratorImpl) 1.166 +NS_IMPL_QUERY_INTERFACE(CompositeEnumeratorImpl, nsISimpleEnumerator) 1.167 + 1.168 +NS_IMETHODIMP 1.169 +CompositeEnumeratorImpl::HasMoreElements(bool* aResult) 1.170 +{ 1.171 + NS_PRECONDITION(aResult != nullptr, "null ptr"); 1.172 + if (! aResult) 1.173 + return NS_ERROR_NULL_POINTER; 1.174 + 1.175 + nsresult rv; 1.176 + 1.177 + // If we've already queued up a next target, then yep, there are 1.178 + // more elements. 1.179 + if (mResult) { 1.180 + *aResult = true; 1.181 + return NS_OK; 1.182 + } 1.183 + 1.184 + // Otherwise, we'll need to find a next target, switching cursors 1.185 + // if necessary. 1.186 + for ( ; mNext < mCompositeDataSource->mDataSources.Count(); ++mNext) { 1.187 + if (! mCurrent) { 1.188 + // We don't have a current enumerator, so create a new one on 1.189 + // the next data source. 1.190 + nsIRDFDataSource* datasource = 1.191 + mCompositeDataSource->mDataSources[mNext]; 1.192 + 1.193 + rv = GetEnumerator(datasource, &mCurrent); 1.194 + if (NS_FAILED(rv)) return rv; 1.195 + if (rv == NS_RDF_NO_VALUE) 1.196 + continue; 1.197 + 1.198 + NS_ASSERTION(mCurrent != nullptr, "you're always supposed to return an enumerator from GetEnumerator, punk."); 1.199 + if (! mCurrent) 1.200 + continue; 1.201 + } 1.202 + 1.203 + do { 1.204 + int32_t i; 1.205 + 1.206 + bool hasMore; 1.207 + rv = mCurrent->HasMoreElements(&hasMore); 1.208 + if (NS_FAILED(rv)) return rv; 1.209 + 1.210 + // Is the current enumerator depleted? 1.211 + if (! hasMore) { 1.212 + NS_RELEASE(mCurrent); 1.213 + break; 1.214 + } 1.215 + 1.216 + // Even if the current enumerator has more elements, we still 1.217 + // need to check that the current element isn't masked by 1.218 + // a negation in an earlier data source. 1.219 + 1.220 + // "Peek" ahead and pull out the next target. 1.221 + nsCOMPtr<nsISupports> result; 1.222 + rv = mCurrent->GetNext(getter_AddRefs(result)); 1.223 + if (NS_FAILED(rv)) return rv; 1.224 + 1.225 + rv = result->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) &mResult); 1.226 + if (NS_FAILED(rv)) return rv; 1.227 + 1.228 + if (mAllowNegativeAssertions) 1.229 + { 1.230 + // See if any previous data source negates this 1.231 + bool hasNegation = false; 1.232 + for (i = mNext - 1; i >= 0; --i) 1.233 + { 1.234 + nsIRDFDataSource* datasource = 1.235 + mCompositeDataSource->mDataSources[i]; 1.236 + 1.237 + rv = HasNegation(datasource, mResult, &hasNegation); 1.238 + if (NS_FAILED(rv)) return rv; 1.239 + 1.240 + if (hasNegation) 1.241 + break; 1.242 + } 1.243 + 1.244 + // if so, we've gotta keep looking 1.245 + if (hasNegation) 1.246 + { 1.247 + NS_RELEASE(mResult); 1.248 + continue; 1.249 + } 1.250 + } 1.251 + 1.252 + if (mCoalesceDuplicateArcs) 1.253 + { 1.254 + // Now see if we've returned it once already. 1.255 + // XXX N.B. performance here...may want to hash if things get large? 1.256 + bool alreadyReturned = false; 1.257 + for (i = mAlreadyReturned.Length() - 1; i >= 0; --i) 1.258 + { 1.259 + if (mAlreadyReturned[i] == mResult) 1.260 + { 1.261 + alreadyReturned = true; 1.262 + break; 1.263 + } 1.264 + } 1.265 + if (alreadyReturned) 1.266 + { 1.267 + NS_RELEASE(mResult); 1.268 + continue; 1.269 + } 1.270 + } 1.271 + 1.272 + // If we get here, then we've really found one. It'll 1.273 + // remain cached in mResult until GetNext() sucks it out. 1.274 + *aResult = true; 1.275 + 1.276 + // Remember that we returned it, so we don't return duplicates. 1.277 + 1.278 + // XXX I wonder if we should make unique-checking be 1.279 + // optional. This could get to be pretty expensive (this 1.280 + // implementation turns iteration into O(n^2)). 1.281 + 1.282 + if (mCoalesceDuplicateArcs) 1.283 + { 1.284 + mAlreadyReturned.AppendElement(mResult); 1.285 + } 1.286 + 1.287 + return NS_OK; 1.288 + } while (1); 1.289 + } 1.290 + 1.291 + // if we get here, there aren't any elements left. 1.292 + *aResult = false; 1.293 + return NS_OK; 1.294 +} 1.295 + 1.296 + 1.297 +NS_IMETHODIMP 1.298 +CompositeEnumeratorImpl::GetNext(nsISupports** aResult) 1.299 +{ 1.300 + nsresult rv; 1.301 + 1.302 + bool hasMore; 1.303 + rv = HasMoreElements(&hasMore); 1.304 + if (NS_FAILED(rv)) return rv; 1.305 + 1.306 + if (! hasMore) 1.307 + return NS_ERROR_UNEXPECTED; 1.308 + 1.309 + // Don't AddRef: we "transfer" ownership to the caller 1.310 + *aResult = mResult; 1.311 + mResult = nullptr; 1.312 + 1.313 + return NS_OK; 1.314 +} 1.315 + 1.316 +//---------------------------------------------------------------------- 1.317 +// 1.318 +// CompositeArcsInOutEnumeratorImpl 1.319 +// 1.320 +// 1.321 + 1.322 +class CompositeArcsInOutEnumeratorImpl : public CompositeEnumeratorImpl 1.323 +{ 1.324 +public: 1.325 + enum Type { eArcsIn, eArcsOut }; 1.326 + 1.327 + virtual ~CompositeArcsInOutEnumeratorImpl(); 1.328 + 1.329 + virtual nsresult 1.330 + GetEnumerator(nsIRDFDataSource* aDataSource, nsISimpleEnumerator** aResult); 1.331 + 1.332 + virtual nsresult 1.333 + HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, bool* aResult); 1.334 + 1.335 + CompositeArcsInOutEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource, 1.336 + nsIRDFNode* aNode, 1.337 + Type aType, 1.338 + bool aAllowNegativeAssertions, 1.339 + bool aCoalesceDuplicateArcs); 1.340 + 1.341 +private: 1.342 + nsIRDFNode* mNode; 1.343 + Type mType; 1.344 +}; 1.345 + 1.346 + 1.347 +CompositeArcsInOutEnumeratorImpl::CompositeArcsInOutEnumeratorImpl( 1.348 + CompositeDataSourceImpl* aCompositeDataSource, 1.349 + nsIRDFNode* aNode, 1.350 + Type aType, 1.351 + bool aAllowNegativeAssertions, 1.352 + bool aCoalesceDuplicateArcs) 1.353 + : CompositeEnumeratorImpl(aCompositeDataSource, aAllowNegativeAssertions, aCoalesceDuplicateArcs), 1.354 + mNode(aNode), 1.355 + mType(aType) 1.356 +{ 1.357 + NS_ADDREF(mNode); 1.358 +} 1.359 + 1.360 +CompositeArcsInOutEnumeratorImpl::~CompositeArcsInOutEnumeratorImpl() 1.361 +{ 1.362 + NS_RELEASE(mNode); 1.363 +} 1.364 + 1.365 + 1.366 +nsresult 1.367 +CompositeArcsInOutEnumeratorImpl::GetEnumerator( 1.368 + nsIRDFDataSource* aDataSource, 1.369 + nsISimpleEnumerator** aResult) 1.370 +{ 1.371 + if (mType == eArcsIn) { 1.372 + return aDataSource->ArcLabelsIn(mNode, aResult); 1.373 + } 1.374 + else { 1.375 + nsCOMPtr<nsIRDFResource> resource( do_QueryInterface(mNode) ); 1.376 + return aDataSource->ArcLabelsOut(resource, aResult); 1.377 + } 1.378 +} 1.379 + 1.380 +nsresult 1.381 +CompositeArcsInOutEnumeratorImpl::HasNegation( 1.382 + nsIRDFDataSource* aDataSource, 1.383 + nsIRDFNode* aNode, 1.384 + bool* aResult) 1.385 +{ 1.386 + *aResult = false; 1.387 + return NS_OK; 1.388 +} 1.389 + 1.390 + 1.391 +//---------------------------------------------------------------------- 1.392 +// 1.393 +// CompositeAssertionEnumeratorImpl 1.394 +// 1.395 + 1.396 +class CompositeAssertionEnumeratorImpl : public CompositeEnumeratorImpl 1.397 +{ 1.398 +public: 1.399 + virtual nsresult 1.400 + GetEnumerator(nsIRDFDataSource* aDataSource, nsISimpleEnumerator** aResult); 1.401 + 1.402 + virtual nsresult 1.403 + HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, bool* aResult); 1.404 + 1.405 + CompositeAssertionEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource, 1.406 + nsIRDFResource* aSource, 1.407 + nsIRDFResource* aProperty, 1.408 + nsIRDFNode* aTarget, 1.409 + bool aTruthValue, 1.410 + bool aAllowNegativeAssertions, 1.411 + bool aCoalesceDuplicateArcs); 1.412 + 1.413 + virtual ~CompositeAssertionEnumeratorImpl(); 1.414 + 1.415 +private: 1.416 + nsIRDFResource* mSource; 1.417 + nsIRDFResource* mProperty; 1.418 + nsIRDFNode* mTarget; 1.419 + bool mTruthValue; 1.420 +}; 1.421 + 1.422 + 1.423 +CompositeAssertionEnumeratorImpl::CompositeAssertionEnumeratorImpl( 1.424 + CompositeDataSourceImpl* aCompositeDataSource, 1.425 + nsIRDFResource* aSource, 1.426 + nsIRDFResource* aProperty, 1.427 + nsIRDFNode* aTarget, 1.428 + bool aTruthValue, 1.429 + bool aAllowNegativeAssertions, 1.430 + bool aCoalesceDuplicateArcs) 1.431 + : CompositeEnumeratorImpl(aCompositeDataSource, aAllowNegativeAssertions, aCoalesceDuplicateArcs), 1.432 + mSource(aSource), 1.433 + mProperty(aProperty), 1.434 + mTarget(aTarget), 1.435 + mTruthValue(aTruthValue) 1.436 +{ 1.437 + NS_IF_ADDREF(mSource); 1.438 + NS_ADDREF(mProperty); // always must be specified 1.439 + NS_IF_ADDREF(mTarget); 1.440 +} 1.441 + 1.442 +CompositeAssertionEnumeratorImpl::~CompositeAssertionEnumeratorImpl() 1.443 +{ 1.444 + NS_IF_RELEASE(mSource); 1.445 + NS_RELEASE(mProperty); 1.446 + NS_IF_RELEASE(mTarget); 1.447 +} 1.448 + 1.449 + 1.450 +nsresult 1.451 +CompositeAssertionEnumeratorImpl::GetEnumerator( 1.452 + nsIRDFDataSource* aDataSource, 1.453 + nsISimpleEnumerator** aResult) 1.454 +{ 1.455 + if (mSource) { 1.456 + return aDataSource->GetTargets(mSource, mProperty, mTruthValue, aResult); 1.457 + } 1.458 + else { 1.459 + return aDataSource->GetSources(mProperty, mTarget, mTruthValue, aResult); 1.460 + } 1.461 +} 1.462 + 1.463 +nsresult 1.464 +CompositeAssertionEnumeratorImpl::HasNegation( 1.465 + nsIRDFDataSource* aDataSource, 1.466 + nsIRDFNode* aNode, 1.467 + bool* aResult) 1.468 +{ 1.469 + if (mSource) { 1.470 + return aDataSource->HasAssertion(mSource, mProperty, aNode, !mTruthValue, aResult); 1.471 + } 1.472 + else { 1.473 + nsCOMPtr<nsIRDFResource> source( do_QueryInterface(aNode) ); 1.474 + return aDataSource->HasAssertion(source, mProperty, mTarget, !mTruthValue, aResult); 1.475 + } 1.476 +} 1.477 + 1.478 +//////////////////////////////////////////////////////////////////////// 1.479 + 1.480 +nsresult 1.481 +NS_NewRDFCompositeDataSource(nsIRDFCompositeDataSource** result) 1.482 +{ 1.483 + CompositeDataSourceImpl* db = new CompositeDataSourceImpl(); 1.484 + if (! db) 1.485 + return NS_ERROR_OUT_OF_MEMORY; 1.486 + 1.487 + *result = db; 1.488 + NS_ADDREF(*result); 1.489 + return NS_OK; 1.490 +} 1.491 + 1.492 + 1.493 +CompositeDataSourceImpl::CompositeDataSourceImpl(void) 1.494 + : mAllowNegativeAssertions(true), 1.495 + mCoalesceDuplicateArcs(true), 1.496 + mUpdateBatchNest(0) 1.497 +{ 1.498 +#ifdef PR_LOGGING 1.499 + if (nsRDFLog == nullptr) 1.500 + nsRDFLog = PR_NewLogModule("RDF"); 1.501 +#endif 1.502 +} 1.503 + 1.504 +//---------------------------------------------------------------------- 1.505 +// 1.506 +// nsISupports interface 1.507 +// 1.508 + 1.509 +NS_IMPL_CYCLE_COLLECTION_CLASS(CompositeDataSourceImpl) 1.510 + 1.511 +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CompositeDataSourceImpl) 1.512 + uint32_t i, count = tmp->mDataSources.Count(); 1.513 + for (i = count; i > 0; --i) { 1.514 + tmp->mDataSources[i - 1]->RemoveObserver(tmp); 1.515 + tmp->mDataSources.RemoveObjectAt(i - 1); 1.516 + } 1.517 + NS_IMPL_CYCLE_COLLECTION_UNLINK(mObservers); 1.518 +NS_IMPL_CYCLE_COLLECTION_UNLINK_END 1.519 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CompositeDataSourceImpl) 1.520 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObservers) 1.521 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDataSources) 1.522 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.523 + 1.524 + 1.525 +NS_IMPL_CYCLE_COLLECTING_ADDREF(CompositeDataSourceImpl) 1.526 +NS_IMPL_CYCLE_COLLECTING_RELEASE(CompositeDataSourceImpl) 1.527 + 1.528 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CompositeDataSourceImpl) 1.529 + NS_INTERFACE_MAP_ENTRY(nsIRDFCompositeDataSource) 1.530 + NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource) 1.531 + NS_INTERFACE_MAP_ENTRY(nsIRDFObserver) 1.532 + NS_INTERFACE_MAP_ENTRY(nsIRDFCompositeDataSource) 1.533 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFCompositeDataSource) 1.534 +NS_INTERFACE_MAP_END 1.535 + 1.536 + 1.537 +//---------------------------------------------------------------------- 1.538 +// 1.539 +// nsIRDFDataSource interface 1.540 +// 1.541 + 1.542 +NS_IMETHODIMP 1.543 +CompositeDataSourceImpl::GetURI(char* *uri) 1.544 +{ 1.545 + *uri = nullptr; 1.546 + return NS_OK; 1.547 +} 1.548 + 1.549 +NS_IMETHODIMP 1.550 +CompositeDataSourceImpl::GetSource(nsIRDFResource* property, 1.551 + nsIRDFNode* target, 1.552 + bool tv, 1.553 + nsIRDFResource** source) 1.554 +{ 1.555 + if (!mAllowNegativeAssertions && !tv) 1.556 + return(NS_RDF_NO_VALUE); 1.557 + 1.558 + int32_t count = mDataSources.Count(); 1.559 + for (int32_t i = 0; i < count; ++i) { 1.560 + nsresult rv; 1.561 + rv = mDataSources[i]->GetSource(property, target, tv, source); 1.562 + if (NS_FAILED(rv)) return rv; 1.563 + 1.564 + if (rv == NS_RDF_NO_VALUE) 1.565 + continue; 1.566 + 1.567 + if (!mAllowNegativeAssertions) return(NS_OK); 1.568 + 1.569 + // okay, found it. make sure we don't have the opposite 1.570 + // asserted in a more local data source 1.571 + if (!HasAssertionN(count-1, *source, property, target, !tv)) 1.572 + return NS_OK; 1.573 + 1.574 + NS_RELEASE(*source); 1.575 + return NS_RDF_NO_VALUE; 1.576 + } 1.577 + return NS_RDF_NO_VALUE; 1.578 +} 1.579 + 1.580 +NS_IMETHODIMP 1.581 +CompositeDataSourceImpl::GetSources(nsIRDFResource* aProperty, 1.582 + nsIRDFNode* aTarget, 1.583 + bool aTruthValue, 1.584 + nsISimpleEnumerator** aResult) 1.585 +{ 1.586 + NS_PRECONDITION(aProperty != nullptr, "null ptr"); 1.587 + if (! aProperty) 1.588 + return NS_ERROR_NULL_POINTER; 1.589 + 1.590 + NS_PRECONDITION(aTarget != nullptr, "null ptr"); 1.591 + if (! aTarget) 1.592 + return NS_ERROR_NULL_POINTER; 1.593 + 1.594 + NS_PRECONDITION(aResult != nullptr, "null ptr"); 1.595 + if (! aResult) 1.596 + return NS_ERROR_NULL_POINTER; 1.597 + 1.598 + if (! mAllowNegativeAssertions && ! aTruthValue) 1.599 + return(NS_RDF_NO_VALUE); 1.600 + 1.601 + *aResult = new CompositeAssertionEnumeratorImpl(this, nullptr, aProperty, 1.602 + aTarget, aTruthValue, 1.603 + mAllowNegativeAssertions, 1.604 + mCoalesceDuplicateArcs); 1.605 + 1.606 + if (! *aResult) 1.607 + return NS_ERROR_OUT_OF_MEMORY; 1.608 + 1.609 + NS_ADDREF(*aResult); 1.610 + return NS_OK; 1.611 +} 1.612 + 1.613 +NS_IMETHODIMP 1.614 +CompositeDataSourceImpl::GetTarget(nsIRDFResource* aSource, 1.615 + nsIRDFResource* aProperty, 1.616 + bool aTruthValue, 1.617 + nsIRDFNode** aResult) 1.618 +{ 1.619 + NS_PRECONDITION(aSource != nullptr, "null ptr"); 1.620 + if (! aSource) 1.621 + return NS_ERROR_NULL_POINTER; 1.622 + 1.623 + NS_PRECONDITION(aProperty != nullptr, "null ptr"); 1.624 + if (! aProperty) 1.625 + return NS_ERROR_NULL_POINTER; 1.626 + 1.627 + NS_PRECONDITION(aResult != nullptr, "null ptr"); 1.628 + if (! aResult) 1.629 + return NS_ERROR_NULL_POINTER; 1.630 + 1.631 + if (! mAllowNegativeAssertions && ! aTruthValue) 1.632 + return(NS_RDF_NO_VALUE); 1.633 + 1.634 + int32_t count = mDataSources.Count(); 1.635 + for (int32_t i = 0; i < count; ++i) { 1.636 + nsresult rv; 1.637 + rv = mDataSources[i]->GetTarget(aSource, aProperty, aTruthValue, 1.638 + aResult); 1.639 + if (NS_FAILED(rv)) 1.640 + return rv; 1.641 + 1.642 + if (rv == NS_OK) { 1.643 + // okay, found it. make sure we don't have the opposite 1.644 + // asserted in an earlier data source 1.645 + 1.646 + if (mAllowNegativeAssertions) { 1.647 + if (HasAssertionN(count-1, aSource, aProperty, *aResult, !aTruthValue)) { 1.648 + // whoops, it's been negated. 1.649 + NS_RELEASE(*aResult); 1.650 + return NS_RDF_NO_VALUE; 1.651 + } 1.652 + } 1.653 + return NS_OK; 1.654 + } 1.655 + } 1.656 + 1.657 + // Otherwise, we couldn't find it at all. 1.658 + return NS_RDF_NO_VALUE; 1.659 +} 1.660 + 1.661 +bool 1.662 +CompositeDataSourceImpl::HasAssertionN(int n, 1.663 + nsIRDFResource* aSource, 1.664 + nsIRDFResource* aProperty, 1.665 + nsIRDFNode* aTarget, 1.666 + bool aTruthValue) 1.667 +{ 1.668 + nsresult rv; 1.669 + for (int32_t m = 0; m < n; ++m) { 1.670 + bool result; 1.671 + rv = mDataSources[m]->HasAssertion(aSource, aProperty, aTarget, 1.672 + aTruthValue, &result); 1.673 + if (NS_FAILED(rv)) 1.674 + return false; 1.675 + 1.676 + // found it! 1.677 + if (result) 1.678 + return true; 1.679 + } 1.680 + return false; 1.681 +} 1.682 + 1.683 + 1.684 + 1.685 +NS_IMETHODIMP 1.686 +CompositeDataSourceImpl::GetTargets(nsIRDFResource* aSource, 1.687 + nsIRDFResource* aProperty, 1.688 + bool aTruthValue, 1.689 + nsISimpleEnumerator** aResult) 1.690 +{ 1.691 + NS_PRECONDITION(aSource != nullptr, "null ptr"); 1.692 + if (! aSource) 1.693 + return NS_ERROR_NULL_POINTER; 1.694 + 1.695 + NS_PRECONDITION(aProperty != nullptr, "null ptr"); 1.696 + if (! aProperty) 1.697 + return NS_ERROR_NULL_POINTER; 1.698 + 1.699 + NS_PRECONDITION(aResult != nullptr, "null ptr"); 1.700 + if (! aResult) 1.701 + return NS_ERROR_NULL_POINTER; 1.702 + 1.703 + if (! mAllowNegativeAssertions && ! aTruthValue) 1.704 + return(NS_RDF_NO_VALUE); 1.705 + 1.706 + *aResult = 1.707 + new CompositeAssertionEnumeratorImpl(this, 1.708 + aSource, aProperty, nullptr, 1.709 + aTruthValue, 1.710 + mAllowNegativeAssertions, 1.711 + mCoalesceDuplicateArcs); 1.712 + 1.713 + if (! *aResult) 1.714 + return NS_ERROR_OUT_OF_MEMORY; 1.715 + 1.716 + NS_ADDREF(*aResult); 1.717 + return NS_OK; 1.718 +} 1.719 + 1.720 +NS_IMETHODIMP 1.721 +CompositeDataSourceImpl::Assert(nsIRDFResource* aSource, 1.722 + nsIRDFResource* aProperty, 1.723 + nsIRDFNode* aTarget, 1.724 + bool aTruthValue) 1.725 +{ 1.726 + NS_PRECONDITION(aSource != nullptr, "null ptr"); 1.727 + if (! aSource) 1.728 + return NS_ERROR_NULL_POINTER; 1.729 + 1.730 + NS_PRECONDITION(aProperty != nullptr, "null ptr"); 1.731 + if (! aProperty) 1.732 + return NS_ERROR_NULL_POINTER; 1.733 + 1.734 + NS_PRECONDITION(aTarget != nullptr, "null ptr"); 1.735 + if (! aTarget) 1.736 + return NS_ERROR_NULL_POINTER; 1.737 + 1.738 + if (! mAllowNegativeAssertions && ! aTruthValue) 1.739 + return(NS_RDF_ASSERTION_REJECTED); 1.740 + 1.741 + nsresult rv; 1.742 + 1.743 + // XXX Need to add back the stuff for unblocking ... 1.744 + 1.745 + // We iterate backwards from the last data source which was added 1.746 + // ("the most remote") to the first ("the most local"), trying to 1.747 + // apply the assertion in each. 1.748 + for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) { 1.749 + rv = mDataSources[i]->Assert(aSource, aProperty, aTarget, aTruthValue); 1.750 + if (NS_RDF_ASSERTION_ACCEPTED == rv) 1.751 + return rv; 1.752 + 1.753 + if (NS_FAILED(rv)) 1.754 + return rv; 1.755 + } 1.756 + 1.757 + // nobody wanted to accept it 1.758 + return NS_RDF_ASSERTION_REJECTED; 1.759 +} 1.760 + 1.761 +NS_IMETHODIMP 1.762 +CompositeDataSourceImpl::Unassert(nsIRDFResource* aSource, 1.763 + nsIRDFResource* aProperty, 1.764 + nsIRDFNode* aTarget) 1.765 +{ 1.766 + NS_PRECONDITION(aSource != nullptr, "null ptr"); 1.767 + if (! aSource) 1.768 + return NS_ERROR_NULL_POINTER; 1.769 + 1.770 + NS_PRECONDITION(aProperty != nullptr, "null ptr"); 1.771 + if (! aProperty) 1.772 + return NS_ERROR_NULL_POINTER; 1.773 + 1.774 + NS_PRECONDITION(aTarget != nullptr, "null ptr"); 1.775 + if (! aTarget) 1.776 + return NS_ERROR_NULL_POINTER; 1.777 + 1.778 + nsresult rv; 1.779 + 1.780 + // Iterate through each of the datasources, starting with "the 1.781 + // most local" and moving to "the most remote". If _any_ of the 1.782 + // datasources have the assertion, attempt to unassert it. 1.783 + bool unasserted = true; 1.784 + int32_t i; 1.785 + int32_t count = mDataSources.Count(); 1.786 + for (i = 0; i < count; ++i) { 1.787 + nsIRDFDataSource* ds = mDataSources[i]; 1.788 + 1.789 + bool hasAssertion; 1.790 + rv = ds->HasAssertion(aSource, aProperty, aTarget, true, &hasAssertion); 1.791 + if (NS_FAILED(rv)) return rv; 1.792 + 1.793 + if (hasAssertion) { 1.794 + rv = ds->Unassert(aSource, aProperty, aTarget); 1.795 + if (NS_FAILED(rv)) return rv; 1.796 + 1.797 + if (rv != NS_RDF_ASSERTION_ACCEPTED) { 1.798 + unasserted = false; 1.799 + break; 1.800 + } 1.801 + } 1.802 + } 1.803 + 1.804 + // Either none of the datasources had it, or they were all willing 1.805 + // to let it be unasserted. 1.806 + if (unasserted) 1.807 + return NS_RDF_ASSERTION_ACCEPTED; 1.808 + 1.809 + // If we get here, one of the datasources already had the 1.810 + // assertion, and was adamant about not letting us remove 1.811 + // it. Iterate from the "most local" to the "most remote" 1.812 + // attempting to assert the negation... 1.813 + for (i = 0; i < count; ++i) { 1.814 + rv = mDataSources[i]->Assert(aSource, aProperty, aTarget, false); 1.815 + if (NS_FAILED(rv)) return rv; 1.816 + 1.817 + // Did it take? 1.818 + if (rv == NS_RDF_ASSERTION_ACCEPTED) 1.819 + return rv; 1.820 + } 1.821 + 1.822 + // Couln't get anyone to accept the negation, either. 1.823 + return NS_RDF_ASSERTION_REJECTED; 1.824 +} 1.825 + 1.826 +NS_IMETHODIMP 1.827 +CompositeDataSourceImpl::Change(nsIRDFResource* aSource, 1.828 + nsIRDFResource* aProperty, 1.829 + nsIRDFNode* aOldTarget, 1.830 + nsIRDFNode* aNewTarget) 1.831 +{ 1.832 + NS_PRECONDITION(aSource != nullptr, "null ptr"); 1.833 + if (! aSource) 1.834 + return NS_ERROR_NULL_POINTER; 1.835 + 1.836 + NS_PRECONDITION(aProperty != nullptr, "null ptr"); 1.837 + if (! aProperty) 1.838 + return NS_ERROR_NULL_POINTER; 1.839 + 1.840 + NS_PRECONDITION(aOldTarget != nullptr, "null ptr"); 1.841 + if (! aOldTarget) 1.842 + return NS_ERROR_NULL_POINTER; 1.843 + 1.844 + NS_PRECONDITION(aNewTarget != nullptr, "null ptr"); 1.845 + if (! aNewTarget) 1.846 + return NS_ERROR_NULL_POINTER; 1.847 + 1.848 + nsresult rv; 1.849 + 1.850 + // XXX So we're assuming that a datasource _must_ accept the 1.851 + // atomic change; i.e., we can't split it up across two 1.852 + // datasources. That sucks. 1.853 + 1.854 + // We iterate backwards from the last data source which was added 1.855 + // ("the most remote") to the first ("the most local"), trying to 1.856 + // apply the change in each. 1.857 + for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) { 1.858 + rv = mDataSources[i]->Change(aSource, aProperty, aOldTarget, aNewTarget); 1.859 + if (NS_RDF_ASSERTION_ACCEPTED == rv) 1.860 + return rv; 1.861 + 1.862 + if (NS_FAILED(rv)) 1.863 + return rv; 1.864 + } 1.865 + 1.866 + // nobody wanted to accept it 1.867 + return NS_RDF_ASSERTION_REJECTED; 1.868 +} 1.869 + 1.870 +NS_IMETHODIMP 1.871 +CompositeDataSourceImpl::Move(nsIRDFResource* aOldSource, 1.872 + nsIRDFResource* aNewSource, 1.873 + nsIRDFResource* aProperty, 1.874 + nsIRDFNode* aTarget) 1.875 +{ 1.876 + NS_PRECONDITION(aOldSource != nullptr, "null ptr"); 1.877 + if (! aOldSource) 1.878 + return NS_ERROR_NULL_POINTER; 1.879 + 1.880 + NS_PRECONDITION(aNewSource != nullptr, "null ptr"); 1.881 + if (! aNewSource) 1.882 + return NS_ERROR_NULL_POINTER; 1.883 + 1.884 + NS_PRECONDITION(aProperty != nullptr, "null ptr"); 1.885 + if (! aProperty) 1.886 + return NS_ERROR_NULL_POINTER; 1.887 + 1.888 + NS_PRECONDITION(aTarget != nullptr, "null ptr"); 1.889 + if (! aTarget) 1.890 + return NS_ERROR_NULL_POINTER; 1.891 + 1.892 + nsresult rv; 1.893 + 1.894 + // XXX So we're assuming that a datasource _must_ accept the 1.895 + // atomic move; i.e., we can't split it up across two 1.896 + // datasources. That sucks. 1.897 + 1.898 + // We iterate backwards from the last data source which was added 1.899 + // ("the most remote") to the first ("the most local"), trying to 1.900 + // apply the assertion in each. 1.901 + for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) { 1.902 + rv = mDataSources[i]->Move(aOldSource, aNewSource, aProperty, aTarget); 1.903 + if (NS_RDF_ASSERTION_ACCEPTED == rv) 1.904 + return rv; 1.905 + 1.906 + if (NS_FAILED(rv)) 1.907 + return rv; 1.908 + } 1.909 + 1.910 + // nobody wanted to accept it 1.911 + return NS_RDF_ASSERTION_REJECTED; 1.912 +} 1.913 + 1.914 + 1.915 +NS_IMETHODIMP 1.916 +CompositeDataSourceImpl::HasAssertion(nsIRDFResource* aSource, 1.917 + nsIRDFResource* aProperty, 1.918 + nsIRDFNode* aTarget, 1.919 + bool aTruthValue, 1.920 + bool* aResult) 1.921 +{ 1.922 + NS_PRECONDITION(aSource != nullptr, "null ptr"); 1.923 + if (! aSource) 1.924 + return NS_ERROR_NULL_POINTER; 1.925 + 1.926 + NS_PRECONDITION(aProperty != nullptr, "null ptr"); 1.927 + if (! aProperty) 1.928 + return NS_ERROR_NULL_POINTER; 1.929 + 1.930 + NS_PRECONDITION(aResult != nullptr, "null ptr"); 1.931 + if (! aResult) 1.932 + return NS_ERROR_NULL_POINTER; 1.933 + 1.934 + if (! mAllowNegativeAssertions && ! aTruthValue) 1.935 + { 1.936 + *aResult = false; 1.937 + return(NS_OK); 1.938 + } 1.939 + 1.940 + nsresult rv; 1.941 + 1.942 + // Otherwise, look through all the data sources to see if anyone 1.943 + // has the positive... 1.944 + int32_t count = mDataSources.Count(); 1.945 + for (int32_t i = 0; i < count; ++i) { 1.946 + nsIRDFDataSource* datasource = mDataSources[i]; 1.947 + rv = datasource->HasAssertion(aSource, aProperty, aTarget, aTruthValue, aResult); 1.948 + if (NS_FAILED(rv)) return rv; 1.949 + 1.950 + if (*aResult) 1.951 + return NS_OK; 1.952 + 1.953 + if (mAllowNegativeAssertions) 1.954 + { 1.955 + bool hasNegation; 1.956 + rv = datasource->HasAssertion(aSource, aProperty, aTarget, !aTruthValue, &hasNegation); 1.957 + if (NS_FAILED(rv)) return rv; 1.958 + 1.959 + if (hasNegation) 1.960 + { 1.961 + *aResult = false; 1.962 + return NS_OK; 1.963 + } 1.964 + } 1.965 + } 1.966 + 1.967 + // If we get here, nobody had the assertion at all 1.968 + *aResult = false; 1.969 + return NS_OK; 1.970 +} 1.971 + 1.972 +NS_IMETHODIMP 1.973 +CompositeDataSourceImpl::AddObserver(nsIRDFObserver* aObserver) 1.974 +{ 1.975 + NS_PRECONDITION(aObserver != nullptr, "null ptr"); 1.976 + if (! aObserver) 1.977 + return NS_ERROR_NULL_POINTER; 1.978 + 1.979 + // XXX ensure uniqueness? 1.980 + mObservers.AppendObject(aObserver); 1.981 + 1.982 + return NS_OK; 1.983 +} 1.984 + 1.985 +NS_IMETHODIMP 1.986 +CompositeDataSourceImpl::RemoveObserver(nsIRDFObserver* aObserver) 1.987 +{ 1.988 + NS_PRECONDITION(aObserver != nullptr, "null ptr"); 1.989 + if (! aObserver) 1.990 + return NS_ERROR_NULL_POINTER; 1.991 + 1.992 + mObservers.RemoveObject(aObserver); 1.993 + 1.994 + return NS_OK; 1.995 +} 1.996 + 1.997 +NS_IMETHODIMP 1.998 +CompositeDataSourceImpl::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result) 1.999 +{ 1.1000 + nsresult rv; 1.1001 + *result = false; 1.1002 + int32_t count = mDataSources.Count(); 1.1003 + for (int32_t i = 0; i < count; ++i) { 1.1004 + rv = mDataSources[i]->HasArcIn(aNode, aArc, result); 1.1005 + if (NS_FAILED(rv)) return rv; 1.1006 + if (*result) 1.1007 + return NS_OK; 1.1008 + } 1.1009 + return NS_OK; 1.1010 +} 1.1011 + 1.1012 +NS_IMETHODIMP 1.1013 +CompositeDataSourceImpl::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *result) 1.1014 +{ 1.1015 + nsresult rv; 1.1016 + *result = false; 1.1017 + int32_t count = mDataSources.Count(); 1.1018 + for (int32_t i = 0; i < count; ++i) { 1.1019 + rv = mDataSources[i]->HasArcOut(aSource, aArc, result); 1.1020 + if (NS_FAILED(rv)) return rv; 1.1021 + if (*result) 1.1022 + return NS_OK; 1.1023 + } 1.1024 + return NS_OK; 1.1025 +} 1.1026 + 1.1027 +NS_IMETHODIMP 1.1028 +CompositeDataSourceImpl::ArcLabelsIn(nsIRDFNode* aTarget, nsISimpleEnumerator** aResult) 1.1029 +{ 1.1030 + NS_PRECONDITION(aTarget != nullptr, "null ptr"); 1.1031 + if (! aTarget) 1.1032 + return NS_ERROR_NULL_POINTER; 1.1033 + 1.1034 + NS_PRECONDITION(aResult != nullptr, "null ptr"); 1.1035 + if (! aResult) 1.1036 + return NS_ERROR_NULL_POINTER; 1.1037 + 1.1038 + nsISimpleEnumerator* result = 1.1039 + new CompositeArcsInOutEnumeratorImpl(this, aTarget, 1.1040 + CompositeArcsInOutEnumeratorImpl::eArcsIn, 1.1041 + mAllowNegativeAssertions, 1.1042 + mCoalesceDuplicateArcs); 1.1043 + 1.1044 + if (! result) 1.1045 + return NS_ERROR_OUT_OF_MEMORY; 1.1046 + 1.1047 + NS_ADDREF(result); 1.1048 + *aResult = result; 1.1049 + return NS_OK; 1.1050 +} 1.1051 + 1.1052 +NS_IMETHODIMP 1.1053 +CompositeDataSourceImpl::ArcLabelsOut(nsIRDFResource* aSource, 1.1054 + nsISimpleEnumerator** aResult) 1.1055 +{ 1.1056 + NS_PRECONDITION(aSource != nullptr, "null ptr"); 1.1057 + if (! aSource) 1.1058 + return NS_ERROR_NULL_POINTER; 1.1059 + 1.1060 + NS_PRECONDITION(aResult != nullptr, "null ptr"); 1.1061 + if (! aResult) 1.1062 + return NS_ERROR_NULL_POINTER; 1.1063 + 1.1064 + nsISimpleEnumerator* result = 1.1065 + new CompositeArcsInOutEnumeratorImpl(this, aSource, 1.1066 + CompositeArcsInOutEnumeratorImpl::eArcsOut, 1.1067 + mAllowNegativeAssertions, 1.1068 + mCoalesceDuplicateArcs); 1.1069 + 1.1070 + if (! result) 1.1071 + return NS_ERROR_OUT_OF_MEMORY; 1.1072 + 1.1073 + NS_ADDREF(result); 1.1074 + *aResult = result; 1.1075 + return NS_OK; 1.1076 +} 1.1077 + 1.1078 +NS_IMETHODIMP 1.1079 +CompositeDataSourceImpl::GetAllResources(nsISimpleEnumerator** aResult) 1.1080 +{ 1.1081 + NS_NOTYETIMPLEMENTED("CompositeDataSourceImpl::GetAllResources"); 1.1082 + return NS_ERROR_NOT_IMPLEMENTED; 1.1083 +} 1.1084 + 1.1085 +NS_IMETHODIMP 1.1086 +CompositeDataSourceImpl::GetAllCmds(nsIRDFResource* source, 1.1087 + nsISimpleEnumerator/*<nsIRDFResource>*/** result) 1.1088 +{ 1.1089 + nsresult rv; 1.1090 + nsCOMPtr<nsISimpleEnumerator> set; 1.1091 + 1.1092 + for (int32_t i = 0; i < mDataSources.Count(); i++) 1.1093 + { 1.1094 + nsCOMPtr<nsISimpleEnumerator> dsCmds; 1.1095 + 1.1096 + rv = mDataSources[i]->GetAllCmds(source, getter_AddRefs(dsCmds)); 1.1097 + if (NS_SUCCEEDED(rv)) 1.1098 + { 1.1099 + nsCOMPtr<nsISimpleEnumerator> tmp; 1.1100 + rv = NS_NewUnionEnumerator(getter_AddRefs(tmp), set, dsCmds); 1.1101 + set.swap(tmp); 1.1102 + if (NS_FAILED(rv)) return(rv); 1.1103 + } 1.1104 + } 1.1105 + 1.1106 + set.forget(result); 1.1107 + return NS_OK; 1.1108 +} 1.1109 + 1.1110 +NS_IMETHODIMP 1.1111 +CompositeDataSourceImpl::IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources, 1.1112 + nsIRDFResource* aCommand, 1.1113 + nsISupportsArray/*<nsIRDFResource>*/* aArguments, 1.1114 + bool* aResult) 1.1115 +{ 1.1116 + nsresult rv; 1.1117 + for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) { 1.1118 + bool enabled = true; 1.1119 + rv = mDataSources[i]->IsCommandEnabled(aSources, aCommand, aArguments, &enabled); 1.1120 + if (NS_FAILED(rv) && (rv != NS_ERROR_NOT_IMPLEMENTED)) 1.1121 + { 1.1122 + return(rv); 1.1123 + } 1.1124 + 1.1125 + if (! enabled) { 1.1126 + *aResult = false; 1.1127 + return(NS_OK); 1.1128 + } 1.1129 + } 1.1130 + *aResult = true; 1.1131 + return(NS_OK); 1.1132 +} 1.1133 + 1.1134 +NS_IMETHODIMP 1.1135 +CompositeDataSourceImpl::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources, 1.1136 + nsIRDFResource* aCommand, 1.1137 + nsISupportsArray/*<nsIRDFResource>*/* aArguments) 1.1138 +{ 1.1139 + for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) { 1.1140 + nsresult rv = mDataSources[i]->DoCommand(aSources, aCommand, aArguments); 1.1141 + if (NS_FAILED(rv) && (rv != NS_ERROR_NOT_IMPLEMENTED)) 1.1142 + { 1.1143 + return(rv); // all datasources must succeed 1.1144 + } 1.1145 + } 1.1146 + return(NS_OK); 1.1147 +} 1.1148 + 1.1149 +NS_IMETHODIMP 1.1150 +CompositeDataSourceImpl::BeginUpdateBatch() 1.1151 +{ 1.1152 + for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) { 1.1153 + mDataSources[i]->BeginUpdateBatch(); 1.1154 + } 1.1155 + return NS_OK; 1.1156 +} 1.1157 + 1.1158 +NS_IMETHODIMP 1.1159 +CompositeDataSourceImpl::EndUpdateBatch() 1.1160 +{ 1.1161 + for (int32_t i = mDataSources.Count() - 1; i >= 0; --i) { 1.1162 + mDataSources[i]->EndUpdateBatch(); 1.1163 + } 1.1164 + return NS_OK; 1.1165 +} 1.1166 + 1.1167 +//////////////////////////////////////////////////////////////////////// 1.1168 +// nsIRDFCompositeDataSource methods 1.1169 +// XXX rvg We should make this take an additional argument specifying where 1.1170 +// in the sequence of data sources (of the db), the new data source should 1.1171 +// fit in. Right now, the new datasource gets stuck at the end. 1.1172 +// need to add the observers of the CompositeDataSourceImpl to the new data source. 1.1173 + 1.1174 +NS_IMETHODIMP 1.1175 +CompositeDataSourceImpl::GetAllowNegativeAssertions(bool *aAllowNegativeAssertions) 1.1176 +{ 1.1177 + *aAllowNegativeAssertions = mAllowNegativeAssertions; 1.1178 + return(NS_OK); 1.1179 +} 1.1180 + 1.1181 +NS_IMETHODIMP 1.1182 +CompositeDataSourceImpl::SetAllowNegativeAssertions(bool aAllowNegativeAssertions) 1.1183 +{ 1.1184 + mAllowNegativeAssertions = aAllowNegativeAssertions; 1.1185 + return(NS_OK); 1.1186 +} 1.1187 + 1.1188 +NS_IMETHODIMP 1.1189 +CompositeDataSourceImpl::GetCoalesceDuplicateArcs(bool *aCoalesceDuplicateArcs) 1.1190 +{ 1.1191 + *aCoalesceDuplicateArcs = mCoalesceDuplicateArcs; 1.1192 + return(NS_OK); 1.1193 +} 1.1194 + 1.1195 +NS_IMETHODIMP 1.1196 +CompositeDataSourceImpl::SetCoalesceDuplicateArcs(bool aCoalesceDuplicateArcs) 1.1197 +{ 1.1198 + mCoalesceDuplicateArcs = aCoalesceDuplicateArcs; 1.1199 + return(NS_OK); 1.1200 +} 1.1201 + 1.1202 +NS_IMETHODIMP 1.1203 +CompositeDataSourceImpl::AddDataSource(nsIRDFDataSource* aDataSource) 1.1204 +{ 1.1205 + NS_ASSERTION(aDataSource != nullptr, "null ptr"); 1.1206 + if (! aDataSource) 1.1207 + return NS_ERROR_NULL_POINTER; 1.1208 + 1.1209 + mDataSources.AppendObject(aDataSource); 1.1210 + aDataSource->AddObserver(this); 1.1211 + return NS_OK; 1.1212 +} 1.1213 + 1.1214 + 1.1215 + 1.1216 +NS_IMETHODIMP 1.1217 +CompositeDataSourceImpl::RemoveDataSource(nsIRDFDataSource* aDataSource) 1.1218 +{ 1.1219 + NS_ASSERTION(aDataSource != nullptr, "null ptr"); 1.1220 + if (! aDataSource) 1.1221 + return NS_ERROR_NULL_POINTER; 1.1222 + 1.1223 + 1.1224 + if (mDataSources.IndexOf(aDataSource) >= 0) { 1.1225 + aDataSource->RemoveObserver(this); 1.1226 + mDataSources.RemoveObject(aDataSource); 1.1227 + } 1.1228 + return NS_OK; 1.1229 +} 1.1230 + 1.1231 + 1.1232 +NS_IMETHODIMP 1.1233 +CompositeDataSourceImpl::GetDataSources(nsISimpleEnumerator** _result) 1.1234 +{ 1.1235 + // NS_NewArrayEnumerator for an nsCOMArray takes a snapshot of the 1.1236 + // current state. 1.1237 + return NS_NewArrayEnumerator(_result, mDataSources); 1.1238 +} 1.1239 + 1.1240 +NS_IMETHODIMP 1.1241 +CompositeDataSourceImpl::OnAssert(nsIRDFDataSource* aDataSource, 1.1242 + nsIRDFResource* aSource, 1.1243 + nsIRDFResource* aProperty, 1.1244 + nsIRDFNode* aTarget) 1.1245 +{ 1.1246 + // Make sure that the assertion isn't masked by another 1.1247 + // datasource. 1.1248 + // 1.1249 + // XXX We could make this more efficient if we knew _which_ 1.1250 + // datasource actually served up the OnAssert(): we could use 1.1251 + // HasAssertionN() to only search datasources _before_ the 1.1252 + // datasource that coughed up the assertion. 1.1253 + nsresult rv = NS_OK; 1.1254 + 1.1255 + if (mAllowNegativeAssertions) 1.1256 + { 1.1257 + bool hasAssertion; 1.1258 + rv = HasAssertion(aSource, aProperty, aTarget, true, &hasAssertion); 1.1259 + if (NS_FAILED(rv)) return rv; 1.1260 + 1.1261 + if (! hasAssertion) 1.1262 + return(NS_OK); 1.1263 + } 1.1264 + 1.1265 + for (int32_t i = mObservers.Count() - 1; i >= 0; --i) { 1.1266 + mObservers[i]->OnAssert(this, aSource, aProperty, aTarget); 1.1267 + } 1.1268 + return NS_OK; 1.1269 +} 1.1270 + 1.1271 +NS_IMETHODIMP 1.1272 +CompositeDataSourceImpl::OnUnassert(nsIRDFDataSource* aDataSource, 1.1273 + nsIRDFResource* aSource, 1.1274 + nsIRDFResource* aProperty, 1.1275 + nsIRDFNode* aTarget) 1.1276 +{ 1.1277 + // Make sure that the un-assertion doesn't just unmask the 1.1278 + // same assertion in a different datasource. 1.1279 + // 1.1280 + // XXX We could make this more efficient if we knew _which_ 1.1281 + // datasource actually served up the OnAssert(): we could use 1.1282 + // HasAssertionN() to only search datasources _before_ the 1.1283 + // datasource that coughed up the assertion. 1.1284 + nsresult rv; 1.1285 + 1.1286 + if (mAllowNegativeAssertions) 1.1287 + { 1.1288 + bool hasAssertion; 1.1289 + rv = HasAssertion(aSource, aProperty, aTarget, true, &hasAssertion); 1.1290 + if (NS_FAILED(rv)) return rv; 1.1291 + 1.1292 + if (hasAssertion) 1.1293 + return NS_OK; 1.1294 + } 1.1295 + 1.1296 + for (int32_t i = mObservers.Count() - 1; i >= 0; --i) { 1.1297 + mObservers[i]->OnUnassert(this, aSource, aProperty, aTarget); 1.1298 + } 1.1299 + return NS_OK; 1.1300 +} 1.1301 + 1.1302 + 1.1303 +NS_IMETHODIMP 1.1304 +CompositeDataSourceImpl::OnChange(nsIRDFDataSource* aDataSource, 1.1305 + nsIRDFResource* aSource, 1.1306 + nsIRDFResource* aProperty, 1.1307 + nsIRDFNode* aOldTarget, 1.1308 + nsIRDFNode* aNewTarget) 1.1309 +{ 1.1310 + // Make sure that the change is actually visible, and not hidden 1.1311 + // by an assertion in a different datasource. 1.1312 + // 1.1313 + // XXX Because of aggregation, this could actually mutate into a 1.1314 + // variety of OnAssert or OnChange notifications, which we'll 1.1315 + // ignore for now :-/. 1.1316 + for (int32_t i = mObservers.Count() - 1; i >= 0; --i) { 1.1317 + mObservers[i]->OnChange(this, aSource, aProperty, 1.1318 + aOldTarget, aNewTarget); 1.1319 + } 1.1320 + return NS_OK; 1.1321 +} 1.1322 + 1.1323 + 1.1324 +NS_IMETHODIMP 1.1325 +CompositeDataSourceImpl::OnMove(nsIRDFDataSource* aDataSource, 1.1326 + nsIRDFResource* aOldSource, 1.1327 + nsIRDFResource* aNewSource, 1.1328 + nsIRDFResource* aProperty, 1.1329 + nsIRDFNode* aTarget) 1.1330 +{ 1.1331 + // Make sure that the move is actually visible, and not hidden 1.1332 + // by an assertion in a different datasource. 1.1333 + // 1.1334 + // XXX Because of aggregation, this could actually mutate into a 1.1335 + // variety of OnAssert or OnMove notifications, which we'll 1.1336 + // ignore for now :-/. 1.1337 + for (int32_t i = mObservers.Count() - 1; i >= 0; --i) { 1.1338 + mObservers[i]->OnMove(this, aOldSource, aNewSource, 1.1339 + aProperty, aTarget); 1.1340 + } 1.1341 + return NS_OK; 1.1342 +} 1.1343 + 1.1344 + 1.1345 +NS_IMETHODIMP 1.1346 +CompositeDataSourceImpl::OnBeginUpdateBatch(nsIRDFDataSource* aDataSource) 1.1347 +{ 1.1348 + if (mUpdateBatchNest++ == 0) { 1.1349 + for (int32_t i = mObservers.Count() - 1; i >= 0; --i) { 1.1350 + mObservers[i]->OnBeginUpdateBatch(this); 1.1351 + } 1.1352 + } 1.1353 + return NS_OK; 1.1354 +} 1.1355 + 1.1356 + 1.1357 +NS_IMETHODIMP 1.1358 +CompositeDataSourceImpl::OnEndUpdateBatch(nsIRDFDataSource* aDataSource) 1.1359 +{ 1.1360 + NS_ASSERTION(mUpdateBatchNest > 0, "badly nested update batch"); 1.1361 + if (--mUpdateBatchNest == 0) { 1.1362 + for (int32_t i = mObservers.Count() - 1; i >= 0; --i) { 1.1363 + mObservers[i]->OnEndUpdateBatch(this); 1.1364 + } 1.1365 + } 1.1366 + return NS_OK; 1.1367 +}