1998-12-24 05:07:14 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Netscape Public License
|
|
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
|
|
* http://www.mozilla.org/NPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* NPL.
|
|
|
|
*
|
|
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
|
|
* Communications Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
|
|
* Reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Implementation for an in-memory RDF data store.
|
|
|
|
|
1999-01-05 21:06:54 +00:00
|
|
|
TO DO
|
|
|
|
|
|
|
|
1) Instrument this code to gather space and time performance
|
|
|
|
characteristics.
|
|
|
|
|
|
|
|
2) If/when RDF containers become commonplace, consider implementing
|
|
|
|
a special case for them to improve access time to individual
|
|
|
|
elements.
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
3) Complete implementation of thread-safety; specifically, make
|
|
|
|
assertions be reference counted objects (so that a cursor can
|
|
|
|
still refer to an assertion that gets removed from the graph).
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "nscore.h"
|
1999-01-05 03:53:15 +00:00
|
|
|
#include "nsIOutputStream.h"
|
1998-12-24 05:07:14 +00:00
|
|
|
#include "nsIRDFCursor.h"
|
|
|
|
#include "nsIRDFDataSource.h"
|
|
|
|
#include "nsIRDFNode.h"
|
|
|
|
#include "nsIRDFObserver.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsVoidArray.h" // XXX introduces dependency on raptorbase
|
|
|
|
#include "nsRDFCID.h"
|
1999-01-05 03:53:15 +00:00
|
|
|
#include "nsString.h"
|
1999-03-29 19:52:54 +00:00
|
|
|
#include "nsXPIDLString.h"
|
1998-12-24 05:07:14 +00:00
|
|
|
#include "rdfutil.h"
|
|
|
|
#include "plhash.h"
|
|
|
|
#include "plstr.h"
|
1999-03-29 19:52:54 +00:00
|
|
|
#include "rdf.h"
|
1998-12-24 05:07:14 +00:00
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
|
|
|
|
#if 1 // defined(MOZ_THREADSAFE_RDF)
|
|
|
|
#include "nsAutoLock.h"
|
|
|
|
#define NS_AUTOLOCK(__monitor) nsAutoLock __lock(__monitor)
|
|
|
|
#else
|
|
|
|
#define NS_AUTOLOCK(__monitor)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
static NS_DEFINE_IID(kIRDFAssertionCursorIID, NS_IRDFASSERTIONCURSOR_IID);
|
|
|
|
static NS_DEFINE_IID(kIRDFArcsInCursorIID, NS_IRDFARCSINCURSOR_IID);
|
|
|
|
static NS_DEFINE_IID(kIRDFArcsOutCursorIID, NS_IRDFARCSOUTCURSOR_IID);
|
|
|
|
static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID);
|
|
|
|
static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID);
|
|
|
|
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
|
|
|
|
static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID);
|
|
|
|
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
|
1999-01-21 22:24:32 +00:00
|
|
|
static NS_DEFINE_IID(kIRDFResourceCursorIID, NS_IRDFRESOURCECURSOR_IID);
|
1998-12-24 05:07:14 +00:00
|
|
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
enum Direction {
|
|
|
|
eDirectionForwards,
|
|
|
|
eDirectionReverse
|
|
|
|
};
|
1998-12-24 05:07:14 +00:00
|
|
|
|
1999-01-05 21:06:54 +00:00
|
|
|
// This struct is used as the slot value in the forward and reverse
|
|
|
|
// arcs hash tables.
|
1999-01-05 03:53:15 +00:00
|
|
|
struct Assertion
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
|
|
|
nsIRDFResource* mSource;
|
|
|
|
nsIRDFResource* mProperty;
|
|
|
|
nsIRDFNode* mTarget;
|
1999-01-05 03:53:15 +00:00
|
|
|
PRBool mTruthValue;
|
1998-12-24 05:07:14 +00:00
|
|
|
Assertion* mNext;
|
|
|
|
Assertion* mInvNext;
|
1998-12-27 20:35:46 +00:00
|
|
|
};
|
1998-12-24 05:07:14 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
1999-01-05 21:06:54 +00:00
|
|
|
// Utility routines
|
1998-12-24 05:07:14 +00:00
|
|
|
|
|
|
|
static PLHashNumber
|
|
|
|
rdf_HashPointer(const void* key)
|
|
|
|
{
|
|
|
|
return (PLHashNumber) key;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PRIntn
|
|
|
|
rdf_CompareNodes(const void* v1, const void* v2)
|
|
|
|
{
|
|
|
|
nsIRDFNode* a = (nsIRDFNode*)v1;
|
|
|
|
nsIRDFNode* b = (nsIRDFNode*)v2;
|
|
|
|
|
|
|
|
PRBool result;
|
|
|
|
if (NS_FAILED(a->EqualsNode(b, &result)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return (PRIntn) result;
|
|
|
|
}
|
|
|
|
|
1999-01-05 08:44:40 +00:00
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// InMemoryDataSource
|
1999-01-21 22:24:32 +00:00
|
|
|
class InMemoryResourceCursor;
|
1998-12-24 05:07:14 +00:00
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
class InMemoryDataSource : public nsIRDFDataSource
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
|
|
|
protected:
|
|
|
|
char* mURL;
|
|
|
|
|
1999-01-05 21:06:54 +00:00
|
|
|
// These hash tables are keyed on pointers to nsIRDFResource
|
|
|
|
// objects (the nsIRDFService ensures that there is only ever one
|
|
|
|
// nsIRDFResource object per unique URI). The value of an entry is
|
|
|
|
// an Assertion struct, which is a linked list of (subject
|
|
|
|
// predicate object) triples.
|
1998-12-24 05:07:14 +00:00
|
|
|
PLHashTable* mForwardArcs;
|
|
|
|
PLHashTable* mReverseArcs;
|
|
|
|
|
|
|
|
nsVoidArray* mObservers;
|
|
|
|
|
|
|
|
static const PRInt32 kInitialTableSize;
|
|
|
|
|
1999-02-02 08:06:38 +00:00
|
|
|
static PRIntn DeleteForwardArcsEntry(PLHashEntry* he, PRIntn index, void* arg);
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
friend class InMemoryResourceCursor; // b/c it needs to enumerate mForwardArcs
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
// Thread-safe writer implementation methods.
|
|
|
|
nsresult
|
|
|
|
SafeAssert(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv);
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
SafeUnassert(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target);
|
|
|
|
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
public:
|
|
|
|
InMemoryDataSource(void);
|
|
|
|
virtual ~InMemoryDataSource(void);
|
|
|
|
|
|
|
|
// nsISupports
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
// nsIRDFDataSource methods
|
|
|
|
NS_IMETHOD Init(const char* uri);
|
|
|
|
|
1999-03-29 19:52:54 +00:00
|
|
|
NS_IMETHOD GetURI(char* *uri);
|
1999-01-05 03:53:15 +00:00
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
NS_IMETHOD GetSource(nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv,
|
|
|
|
nsIRDFResource** source);
|
|
|
|
|
|
|
|
NS_IMETHOD GetSources(nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv,
|
|
|
|
nsIRDFAssertionCursor** sources);
|
|
|
|
|
|
|
|
NS_IMETHOD GetTarget(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
PRBool tv,
|
|
|
|
nsIRDFNode** target);
|
|
|
|
|
|
|
|
NS_IMETHOD GetTargets(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
PRBool tv,
|
|
|
|
nsIRDFAssertionCursor** targets);
|
|
|
|
|
|
|
|
NS_IMETHOD Assert(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv);
|
|
|
|
|
|
|
|
NS_IMETHOD Unassert(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target);
|
|
|
|
|
|
|
|
NS_IMETHOD HasAssertion(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv,
|
|
|
|
PRBool* hasAssertion);
|
|
|
|
|
|
|
|
NS_IMETHOD AddObserver(nsIRDFObserver* n);
|
|
|
|
|
|
|
|
NS_IMETHOD RemoveObserver(nsIRDFObserver* n);
|
|
|
|
|
|
|
|
NS_IMETHOD ArcLabelsIn(nsIRDFNode* node,
|
|
|
|
nsIRDFArcsInCursor** labels);
|
|
|
|
|
|
|
|
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
|
|
|
|
nsIRDFArcsOutCursor** labels);
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
NS_IMETHOD GetAllResources(nsIRDFResourceCursor** aCursor);
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
NS_IMETHOD Flush();
|
|
|
|
|
1999-03-12 21:28:34 +00:00
|
|
|
NS_IMETHOD GetAllCommands(nsIRDFResource* source,
|
|
|
|
nsIEnumerator/*<nsIRDFResource>*/** commands);
|
1999-01-12 19:41:06 +00:00
|
|
|
|
1999-03-12 21:28:34 +00:00
|
|
|
NS_IMETHOD IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
|
|
|
nsIRDFResource* aCommand,
|
1999-03-29 19:52:54 +00:00
|
|
|
nsISupportsArray/*<nsIRDFResource>*/* aArguments,
|
|
|
|
PRBool* aResult);
|
1999-03-12 21:28:34 +00:00
|
|
|
|
|
|
|
NS_IMETHOD DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
1999-03-11 10:01:25 +00:00
|
|
|
nsIRDFResource* aCommand,
|
1999-03-12 21:28:34 +00:00
|
|
|
nsISupportsArray/*<nsIRDFResource>*/* aArguments);
|
1999-01-12 19:41:06 +00:00
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
// Implemenatation methods
|
|
|
|
Assertion* GetForwardArcs(nsIRDFResource* u);
|
|
|
|
Assertion* GetReverseArcs(nsIRDFNode* v);
|
|
|
|
void SetForwardArcs(nsIRDFResource* u, Assertion* as);
|
|
|
|
void SetReverseArcs(nsIRDFNode* v, Assertion* as);
|
1999-02-04 10:42:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
// This datasource's monitor object.
|
|
|
|
PRLock* mLock;
|
1998-12-24 05:07:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const PRInt32 InMemoryDataSource::kInitialTableSize = 500;
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// InMemoryAssertionCursor
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
/**
|
|
|
|
* InMemoryAssertionCursor
|
|
|
|
*/
|
1998-12-24 05:07:14 +00:00
|
|
|
class InMemoryAssertionCursor : public nsIRDFAssertionCursor
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
InMemoryDataSource* mDataSource;
|
|
|
|
nsIRDFResource* mSource;
|
|
|
|
nsIRDFResource* mLabel;
|
|
|
|
nsIRDFNode* mTarget;
|
|
|
|
nsIRDFNode* mValue;
|
|
|
|
PRInt32 mCount;
|
|
|
|
PRBool mTruthValue;
|
1999-01-05 03:53:15 +00:00
|
|
|
Direction mDirection;
|
|
|
|
|
|
|
|
// XXX this implementation is a race condition waiting to
|
|
|
|
// happen. Hopefully, no one will blow away this assertion while
|
|
|
|
// we're iterating, but...
|
1998-12-24 05:07:14 +00:00
|
|
|
Assertion* mNextAssertion;
|
|
|
|
|
|
|
|
public:
|
|
|
|
InMemoryAssertionCursor(InMemoryDataSource* ds,
|
1999-01-05 03:53:15 +00:00
|
|
|
nsIRDFNode* u,
|
|
|
|
nsIRDFResource* s,
|
|
|
|
PRBool tv,
|
|
|
|
Direction mDirection);
|
1998-12-24 05:07:14 +00:00
|
|
|
|
|
|
|
virtual ~InMemoryAssertionCursor(void);
|
|
|
|
|
|
|
|
// nsISupports interface
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
// nsIRDFCursor interface
|
|
|
|
NS_IMETHOD Advance(void);
|
1999-01-21 22:24:32 +00:00
|
|
|
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource);
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_IMETHOD GetValue(nsIRDFNode** aValue);
|
1998-12-24 05:07:14 +00:00
|
|
|
|
|
|
|
// nsIRDFAssertionCursor interface
|
1999-03-29 19:52:54 +00:00
|
|
|
NS_IMETHOD GetSource(nsIRDFResource** aResource);
|
|
|
|
NS_IMETHOD GetLabel(nsIRDFResource** aPredicate);
|
|
|
|
NS_IMETHOD GetTarget(nsIRDFNode** aObject);
|
1998-12-24 05:07:14 +00:00
|
|
|
NS_IMETHOD GetTruthValue(PRBool* aTruthValue);
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryAssertionCursor::InMemoryAssertionCursor(InMemoryDataSource* ds,
|
1999-02-04 10:42:21 +00:00
|
|
|
nsIRDFNode* u,
|
|
|
|
nsIRDFResource* label,
|
|
|
|
PRBool tv,
|
|
|
|
Direction direction)
|
1998-12-24 05:07:14 +00:00
|
|
|
: mDataSource(ds),
|
1999-01-05 03:53:15 +00:00
|
|
|
mSource(nsnull),
|
1998-12-24 05:07:14 +00:00
|
|
|
mLabel(label),
|
1999-01-05 03:53:15 +00:00
|
|
|
mTarget(nsnull),
|
1998-12-24 05:07:14 +00:00
|
|
|
mTruthValue(tv),
|
1999-01-05 03:53:15 +00:00
|
|
|
mDirection(direction),
|
1998-12-24 05:07:14 +00:00
|
|
|
mCount(0),
|
|
|
|
mNextAssertion(nsnull),
|
|
|
|
mValue(nsnull)
|
|
|
|
{
|
|
|
|
NS_INIT_REFCNT();
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_ADDREF(mDataSource);
|
|
|
|
NS_ADDREF(mLabel);
|
|
|
|
|
|
|
|
if (mDirection == eDirectionForwards) {
|
|
|
|
// Cast is okay because we're in a closed system.
|
1998-12-27 20:35:46 +00:00
|
|
|
mSource = (nsIRDFResource*) u;
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_ADDREF(mSource);
|
|
|
|
|
|
|
|
mNextAssertion = mDataSource->GetForwardArcs(mSource);
|
|
|
|
} else {
|
|
|
|
mTarget = u;
|
|
|
|
NS_ADDREF(mTarget);
|
|
|
|
|
|
|
|
mNextAssertion = mDataSource->GetReverseArcs(u);
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
InMemoryAssertionCursor::~InMemoryAssertionCursor(void)
|
|
|
|
{
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_IF_RELEASE(mDataSource);
|
|
|
|
NS_IF_RELEASE(mSource);
|
|
|
|
NS_IF_RELEASE(mLabel);
|
|
|
|
NS_IF_RELEASE(mTarget);
|
1998-12-24 05:07:14 +00:00
|
|
|
NS_IF_RELEASE(mValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS(InMemoryAssertionCursor, kIRDFAssertionCursorIID);
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryAssertionCursor::Advance(void)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mDataSource->mLock);
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
NS_IF_RELEASE(mValue);
|
|
|
|
|
|
|
|
while (mNextAssertion) {
|
|
|
|
PRBool eq;
|
|
|
|
if (NS_FAILED(rv = mLabel->EqualsResource(mNextAssertion->mProperty, &eq)))
|
|
|
|
return rv;
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
PRBool foundIt = PR_FALSE;
|
|
|
|
if ((mTruthValue == mNextAssertion->mTruthValue) && eq) {
|
|
|
|
if (mDirection == eDirectionForwards) {
|
|
|
|
mValue = mNextAssertion->mTarget;
|
1998-12-24 05:07:14 +00:00
|
|
|
NS_ADDREF(mValue);
|
|
|
|
} else {
|
1999-01-05 03:53:15 +00:00
|
|
|
mValue = mNextAssertion->mSource;
|
1998-12-24 05:07:14 +00:00
|
|
|
NS_ADDREF(mValue);
|
|
|
|
}
|
1999-01-05 03:53:15 +00:00
|
|
|
foundIt = PR_TRUE;
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
1999-01-05 03:53:15 +00:00
|
|
|
mNextAssertion = (mDirection == eDirectionForwards ?
|
|
|
|
mNextAssertion->mNext :
|
|
|
|
mNextAssertion->mInvNext);
|
|
|
|
|
|
|
|
if (foundIt)
|
|
|
|
return NS_OK;
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If we get here, the cursor is empty.
|
|
|
|
return NS_ERROR_RDF_CURSOR_EMPTY;
|
|
|
|
}
|
|
|
|
|
1998-12-27 20:35:46 +00:00
|
|
|
NS_IMETHODIMP
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryAssertionCursor::GetValue(nsIRDFNode** aValue)
|
|
|
|
{
|
1998-12-27 20:35:46 +00:00
|
|
|
if (! aValue)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mDataSource->mLock);
|
|
|
|
|
1998-12-27 20:35:46 +00:00
|
|
|
NS_ADDREF(mValue);
|
|
|
|
*aValue = mValue;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryAssertionCursor::GetDataSource(nsIRDFDataSource** aDataSource)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aDataSource != nsnull, "null ptr");
|
|
|
|
if (! aDataSource)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_ADDREF(mDataSource);
|
|
|
|
*aDataSource = mDataSource;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-03-29 19:52:54 +00:00
|
|
|
InMemoryAssertionCursor::GetSource(nsIRDFResource** aSubject)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aSubject != nsnull, "null ptr");
|
|
|
|
if (! aSubject)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mDataSource->mLock);
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
if (mDirection == eDirectionForwards) {
|
|
|
|
NS_ADDREF(mSource);
|
|
|
|
*aSubject = mSource;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
else {
|
1998-12-24 05:07:14 +00:00
|
|
|
if (! mValue)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
// this'll AddRef()
|
|
|
|
return mValue->QueryInterface(kIRDFResourceIID, (void**) aSubject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-03-29 19:52:54 +00:00
|
|
|
InMemoryAssertionCursor::GetLabel(nsIRDFResource** aPredicate)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aPredicate != nsnull, "null ptr");
|
|
|
|
if (! aPredicate)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_ADDREF(mLabel);
|
|
|
|
*aPredicate = mLabel;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-03-29 19:52:54 +00:00
|
|
|
InMemoryAssertionCursor::GetTarget(nsIRDFNode** aObject)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aObject != nsnull, "null ptr");
|
|
|
|
if (! aObject)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mDataSource->mLock);
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
if (mDirection == eDirectionForwards) {
|
1998-12-24 05:07:14 +00:00
|
|
|
if (! mValue)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
// this'll AddRef()
|
|
|
|
*aObject = mValue;
|
|
|
|
}
|
1999-01-05 03:53:15 +00:00
|
|
|
else {
|
|
|
|
NS_ADDREF(mTarget);
|
|
|
|
*aObject = mTarget;
|
|
|
|
}
|
1998-12-24 05:07:14 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryAssertionCursor::GetTruthValue(PRBool* aTruthValue)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aTruthValue != nsnull, "null ptr");
|
|
|
|
if (! aTruthValue)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mDataSource->mLock);
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
*aTruthValue = mTruthValue;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This class is a little bit bizarre in that it implements both the
|
|
|
|
* <tt>nsIRDFArcsOutCursor</tt> and <tt>nsIRDFArcsInCursor</tt> interfaces.
|
|
|
|
* Because the structure of the in-memory graph is pretty flexible, it's
|
|
|
|
* fairly easy to parameterize this class. The only funky thing to watch
|
1999-01-05 21:06:54 +00:00
|
|
|
* out for is the mutliple inheiritance clashes.
|
1999-01-05 03:53:15 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
class InMemoryArcsCursor : public nsIRDFArcsOutCursor,
|
|
|
|
public nsIRDFArcsInCursor
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
InMemoryDataSource* mDataSource;
|
|
|
|
nsIRDFResource* mSubject;
|
|
|
|
nsIRDFNode* mObject;
|
|
|
|
nsVoidArray mElements;
|
|
|
|
PRInt32 mNextIndex;
|
|
|
|
nsIRDFResource* mCurrent;
|
|
|
|
Direction mDirection;
|
|
|
|
|
|
|
|
public:
|
|
|
|
InMemoryArcsCursor(InMemoryDataSource* ds,
|
|
|
|
nsIRDFNode* node,
|
|
|
|
Direction direction);
|
|
|
|
|
|
|
|
virtual ~InMemoryArcsCursor(void);
|
|
|
|
|
|
|
|
// nsISupports interface
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
// nsIRDFCursor interface
|
|
|
|
NS_IMETHOD Advance(void);
|
1999-01-21 22:24:32 +00:00
|
|
|
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource);
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_IMETHOD GetValue(nsIRDFNode** aValue);
|
|
|
|
|
|
|
|
// nsIRDFArcsOutCursor interface
|
1999-03-29 19:52:54 +00:00
|
|
|
NS_IMETHOD GetSource(nsIRDFResource** aSubject);
|
|
|
|
NS_IMETHOD GetLabel(nsIRDFResource** aPredicate);
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_IMETHOD GetTruthValue(PRBool* aTruthValue);
|
|
|
|
|
|
|
|
// nsIRDFArcsInCursor interface
|
1999-03-29 19:52:54 +00:00
|
|
|
NS_IMETHOD GetTarget(nsIRDFNode** aObject);
|
1999-01-05 03:53:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
InMemoryArcsCursor::InMemoryArcsCursor(InMemoryDataSource* ds,
|
|
|
|
nsIRDFNode* node,
|
|
|
|
Direction direction)
|
|
|
|
: mDataSource(ds),
|
|
|
|
mSubject(nsnull),
|
|
|
|
mObject(nsnull),
|
|
|
|
mNextIndex(0),
|
|
|
|
mCurrent(nsnull),
|
|
|
|
mDirection(direction)
|
|
|
|
{
|
1999-01-12 19:41:06 +00:00
|
|
|
NS_INIT_REFCNT();
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_ADDREF(mDataSource);
|
|
|
|
|
1999-01-05 21:06:54 +00:00
|
|
|
// Hopefully this won't suck too much because most arcs will have
|
1999-01-05 03:53:15 +00:00
|
|
|
// a small number of properties; or at worst, a small number of
|
1999-01-05 21:06:54 +00:00
|
|
|
// unique properties in the case of multi-attributes. This breaks
|
1999-01-05 03:53:15 +00:00
|
|
|
// for RDF container elements, which we should eventually special
|
|
|
|
// case.
|
|
|
|
|
|
|
|
Assertion* as;
|
|
|
|
if (mDirection == eDirectionForwards) {
|
|
|
|
// cast okay because it's a closed system
|
|
|
|
mSubject = (nsIRDFResource*) node;
|
|
|
|
NS_ADDREF(mSubject);
|
|
|
|
as = ds->GetForwardArcs(mSubject);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mObject = node;
|
|
|
|
NS_ADDREF(mObject);
|
|
|
|
as = ds->GetReverseArcs(mObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (as != nsnull) {
|
|
|
|
PRBool alreadyHadIt = PR_FALSE;
|
|
|
|
|
|
|
|
for (PRInt32 i = mElements.Count() - 1; i >= 0; --i) {
|
|
|
|
if (mElements[i] == as->mProperty) {
|
1999-01-26 01:22:40 +00:00
|
|
|
alreadyHadIt = PR_TRUE;
|
1999-01-05 03:53:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! alreadyHadIt) {
|
|
|
|
mElements.AppendElement(as->mProperty);
|
|
|
|
NS_ADDREF(as->mProperty);
|
|
|
|
}
|
|
|
|
|
|
|
|
as = ((mDirection == eDirectionForwards) ? as->mNext : as->mInvNext);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
InMemoryArcsCursor::~InMemoryArcsCursor(void)
|
|
|
|
{
|
|
|
|
NS_RELEASE(mDataSource);
|
|
|
|
NS_IF_RELEASE(mSubject);
|
|
|
|
NS_IF_RELEASE(mObject);
|
|
|
|
NS_IF_RELEASE(mCurrent);
|
|
|
|
|
|
|
|
for (PRInt32 i = mElements.Count() - 1; i >= mNextIndex; --i) {
|
|
|
|
nsIRDFResource* resource = (nsIRDFResource*) mElements[i];
|
|
|
|
NS_RELEASE(resource);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(InMemoryArcsCursor);
|
|
|
|
NS_IMPL_RELEASE(InMemoryArcsCursor);
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryArcsCursor::QueryInterface(REFNSIID iid, void** result)
|
|
|
|
{
|
|
|
|
if (! result)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
if (iid.Equals(kISupportsIID) ||
|
|
|
|
iid.Equals(kIRDFCursorIID) ||
|
|
|
|
iid.Equals(kIRDFArcsOutCursorIID)) {
|
|
|
|
*result = NS_STATIC_CAST(nsIRDFArcsOutCursor*, this);
|
|
|
|
AddRef();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
else if (iid.Equals(kIRDFArcsInCursorIID)) {
|
|
|
|
*result = NS_STATIC_CAST(nsIRDFArcsInCursor*, this);
|
|
|
|
AddRef();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*result = nsnull;
|
|
|
|
return NS_NOINTERFACE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryArcsCursor::Advance(void)
|
|
|
|
{
|
|
|
|
NS_IF_RELEASE(mCurrent);
|
|
|
|
|
|
|
|
if (mNextIndex >= mElements.Count())
|
|
|
|
return NS_ERROR_RDF_CURSOR_EMPTY;
|
|
|
|
|
|
|
|
// Cast is ok because this is a closed system. This code
|
|
|
|
// effectively "transfers" the reference from the array to
|
|
|
|
// mCurrent, keeping the refcount properly in sync. We just need
|
|
|
|
// to remember that any of the indicies before mNextIndex are
|
|
|
|
// dangling pointers.
|
|
|
|
mCurrent = (nsIRDFResource*) mElements[mNextIndex];
|
|
|
|
++mNextIndex;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryArcsCursor::GetValue(nsIRDFNode** aValue)
|
|
|
|
{
|
|
|
|
if (! aValue)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_ADDREF(mCurrent);
|
|
|
|
*aValue = mCurrent;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryArcsCursor::GetDataSource(nsIRDFDataSource** aDataSource)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aDataSource != nsnull, "null ptr");
|
|
|
|
if (! aDataSource)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_ADDREF(mDataSource);
|
|
|
|
*aDataSource = mDataSource;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-03-29 19:52:54 +00:00
|
|
|
InMemoryArcsCursor::GetSource(nsIRDFResource** aSubject)
|
1999-01-05 03:53:15 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aSubject != nsnull, "null ptr");
|
|
|
|
if (! aSubject)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_ADDREF(mSubject);
|
|
|
|
*aSubject = mSubject;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-03-29 19:52:54 +00:00
|
|
|
InMemoryArcsCursor::GetTarget(nsIRDFNode** aObject)
|
1999-01-05 03:53:15 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aObject != nsnull, "null ptr");
|
|
|
|
if (! aObject)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_ADDREF(mObject);
|
|
|
|
*aObject = mObject;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-03-29 19:52:54 +00:00
|
|
|
InMemoryArcsCursor::GetLabel(nsIRDFResource** aPredicate)
|
1999-01-05 03:53:15 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aPredicate != nsnull, "null ptr");
|
|
|
|
if (! aPredicate)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_PRECONDITION(mCurrent != nsnull, "cursor overrun");
|
|
|
|
if (! mCurrent)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
NS_ADDREF(mCurrent);
|
|
|
|
*aPredicate = mCurrent;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryArcsCursor::GetTruthValue(PRBool* aTruthValue)
|
|
|
|
{
|
|
|
|
*aTruthValue = PR_TRUE; // XXX need to worry about this some day...
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-12-24 05:07:14 +00:00
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// InMemoryResourceCursor
|
|
|
|
|
|
|
|
class InMemoryResourceCursor : public nsIRDFResourceCursor
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
nsIRDFDataSource* mDataSource;
|
|
|
|
nsVoidArray mResources;
|
|
|
|
PRInt32 mNext;
|
|
|
|
|
|
|
|
public:
|
|
|
|
InMemoryResourceCursor(InMemoryDataSource* ds);
|
|
|
|
virtual ~InMemoryResourceCursor(void);
|
|
|
|
|
|
|
|
// nsISupports interface
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
// nsIRDFCursor interface
|
|
|
|
NS_IMETHOD Advance(void);
|
|
|
|
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource);
|
|
|
|
NS_IMETHOD GetValue(nsIRDFNode** aValue);
|
|
|
|
|
|
|
|
// nsIRDFResourceCursor interface
|
|
|
|
NS_IMETHOD GetResource(nsIRDFResource** aResource);
|
|
|
|
};
|
|
|
|
|
|
|
|
static PRIntn
|
|
|
|
rdf_ResourceEnumerator(PLHashEntry* he, PRIntn index, void* closure)
|
|
|
|
{
|
|
|
|
nsVoidArray* resources = NS_STATIC_CAST(nsVoidArray*, closure);
|
|
|
|
|
|
|
|
nsIRDFResource* resource =
|
|
|
|
NS_CONST_CAST(nsIRDFResource*, NS_STATIC_CAST(const nsIRDFResource*, he->key));
|
|
|
|
|
|
|
|
NS_ADDREF(resource);
|
|
|
|
resources->AppendElement(resource);
|
|
|
|
return HT_ENUMERATE_NEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
InMemoryResourceCursor::InMemoryResourceCursor(InMemoryDataSource* ds)
|
|
|
|
: mDataSource(ds),
|
|
|
|
mNext(-1)
|
|
|
|
{
|
1999-03-19 01:09:48 +00:00
|
|
|
NS_INIT_REFCNT();
|
1999-01-21 22:24:32 +00:00
|
|
|
mDataSource = ds;
|
|
|
|
NS_ADDREF(ds);
|
|
|
|
|
|
|
|
// XXX Ick. To fix this, we need to write our own hash table
|
|
|
|
// implementation. Takers?
|
|
|
|
PL_HashTableEnumerateEntries(ds->mForwardArcs, rdf_ResourceEnumerator, &mResources);
|
|
|
|
}
|
|
|
|
|
|
|
|
InMemoryResourceCursor::~InMemoryResourceCursor(void)
|
|
|
|
{
|
|
|
|
for (PRInt32 i = mResources.Count() - 1; i >= mNext; --i) {
|
|
|
|
nsIRDFResource* resource = NS_STATIC_CAST(nsIRDFResource*, mResources[i]);
|
|
|
|
NS_RELEASE(resource);
|
|
|
|
}
|
|
|
|
NS_RELEASE(mDataSource);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS(InMemoryResourceCursor, kIRDFResourceCursorIID);
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryResourceCursor::Advance(void)
|
|
|
|
{
|
|
|
|
if (mNext >= mResources.Count())
|
|
|
|
return NS_ERROR_RDF_CURSOR_EMPTY;
|
|
|
|
|
|
|
|
if (mNext >= 0) {
|
|
|
|
nsIRDFResource* resource = NS_STATIC_CAST(nsIRDFResource*, mResources[mNext]);
|
|
|
|
NS_RELEASE(resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
++mNext;
|
|
|
|
|
|
|
|
if (mNext >= mResources.Count())
|
|
|
|
return NS_ERROR_RDF_CURSOR_EMPTY;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryResourceCursor::GetDataSource(nsIRDFDataSource** aDataSource)
|
|
|
|
{
|
|
|
|
NS_ADDREF(mDataSource);
|
|
|
|
*aDataSource = mDataSource;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryResourceCursor::GetValue(nsIRDFNode** aValue)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
nsIRDFResource* result;
|
|
|
|
if (NS_FAILED(rv = GetResource(&result)))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
*aValue = result; // already addref-ed
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryResourceCursor::GetResource(nsIRDFResource** aResource)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(mNext >= 0, "didn't advance");
|
|
|
|
if (mNext < 0)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
NS_ASSERTION(mNext < mResources.Count(), "past end of cursor");
|
|
|
|
if (mNext > mResources.Count())
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
nsIRDFResource* result = NS_STATIC_CAST(nsIRDFResource*, mResources[mNext]);
|
|
|
|
*aResource = result;
|
|
|
|
NS_ADDREF(result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
1999-01-05 03:53:15 +00:00
|
|
|
// InMemoryDataSource
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(InMemoryDataSource);
|
|
|
|
NS_IMPL_RELEASE(InMemoryDataSource);
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::QueryInterface(REFNSIID iid, void** result)
|
|
|
|
{
|
|
|
|
if (! result)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
1998-12-24 05:07:14 +00:00
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
if (iid.Equals(kISupportsIID) ||
|
|
|
|
iid.Equals(kIRDFDataSourceIID)) {
|
|
|
|
*result = NS_STATIC_CAST(nsIRDFDataSource*, this);
|
|
|
|
NS_ADDREF(this);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*result = nsnull;
|
|
|
|
return NS_NOINTERFACE;
|
|
|
|
}
|
|
|
|
}
|
1998-12-24 05:07:14 +00:00
|
|
|
|
|
|
|
InMemoryDataSource::InMemoryDataSource(void)
|
|
|
|
: mURL(nsnull),
|
|
|
|
mForwardArcs(nsnull),
|
|
|
|
mReverseArcs(nsnull),
|
1999-02-04 10:42:21 +00:00
|
|
|
mObservers(nsnull),
|
|
|
|
mLock(nsnull)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
|
|
|
mForwardArcs = PL_NewHashTable(kInitialTableSize,
|
1999-03-08 08:27:53 +00:00
|
|
|
rdf_HashPointer,
|
|
|
|
PL_CompareValues,
|
|
|
|
PL_CompareValues,
|
|
|
|
nsnull,
|
|
|
|
nsnull);
|
1998-12-24 05:07:14 +00:00
|
|
|
|
|
|
|
mReverseArcs = PL_NewHashTable(kInitialTableSize,
|
1999-03-08 08:27:53 +00:00
|
|
|
rdf_HashPointer,
|
|
|
|
rdf_CompareNodes,
|
|
|
|
PL_CompareValues,
|
|
|
|
nsnull,
|
|
|
|
nsnull);
|
1999-02-04 10:42:21 +00:00
|
|
|
|
|
|
|
mLock = PR_NewLock();
|
|
|
|
|
1999-02-02 08:06:38 +00:00
|
|
|
NS_INIT_REFCNT();
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
InMemoryDataSource::~InMemoryDataSource(void)
|
|
|
|
{
|
|
|
|
if (mForwardArcs) {
|
1999-02-02 08:06:38 +00:00
|
|
|
// This'll release all of the Assertion objects that are
|
|
|
|
// associated with this data source. We only need to do this
|
|
|
|
// for the forward arcs, because the reverse arcs table
|
|
|
|
// indexes the exact same set of resources.
|
|
|
|
PL_HashTableEnumerateEntries(mForwardArcs, DeleteForwardArcsEntry, nsnull);
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
PL_HashTableDestroy(mForwardArcs);
|
|
|
|
mForwardArcs = nsnull;
|
|
|
|
}
|
|
|
|
if (mReverseArcs) {
|
|
|
|
PL_HashTableDestroy(mReverseArcs);
|
|
|
|
mReverseArcs = nsnull;
|
|
|
|
}
|
|
|
|
if (mObservers) {
|
1999-02-02 07:05:52 +00:00
|
|
|
for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) {
|
1998-12-24 05:07:14 +00:00
|
|
|
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
|
|
|
NS_RELEASE(obs);
|
|
|
|
}
|
|
|
|
delete mObservers;
|
|
|
|
}
|
1999-02-04 10:42:21 +00:00
|
|
|
|
1999-03-29 19:52:54 +00:00
|
|
|
if (mURL) PL_strfree(mURL);
|
1999-02-04 10:42:21 +00:00
|
|
|
PR_DestroyLock(mLock);
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
1999-02-02 08:06:38 +00:00
|
|
|
PRIntn
|
|
|
|
InMemoryDataSource::DeleteForwardArcsEntry(PLHashEntry* he, PRIntn index, void* arg)
|
|
|
|
{
|
|
|
|
Assertion* as = (Assertion*) he->value;
|
|
|
|
while (as) {
|
|
|
|
Assertion* doomed = as;
|
|
|
|
as = as->mNext;
|
|
|
|
|
|
|
|
NS_RELEASE(doomed->mSource);
|
|
|
|
NS_RELEASE(doomed->mProperty);
|
|
|
|
NS_RELEASE(doomed->mTarget);
|
|
|
|
delete doomed;
|
|
|
|
}
|
|
|
|
return HT_ENUMERATE_NEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
Assertion*
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryDataSource::GetForwardArcs(nsIRDFResource* u)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
|
|
|
// Cast is okay, we're in a closed system
|
|
|
|
return (Assertion*) PL_HashTableLookup(mForwardArcs, u);
|
|
|
|
}
|
|
|
|
|
|
|
|
Assertion*
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryDataSource::GetReverseArcs(nsIRDFNode* v)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
|
|
|
// Cast is okay, we're in a closed system
|
|
|
|
return (Assertion*) PL_HashTableLookup(mReverseArcs, v);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryDataSource::SetForwardArcs(nsIRDFResource* u, Assertion* as)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
1999-03-08 08:27:53 +00:00
|
|
|
NS_PRECONDITION(u != nsnull, "null ptr");
|
|
|
|
if (as) {
|
|
|
|
PL_HashTableAdd(mForwardArcs, u, as);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
PL_HashTableRemove(mForwardArcs, u);
|
|
|
|
}
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryDataSource::SetReverseArcs(nsIRDFNode* v, Assertion* as)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
1999-03-08 08:27:53 +00:00
|
|
|
NS_PRECONDITION(v != nsnull, "null ptr");
|
|
|
|
if (as) {
|
|
|
|
PL_HashTableAdd(mReverseArcs, v, as);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
PL_HashTableRemove(mReverseArcs, v);
|
|
|
|
}
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::Init(const char* uri)
|
|
|
|
{
|
|
|
|
if ((mURL = PL_strdup(uri)) == nsnull)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-03-29 19:52:54 +00:00
|
|
|
InMemoryDataSource::GetURI(char* *uri)
|
1999-01-05 03:53:15 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(uri != nsnull, "null ptr");
|
|
|
|
if (! uri)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-03-29 19:52:54 +00:00
|
|
|
if ((*uri = nsXPIDLCString::Copy(mURL)) == nsnull)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
else
|
|
|
|
return NS_OK;
|
1999-01-05 03:53:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::GetSource(nsIRDFResource* property,
|
1999-02-02 08:06:38 +00:00
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv,
|
|
|
|
nsIRDFResource** source)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_PRECONDITION(source != nsnull, "null ptr");
|
|
|
|
if (! source)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_PRECONDITION(property != nsnull, "null ptr");
|
|
|
|
if (! property)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_PRECONDITION(target != nsnull, "null ptr");
|
|
|
|
if (! target)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_AUTOLOCK(mLock);
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
nsresult rv;
|
1999-01-05 03:53:15 +00:00
|
|
|
for (Assertion* as = GetReverseArcs(target); as != nsnull; as = as->mNext) {
|
1998-12-24 05:07:14 +00:00
|
|
|
PRBool eq;
|
|
|
|
if (NS_FAILED(rv = property->EqualsResource(as->mProperty, &eq)))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (! eq)
|
|
|
|
continue;
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
if (as->mTruthValue != tv)
|
1998-12-24 05:07:14 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
*source = as->mSource;
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_ADDREF(as->mSource);
|
1998-12-24 05:07:14 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
*source = nsnull;
|
1999-01-05 03:53:15 +00:00
|
|
|
return NS_ERROR_RDF_NO_VALUE;
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryDataSource::GetTarget(nsIRDFResource* source,
|
1999-02-02 08:06:38 +00:00
|
|
|
nsIRDFResource* property,
|
|
|
|
PRBool tv,
|
|
|
|
nsIRDFNode** target)
|
1999-01-05 03:53:15 +00:00
|
|
|
{
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_PRECONDITION(source != nsnull, "null ptr");
|
|
|
|
if (! source)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_PRECONDITION(property != nsnull, "null ptr");
|
|
|
|
if (! property)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_PRECONDITION(target != nsnull, "null ptr");
|
|
|
|
if (! target)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_AUTOLOCK(mLock);
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
nsresult rv;
|
1999-01-05 03:53:15 +00:00
|
|
|
for (Assertion* as = GetForwardArcs(source); as != nsnull; as = as->mNext) {
|
1998-12-24 05:07:14 +00:00
|
|
|
PRBool eq;
|
|
|
|
if (NS_FAILED(rv = property->EqualsResource(as->mProperty, &eq)))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (! eq)
|
|
|
|
continue;
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
if (as->mTruthValue != tv)
|
1998-12-24 05:07:14 +00:00
|
|
|
continue;
|
|
|
|
|
1998-12-27 20:35:46 +00:00
|
|
|
*target = as->mTarget;
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_ADDREF(as->mTarget);
|
1998-12-24 05:07:14 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we get here, then there was no target with for the specified
|
|
|
|
// property & truth value.
|
|
|
|
*target = nsnull;
|
1999-01-05 03:53:15 +00:00
|
|
|
return NS_ERROR_RDF_NO_VALUE;
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryDataSource::HasAssertion(nsIRDFResource* source,
|
1999-02-02 08:06:38 +00:00
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv,
|
|
|
|
PRBool* hasAssertion)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_PRECONDITION(source != nsnull, "null ptr");
|
|
|
|
if (! source)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_PRECONDITION(property != nsnull, "null ptr");
|
|
|
|
if (! property)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_PRECONDITION(target != nsnull, "null ptr");
|
|
|
|
if (! target)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
NS_AUTOLOCK(mLock);
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
nsresult rv;
|
1999-01-05 03:53:15 +00:00
|
|
|
for (Assertion* as = GetForwardArcs(source); as != nsnull; as = as->mNext) {
|
1998-12-24 05:07:14 +00:00
|
|
|
PRBool eq;
|
|
|
|
if (NS_FAILED(rv = property->EqualsResource(as->mProperty, &eq)))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (! eq)
|
|
|
|
continue;
|
|
|
|
|
1998-12-27 20:35:46 +00:00
|
|
|
if (NS_FAILED(rv = target->EqualsNode(as->mTarget, &eq)))
|
1998-12-24 05:07:14 +00:00
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (! eq)
|
|
|
|
continue;
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
if (as->mTruthValue != tv)
|
1998-12-24 05:07:14 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// found it!
|
|
|
|
*hasAssertion = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we get here, we couldn't find the assertion
|
|
|
|
*hasAssertion = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryDataSource::GetSources(nsIRDFResource* property,
|
1999-02-02 08:06:38 +00:00
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv,
|
|
|
|
nsIRDFAssertionCursor** sources)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_PRECONDITION(sources != nsnull, "null ptr");
|
|
|
|
if (! sources)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mLock);
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryAssertionCursor* result
|
|
|
|
= new InMemoryAssertionCursor(this, target, property, tv, eDirectionReverse);
|
|
|
|
|
|
|
|
if (! result)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
*sources = result;
|
|
|
|
NS_ADDREF(result);
|
1998-12-24 05:07:14 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::GetTargets(nsIRDFResource* source,
|
1999-02-02 08:06:38 +00:00
|
|
|
nsIRDFResource* property,
|
|
|
|
PRBool tv,
|
|
|
|
nsIRDFAssertionCursor** targets)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_PRECONDITION(targets != nsnull, "null ptr");
|
|
|
|
if (! targets)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mLock);
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryAssertionCursor* result
|
|
|
|
= new InMemoryAssertionCursor(this, source, property, tv, eDirectionForwards);
|
|
|
|
|
|
|
|
if (! result)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
*targets = result;
|
|
|
|
NS_ADDREF(result);
|
1998-12-24 05:07:14 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
InMemoryDataSource::SafeAssert(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mLock);
|
1998-12-24 05:07:14 +00:00
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
nsresult rv;
|
1999-01-05 03:53:15 +00:00
|
|
|
Assertion* next = GetForwardArcs(source);
|
1998-12-24 05:07:14 +00:00
|
|
|
Assertion* prev = next;
|
|
|
|
Assertion* as = nsnull;
|
|
|
|
|
|
|
|
// Walk to the end of the linked list.
|
|
|
|
// XXX shouldn't we just keep a pointer to the end, or insert at the front???
|
|
|
|
while (next) {
|
|
|
|
PRBool eq;
|
|
|
|
|
|
|
|
if (NS_FAILED(rv = property->EqualsResource(next->mProperty, &eq)))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (eq) {
|
1998-12-27 20:35:46 +00:00
|
|
|
if (NS_FAILED(rv = target->EqualsNode(next->mTarget, &eq)))
|
1998-12-24 05:07:14 +00:00
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (eq) {
|
|
|
|
// Wow, we already had the assertion. Make sure that the
|
|
|
|
// truth values are correct and bail.
|
1999-01-05 03:53:15 +00:00
|
|
|
next->mTruthValue = tv;
|
1998-12-24 05:07:14 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
prev = next;
|
1999-01-05 03:53:15 +00:00
|
|
|
next = next->mNext;
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
as = new Assertion;
|
|
|
|
if (! as)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
NS_ADDREF(source);
|
1999-01-05 03:53:15 +00:00
|
|
|
as->mSource = source;
|
1998-12-24 05:07:14 +00:00
|
|
|
|
|
|
|
NS_ADDREF(property);
|
1999-01-05 03:53:15 +00:00
|
|
|
as->mProperty = property;
|
1998-12-24 05:07:14 +00:00
|
|
|
|
|
|
|
NS_ADDREF(target);
|
1999-01-05 03:53:15 +00:00
|
|
|
as->mTarget = target;
|
1998-12-24 05:07:14 +00:00
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
as->mTruthValue = tv;
|
|
|
|
as->mNext = nsnull;
|
|
|
|
as->mInvNext = nsnull;
|
1998-12-24 05:07:14 +00:00
|
|
|
|
|
|
|
// Link it in to the "forward arcs" table
|
|
|
|
if (!prev) {
|
1999-01-05 03:53:15 +00:00
|
|
|
SetForwardArcs(source, as);
|
1998-12-24 05:07:14 +00:00
|
|
|
} else {
|
|
|
|
prev->mNext = as;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Link it in to the "reverse arcs" table
|
|
|
|
|
|
|
|
// XXX Shouldn't we keep a pointer to the end of the list to make
|
|
|
|
// sure this is O(1)?
|
1999-03-08 08:27:53 +00:00
|
|
|
prev = nsnull;
|
|
|
|
next = GetReverseArcs(target);
|
|
|
|
while (next) {
|
|
|
|
prev = next;
|
|
|
|
next = next->mInvNext;
|
|
|
|
}
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
if (!prev) {
|
1999-01-05 03:53:15 +00:00
|
|
|
SetReverseArcs(target, as);
|
1998-12-24 05:07:14 +00:00
|
|
|
} else {
|
|
|
|
prev->mInvNext = as;
|
|
|
|
}
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::Assert(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target,
|
|
|
|
PRBool tv)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (NS_FAILED(rv = SafeAssert(source, property, target, tv)))
|
|
|
|
return rv;
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
// notify observers
|
|
|
|
if (mObservers) {
|
1999-01-12 19:41:06 +00:00
|
|
|
for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) {
|
1998-12-24 05:07:14 +00:00
|
|
|
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
|
|
|
obs->OnAssert(source, property, target);
|
|
|
|
// XXX ignore return value?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
InMemoryDataSource::SafeUnassert(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mLock);
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
nsresult rv;
|
1999-01-05 03:53:15 +00:00
|
|
|
Assertion* next = GetForwardArcs(source);
|
1998-12-24 05:07:14 +00:00
|
|
|
Assertion* prev = next;
|
|
|
|
Assertion* as = nsnull;
|
|
|
|
|
|
|
|
while (next) {
|
|
|
|
PRBool eq;
|
|
|
|
|
|
|
|
if (NS_FAILED(rv = property->EqualsResource(next->mProperty, &eq)))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (eq) {
|
1998-12-27 20:35:46 +00:00
|
|
|
if (NS_FAILED(rv = target->EqualsNode(next->mTarget, &eq)))
|
1998-12-24 05:07:14 +00:00
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (eq) {
|
|
|
|
if (prev == next) {
|
1999-01-05 03:53:15 +00:00
|
|
|
SetForwardArcs(source, next->mNext);
|
1998-12-24 05:07:14 +00:00
|
|
|
} else {
|
|
|
|
prev->mNext = next->mNext;
|
|
|
|
}
|
|
|
|
as = next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
prev = next;
|
1999-01-05 03:53:15 +00:00
|
|
|
next = next->mNext;
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// We don't even have the assertion, so just bail.
|
|
|
|
if (!as)
|
|
|
|
return NS_OK;
|
|
|
|
|
1999-03-08 08:27:53 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
PRBool foundReverseArc = PR_FALSE;
|
|
|
|
#endif
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
next = prev = GetReverseArcs(target);
|
1998-12-24 05:07:14 +00:00
|
|
|
while (next) {
|
|
|
|
if (next == as) {
|
|
|
|
if (prev == next) {
|
1999-01-05 03:53:15 +00:00
|
|
|
SetReverseArcs(target, next->mInvNext);
|
1998-12-24 05:07:14 +00:00
|
|
|
} else {
|
|
|
|
prev->mInvNext = next->mInvNext;
|
|
|
|
}
|
1999-03-08 08:27:53 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
foundReverseArc = PR_TRUE;
|
|
|
|
#endif
|
1998-12-24 05:07:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
prev = next;
|
1999-01-05 03:53:15 +00:00
|
|
|
next = next->mInvNext;
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
1999-03-08 08:27:53 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
NS_ASSERTION(foundReverseArc, "in-memory db corrupted: unable to find reverse arc");
|
|
|
|
#endif
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
// Delete the assertion struct & release resources
|
|
|
|
NS_RELEASE(as->mSource);
|
|
|
|
NS_RELEASE(as->mProperty);
|
|
|
|
NS_RELEASE(as->mTarget);
|
|
|
|
delete as;
|
1998-12-24 05:07:14 +00:00
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::Unassert(nsIRDFResource* source,
|
|
|
|
nsIRDFResource* property,
|
|
|
|
nsIRDFNode* target)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (NS_FAILED(rv = SafeUnassert(source, property, target)))
|
|
|
|
return rv;
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
// Notify the world
|
1998-12-24 05:07:14 +00:00
|
|
|
if (mObservers) {
|
1999-01-12 19:41:06 +00:00
|
|
|
for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) {
|
1998-12-24 05:07:14 +00:00
|
|
|
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
|
|
|
obs->OnUnassert(source, property, target);
|
|
|
|
// XXX ignore return value?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::AddObserver(nsIRDFObserver* observer)
|
|
|
|
{
|
1999-01-12 19:41:06 +00:00
|
|
|
NS_ASSERTION(observer != nsnull, "null ptr");
|
|
|
|
if (! observer)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mLock);
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
if (! mObservers) {
|
|
|
|
if ((mObservers = new nsVoidArray()) == nsnull)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
mObservers->AppendElement(observer);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::RemoveObserver(nsIRDFObserver* observer)
|
|
|
|
{
|
1999-01-12 19:41:06 +00:00
|
|
|
NS_ASSERTION(observer != nsnull, "null ptr");
|
|
|
|
if (! observer)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mLock);
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
if (! mObservers)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
mObservers->RemoveElement(observer);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::ArcLabelsIn(nsIRDFNode* node, nsIRDFArcsInCursor** labels)
|
|
|
|
{
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_PRECONDITION(labels != nsnull, "null ptr");
|
|
|
|
if (! labels)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
InMemoryArcsCursor* result =
|
|
|
|
new InMemoryArcsCursor(this, node, eDirectionReverse);
|
|
|
|
|
|
|
|
if (! result)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
*labels = result;
|
|
|
|
NS_ADDREF(result);
|
|
|
|
return NS_OK;
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryDataSource::ArcLabelsOut(nsIRDFResource* source, nsIRDFArcsOutCursor** labels)
|
1998-12-24 05:07:14 +00:00
|
|
|
{
|
1999-01-05 03:53:15 +00:00
|
|
|
NS_PRECONDITION(labels != nsnull, "null ptr");
|
|
|
|
if (! labels)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mLock);
|
|
|
|
|
1999-01-05 03:53:15 +00:00
|
|
|
InMemoryArcsCursor* result =
|
|
|
|
new InMemoryArcsCursor(this, source, eDirectionForwards);
|
|
|
|
|
|
|
|
if (! result)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
*labels = result;
|
|
|
|
NS_ADDREF(result);
|
|
|
|
return NS_OK;
|
1998-12-24 05:07:14 +00:00
|
|
|
}
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::GetAllResources(nsIRDFResourceCursor** aCursor)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aCursor != nsnull, "null ptr");
|
|
|
|
if (! aCursor)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-02-04 10:42:21 +00:00
|
|
|
NS_AUTOLOCK(mLock);
|
|
|
|
|
1999-01-21 22:24:32 +00:00
|
|
|
InMemoryResourceCursor* result =
|
|
|
|
new InMemoryResourceCursor(this);
|
|
|
|
|
|
|
|
if (! result)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
*aCursor = result;
|
|
|
|
NS_ADDREF(result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::Flush()
|
|
|
|
{
|
|
|
|
// XXX nothing to flush, right?
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-01-12 19:41:06 +00:00
|
|
|
NS_IMETHODIMP
|
1999-03-12 21:28:34 +00:00
|
|
|
InMemoryDataSource::GetAllCommands(nsIRDFResource* source,
|
|
|
|
nsIEnumerator/*<nsIRDFResource>*/** commands)
|
|
|
|
{
|
|
|
|
NS_NOTYETIMPLEMENTED("write me!");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InMemoryDataSource::IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
|
|
|
nsIRDFResource* aCommand,
|
1999-03-29 19:52:54 +00:00
|
|
|
nsISupportsArray/*<nsIRDFResource>*/* aArguments,
|
|
|
|
PRBool* aResult)
|
1999-01-12 19:41:06 +00:00
|
|
|
{
|
1999-03-11 10:01:25 +00:00
|
|
|
NS_NOTYETIMPLEMENTED("write me!");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
1999-01-12 19:41:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-03-12 21:28:34 +00:00
|
|
|
InMemoryDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
1999-03-11 10:01:25 +00:00
|
|
|
nsIRDFResource* aCommand,
|
1999-03-12 21:28:34 +00:00
|
|
|
nsISupportsArray/*<nsIRDFResource>*/* aArguments)
|
1999-01-12 19:41:06 +00:00
|
|
|
{
|
1999-03-11 10:01:25 +00:00
|
|
|
NS_NOTYETIMPLEMENTED("write me!");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
1999-01-12 19:41:06 +00:00
|
|
|
}
|
1999-01-05 08:44:40 +00:00
|
|
|
|
1998-12-24 05:07:14 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
1999-03-02 15:30:28 +00:00
|
|
|
nsresult NS_NewRDFInMemoryDataSource(nsIRDFDataSource** result);
|
1998-12-24 05:07:14 +00:00
|
|
|
nsresult
|
|
|
|
NS_NewRDFInMemoryDataSource(nsIRDFDataSource** result)
|
|
|
|
{
|
|
|
|
InMemoryDataSource* ds = new InMemoryDataSource();
|
|
|
|
if (! ds)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
*result = ds;
|
|
|
|
NS_ADDREF(*result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|