Add experimental support for RDF delegates.

This commit is contained in:
waterson%netscape.com 1999-11-24 20:51:39 +00:00
Родитель 25ec09fbb0
Коммит 7615b7ebff
4 изменённых файлов: 138 добавлений и 2 удалений

Просмотреть файл

@ -33,7 +33,7 @@ interface nsIRDFResource;
/** /**
* This interface should be implemented by an XPCOM factory that * This interface should be implemented by an XPCOM factory that
* is registered to handle "component:/rdf/delegate/[key]/[scheme]" * is registered to handle "component:/rdf/delegate-factory/[key]/[scheme]"
* ProgIDs. * ProgIDs.
* *
* The factory will be invoked to create delegate objects from * The factory will be invoked to create delegate objects from

Просмотреть файл

@ -20,6 +20,7 @@
* Contributor(s): * Contributor(s):
*/ */
#include "nsrootidl.idl"
#include "nsIRDFNode.idl" #include "nsIRDFNode.idl"
@ -51,5 +52,39 @@ interface nsIRDFResource : nsIRDFNode {
* Determine if the resource has the given URI. * Determine if the resource has the given URI.
*/ */
boolean EqualsString(in string aURI); boolean EqualsString(in string aURI);
/**
* Retrieve the "delegate" object for this resource. A resource
* may have several delegate objects, each of whose lifetimes is
* bound to the life of the resource object.
*
* This method will return the delegate for the given key after
* QueryInterface()-ing it to the requested IID.
*
* If no delegate exists for the specified key, this method will
* attempt to create one using the component manager. Specifically,
* it will combine aKey with the resource's URI scheme to produce
* a ProgID as follows:
*
* component:/rdf/delegate-factory/[key]/[scheme]
*
* This ProgID will be used to locate a factory using the
* FindFactory() method of nsIComponentManager. If the nsIFactory
* exists, it will be used to create a "delegate factory"; that
* is, an object that supports nsIRDFDelegateFactory. The delegate
* factory will be used to construct the delegate object.
*/
void GetDelegate(in string aKey, in nsIIDRef aIID,
[iid_is(aIID),retval] out nsQIResult aResult);
/**
* Force a delegate to be "unbound" from the resource.
*
* Normally, a delegate object's lifetime will be identical to
* that of the resource to which it is bound; this method allows a
* delegate to unlink itself from an RDF resource prematurely.
*/
void ReleaseDelegate(in string aKey);
}; };

Просмотреть файл

@ -23,9 +23,11 @@
#ifndef nsRDFResource_h__ #ifndef nsRDFResource_h__
#define nsRDFResource_h__ #define nsRDFResource_h__
#include "nsCOMPtr.h"
#include "nsIRDFNode.h" #include "nsIRDFNode.h"
#include "nsIRDFResource.h" #include "nsIRDFResource.h"
#include "nscore.h" #include "nscore.h"
#include "nsString.h"
#include "rdf.h" #include "rdf.h"
class nsIRDFService; class nsIRDFService;
@ -46,6 +48,8 @@ public:
NS_IMETHOD GetValue(char* *aURI); NS_IMETHOD GetValue(char* *aURI);
NS_IMETHOD GetValueConst(const char** aURI); NS_IMETHOD GetValueConst(const char** aURI);
NS_IMETHOD EqualsString(const char* aURI, PRBool* aResult); NS_IMETHOD EqualsString(const char* aURI, PRBool* aResult);
NS_IMETHOD GetDelegate(const char* aKey, REFNSIID aIID, void** aResult);
NS_IMETHOD ReleaseDelegate(const char* aKey);
// nsRDFResource methods: // nsRDFResource methods:
nsRDFResource(void); nsRDFResource(void);
@ -57,6 +61,14 @@ protected:
protected: protected:
char* mURI; char* mURI;
struct DelegateEntry {
nsCString mKey;
nsCOMPtr<nsISupports> mDelegate;
DelegateEntry* mNext;
};
DelegateEntry* mDelegates;
}; };
#endif // nsRDFResource_h__ #endif // nsRDFResource_h__

