LCOV - code coverage report
Current view: directory - rdf/base/src - nsCompositeDataSource.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 540 3 0.6 %
Date: 2012-06-02 Functions: 77 3 3.9 %

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

Generated by: LCOV version 1.7