1998-12-24 08:07:14 +03: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 "License"); you may not use this file except in
|
|
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/NPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS"
|
|
|
|
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
|
|
|
* the License for the specific language governing rights and limitations
|
|
|
|
* under the License.
|
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Communicator client code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape Communications
|
|
|
|
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
|
|
|
* Netscape Communications Corporation. All Rights Reserved.
|
|
|
|
*/
|
|
|
|
|
1999-01-06 00:22:20 +03:00
|
|
|
/*
|
|
|
|
|
|
|
|
Implementations for a bunch of useful RDF utility routines. Many of
|
|
|
|
these will eventually be exported outside of RDF.DLL via the
|
|
|
|
nsIRDFService interface.
|
|
|
|
|
1999-02-16 22:30:04 +03:00
|
|
|
TO DO
|
|
|
|
|
|
|
|
1) Make this so that it doesn't permanently leak the RDF service
|
|
|
|
object.
|
|
|
|
|
|
|
|
2) Make container functions thread-safe. They currently don't ensure
|
|
|
|
that the RDF:nextVal property is maintained safely.
|
|
|
|
|
1999-01-06 00:22:20 +03:00
|
|
|
*/
|
|
|
|
|
1999-02-16 22:30:04 +03:00
|
|
|
#include "nsCOMPtr.h"
|
1999-01-20 04:42:13 +03:00
|
|
|
#include "nsIRDFDataSource.h"
|
1998-12-24 08:07:14 +03:00
|
|
|
#include "nsIRDFNode.h"
|
1999-01-05 06:53:15 +03:00
|
|
|
#include "nsIRDFService.h"
|
1999-01-12 22:41:06 +03:00
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsRDFCID.h"
|
1998-12-24 08:07:14 +03:00
|
|
|
#include "nsString.h"
|
1999-03-29 23:52:54 +04:00
|
|
|
#include "nsXPIDLString.h"
|
1999-01-22 09:48:25 +03:00
|
|
|
#include "plstr.h"
|
1999-02-16 22:30:04 +03:00
|
|
|
#include "prprf.h"
|
1999-05-22 02:18:29 +04:00
|
|
|
#include "prtime.h"
|
1998-12-24 08:07:14 +03:00
|
|
|
#include "rdfutil.h"
|
|
|
|
|
|
|
|
#include "rdf.h"
|
|
|
|
static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
|
|
|
|
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
|
1999-01-12 22:41:06 +03:00
|
|
|
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
|
|
|
|
|
|
|
|
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
1999-01-22 09:48:25 +03:00
|
|
|
// XXX This'll permanently leak
|
1999-01-12 22:41:06 +03:00
|
|
|
static nsIRDFService* gRDFService = nsnull;
|
|
|
|
|
1999-01-22 09:48:25 +03:00
|
|
|
static nsIRDFResource* kRDF_instanceOf = nsnull;
|
|
|
|
static nsIRDFResource* kRDF_Bag = nsnull;
|
|
|
|
static nsIRDFResource* kRDF_Seq = nsnull;
|
|
|
|
static nsIRDFResource* kRDF_Alt = nsnull;
|
|
|
|
static nsIRDFResource* kRDF_nextVal = nsnull;
|
|
|
|
|
1999-01-12 22:41:06 +03:00
|
|
|
static nsresult
|
|
|
|
rdf_EnsureRDFService(void)
|
|
|
|
{
|
|
|
|
if (gRDFService)
|
|
|
|
return NS_OK;
|
|
|
|
|
1999-01-22 09:48:25 +03:00
|
|
|
nsresult rv;
|
|
|
|
|
1999-04-17 04:10:18 +04:00
|
|
|
rv = nsServiceManager::GetService(kRDFServiceCID,
|
|
|
|
kIRDFServiceIID,
|
|
|
|
(nsISupports**) &gRDFService);
|
1999-01-22 09:48:25 +03:00
|
|
|
|
1999-04-17 04:10:18 +04:00
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-01-22 09:48:25 +03:00
|
|
|
|
1999-04-17 04:10:18 +04:00
|
|
|
rv = gRDFService->GetResource(RDF_NAMESPACE_URI "instanceOf", &kRDF_instanceOf);
|
|
|
|
rv = gRDFService->GetResource(RDF_NAMESPACE_URI "Bag", &kRDF_Bag);
|
|
|
|
rv = gRDFService->GetResource(RDF_NAMESPACE_URI "Seq", &kRDF_Seq);
|
|
|
|
rv = gRDFService->GetResource(RDF_NAMESPACE_URI "Alt", &kRDF_Alt);
|
|
|
|
rv = gRDFService->GetResource(RDF_NAMESPACE_URI "nextVal", &kRDF_nextVal);
|
1999-01-22 09:48:25 +03:00
|
|
|
|
1999-04-17 04:10:18 +04:00
|
|
|
return NS_OK;
|
1999-01-12 22:41:06 +03:00
|
|
|
}
|
1998-12-24 08:07:14 +03:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
1999-04-27 09:54:18 +04:00
|
|
|
PR_IMPLEMENT(PRBool)
|
1999-04-17 04:10:18 +04:00
|
|
|
rdf_IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType)
|
1999-01-22 09:48:25 +03:00
|
|
|
{
|
|
|
|
nsresult rv;
|
1999-04-17 04:10:18 +04:00
|
|
|
rv = rdf_EnsureRDFService();
|
|
|
|
if (NS_FAILED(rv)) return PR_FALSE;
|
1998-12-24 08:07:14 +03:00
|
|
|
|
1999-04-17 04:10:18 +04:00
|
|
|
PRBool result;
|
|
|
|
rv = aDataSource->HasAssertion(aResource, kRDF_instanceOf, aType, PR_TRUE, &result);
|
|
|
|
if (NS_FAILED(rv)) return PR_FALSE;
|
1999-01-22 01:24:32 +03:00
|
|
|
|
1999-01-22 09:48:25 +03:00
|
|
|
return result;
|
|
|
|
}
|
1999-01-22 01:24:32 +03:00
|
|
|
|
1999-01-22 09:48:25 +03:00
|
|
|
|
1998-12-24 08:07:14 +03:00
|
|
|
nsresult
|
1999-04-17 04:10:18 +04:00
|
|
|
rdf_CreateAnonymousResource(const nsString& aContextURI, nsIRDFResource** aResult)
|
1998-12-24 08:07:14 +03:00
|
|
|
{
|
1999-01-22 09:48:25 +03:00
|
|
|
static PRUint32 gCounter = 0;
|
1998-12-24 08:07:14 +03:00
|
|
|
|
1999-01-12 22:41:06 +03:00
|
|
|
nsresult rv;
|
1999-04-17 04:10:18 +04:00
|
|
|
rv = rdf_EnsureRDFService();
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-01-12 22:41:06 +03:00
|
|
|
|
1999-05-22 02:18:29 +04:00
|
|
|
if (! gCounter) {
|
|
|
|
// Start it at a semi-unique value, just to minimize the
|
|
|
|
// chance that we get into a situation where
|
|
|
|
//
|
|
|
|
// 1. An anonymous resource gets serialized out in a graph
|
|
|
|
// 2. Reboot
|
|
|
|
// 3. The same anonymous resource gets requested, and refers
|
|
|
|
// to something completely different.
|
|
|
|
// 4. The serialization is read back in.
|
|
|
|
LL_L2UI(gCounter, PR_Now());
|
|
|
|
}
|
|
|
|
|
1999-01-22 09:48:25 +03:00
|
|
|
do {
|
|
|
|
nsAutoString s(aContextURI);
|
1999-01-26 04:23:55 +03:00
|
|
|
s.Append("#$");
|
1999-05-22 02:18:29 +04:00
|
|
|
s.Append(++gCounter, 16);
|
1999-01-22 09:48:25 +03:00
|
|
|
|
|
|
|
nsIRDFResource* resource;
|
1999-04-22 09:57:36 +04:00
|
|
|
if (NS_FAILED(rv = gRDFService->GetUnicodeResource(s.GetUnicode(), &resource)))
|
1999-01-22 09:48:25 +03:00
|
|
|
return rv;
|
|
|
|
|
|
|
|
// XXX an ugly but effective way to make sure that this
|
|
|
|
// resource is really unique in the world.
|
|
|
|
nsrefcnt refcnt = resource->AddRef();
|
|
|
|
resource->Release();
|
|
|
|
|
|
|
|
if (refcnt == 2) {
|
1999-04-17 04:10:18 +04:00
|
|
|
*aResult = resource;
|
1999-01-22 09:48:25 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
rdf_IsAnonymousResource(const nsString& aContextURI, nsIRDFResource* aResource)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
1999-03-29 23:52:54 +04:00
|
|
|
nsXPIDLCString s;
|
|
|
|
if (NS_FAILED(rv = aResource->GetValue( getter_Copies(s) ))) {
|
1999-01-22 09:48:25 +03:00
|
|
|
NS_ASSERTION(PR_FALSE, "unable to get resource URI");
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
1999-03-29 23:52:54 +04:00
|
|
|
nsAutoString uri((const char*) s);
|
1999-01-22 09:48:25 +03:00
|
|
|
|
|
|
|
// Make sure that they have the same context (prefix)
|
|
|
|
if (uri.Find(aContextURI) != 0)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
uri.Cut(0, aContextURI.Length());
|
|
|
|
|
|
|
|
// Anonymous resources look like the regexp "\$[0-9]+"
|
1999-04-20 11:20:21 +04:00
|
|
|
if (uri.CharAt(0) != '#' || uri.CharAt(1) != '$')
|
1999-01-22 09:48:25 +03:00
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
for (PRInt32 i = uri.Length() - 1; i >= 1; --i) {
|
1999-04-20 11:20:21 +04:00
|
|
|
if (uri.CharAt(i) < '0' || uri.CharAt(i) > '9')
|
1999-01-22 09:48:25 +03:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_TRUE;
|
1998-12-24 08:07:14 +03:00
|
|
|
}
|
|
|
|
|
1999-01-22 09:48:25 +03:00
|
|
|
|
|
|
|
PR_EXTERN(nsresult)
|
|
|
|
rdf_PossiblyMakeRelative(const nsString& aContextURI, nsString& aURI)
|
|
|
|
{
|
|
|
|
// This implementation is extremely simple: no ".." or anything
|
|
|
|
// fancy like that. If the context URI is not a prefix of the URI
|
|
|
|
// in question, we'll just bail.
|
|
|
|
if (aURI.Find(aContextURI) != 0)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// Otherwise, pare down the target URI, removing the context URI.
|
|
|
|
aURI.Cut(0, aContextURI.Length());
|
1999-03-05 03:03:30 +03:00
|
|
|
|
|
|
|
if (aURI.First() == '#' || aURI.First() == '/')
|
|
|
|
aURI.Cut(0, 1);
|
|
|
|
|
1999-01-22 09:48:25 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-02-17 14:09:57 +03:00
|
|
|
PR_EXTERN(nsresult)
|
|
|
|
rdf_PossiblyMakeAbsolute(const nsString& aContextURI, nsString& aURI)
|
|
|
|
{
|
|
|
|
PRInt32 index = aURI.Find(':');
|
1999-03-19 00:43:00 +03:00
|
|
|
if (index > 0 && index < 25 /* XXX */)
|
1999-02-17 14:09:57 +03:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
PRUnichar last = aContextURI.Last();
|
|
|
|
PRUnichar first = aURI.First();
|
|
|
|
|
|
|
|
nsAutoString result(aContextURI);
|
|
|
|
if (last == '#' || last == '/') {
|
|
|
|
if (first == '#') {
|
|
|
|
result.Truncate(result.Length() - 2);
|
|
|
|
}
|
|
|
|
result.Append(aURI);
|
|
|
|
}
|
|
|
|
else if (first == '#') {
|
|
|
|
result.Append(aURI);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
result.Append('#');
|
|
|
|
result.Append(aURI);
|
|
|
|
}
|
|
|
|
|
|
|
|
aURI = result;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-04-17 04:10:18 +04:00
|
|
|
|