Просмотреть файл

@ -23,6 +23,7 @@
#include "nsRDFResource.h" #include "nsRDFResource.h"
#include "nsCRT.h" #include "nsCRT.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsIRDFDelegateFactory.h"
#include "nsIRDFService.h" #include "nsIRDFService.h"
#include "nsRDFCID.h" #include "nsRDFCID.h"
#include "nsXPIDLString.h" #include "nsXPIDLString.h"
@ -37,13 +38,20 @@ nsrefcnt nsRDFResource::gRDFServiceRefCnt = 0;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
nsRDFResource::nsRDFResource(void) nsRDFResource::nsRDFResource(void)
: mURI(nsnull) : mURI(nsnull), mDelegates(nsnull)
{ {
NS_INIT_REFCNT(); NS_INIT_REFCNT();
} }
nsRDFResource::~nsRDFResource(void) nsRDFResource::~nsRDFResource(void)
{ {
// Release all of the delegate objects
while (mDelegates) {
DelegateEntry* doomed = mDelegates;
mDelegates = mDelegates->mNext;
delete doomed;
}
gRDFService->UnregisterResource(this); gRDFService->UnregisterResource(this);
// N.B. that we need to free the URI *after* we un-cache the resource, // N.B. that we need to free the URI *after* we un-cache the resource,
@ -166,4 +174,85 @@ nsRDFResource::EqualsString(const char* aURI, PRBool* aResult)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsRDFResource::GetDelegate(const char* aKey, REFNSIID aIID, void** aResult)
{
NS_PRECONDITION(aKey != nsnull, "null ptr");
if (! aKey)
return NS_ERROR_NULL_POINTER;
nsresult rv;
*aResult = nsnull;
DelegateEntry* entry = mDelegates;
while (entry) {
if (entry->mKey == aKey) {
rv = entry->mDelegate->QueryInterface(aIID, aResult);
return rv;
}
entry = entry->mNext;
}
// Construct a ProgID of the form "component:/rdf/delegate/[key]/[scheme]
nsCAutoString progID("component://rdf/delegate-factory/");
progID.Append(aKey);
progID.Append("/");
for (const char* p = mURI; *p && *p != ':'; ++p)
progID.Append(*p);
nsCOMPtr<nsIRDFDelegateFactory> delegateFactory;
rv = nsComponentManager::CreateInstance(progID,
nsnull,
NS_GET_IID(nsIRDFDelegateFactory),
getter_AddRefs(delegateFactory));
if (NS_FAILED(rv)) return rv;
rv = delegateFactory->CreateDelegate(this, aKey, aIID, aResult);
if (NS_FAILED(rv)) return rv;
// Okay, we've successfully created a delegate. Let's remember it.
entry = new DelegateEntry;
if (! entry) {
NS_RELEASE(*NS_REINTERPRET_CAST(nsISupports**, aResult));
return NS_ERROR_OUT_OF_MEMORY;
}
entry->mKey = aKey;
entry->mDelegate = do_QueryInterface(*NS_REINTERPRET_CAST(nsISupports**, aResult));
entry->mNext = mDelegates;
mDelegates = entry;
return NS_OK;
}
NS_IMETHODIMP
nsRDFResource::ReleaseDelegate(const char* aKey)
{
NS_PRECONDITION(aKey != nsnull, "null ptr");
if (! aKey)
return NS_ERROR_NULL_POINTER;
DelegateEntry* entry = mDelegates;
DelegateEntry** link = &mDelegates;
while (entry) {
if (entry->mKey == aKey) {
*link = entry->mNext;
delete entry;
return NS_OK;
}
link = &(entry->mNext);
entry = entry->mNext;
}
NS_WARNING("nsRDFResource::ReleaseDelegate() no delegate found");
return NS_OK;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////