Move APIs to create 'anonymous' resources into the RDF service. Fix stuff that was using it.

This commit is contained in:
waterson%netscape.com 1999-09-06 19:35:41 +00:00
parent 154f675bda
commit 22f68c9558
7 changed files with 158 additions and 151 deletions

View File

@ -38,6 +38,8 @@ interface nsIRDFService : nsISupports {
// be converted to a single-byte representation internally.
nsIRDFResource GetUnicodeResource(in wstring aURI);
nsIRDFResource GetAnonymousResource();
// Construct an RDF literal from a Unicode string.
nsIRDFLiteral GetLiteral(in wstring aValue);
@ -47,6 +49,8 @@ interface nsIRDFService : nsISupports {
// Construct an RDF literal from an int.
nsIRDFInt GetIntLiteral(in long aValue);
boolean IsAnonymousResource(in nsIRDFResource aResource);
// Registers a resource with the RDF system, making it unique w.r.t.
// GetResource.
//

View File

@ -1031,7 +1031,7 @@ RDFContentSinkImpl::GetIdAboutAttribute(const nsIParserNode& aNode,
}
// Otherwise, we couldn't find anything, so just gensym one...
rv = rdf_CreateAnonymousResource(nsCAutoString(docURI), aResource);
rv = gRDFService->GetAnonymousResource(aResource);
return rv;
}

View File

@ -622,6 +622,69 @@ ServiceImpl::GetUnicodeResource(const PRUnichar* aURI, nsIRDFResource** aResourc
}
NS_IMETHODIMP
ServiceImpl::GetAnonymousResource(nsIRDFResource** aResult)
{
static PRUint32 gCounter = 0;
static char gChars[] = "0123456789abcdef"
"ghijklmnopqrstuv"
"wxyzABCDEFGHIJKL"
"MNOPQRSTUVWXYZ.+";
static PRInt32 kMask = 0x003f;
static PRInt32 kShift = 6;
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());
}
nsresult rv;
nsCAutoString s;
do {
// Ugh, this is a really sloppy way to do this; I copied the
// implementation from the days when it lived outside the RDF
// service. Now that it's a member we can be more cleverer.
s.Truncate();
s.Append("rdf:#$");
PRUint32 id = ++gCounter;
while (id) {
char ch = gChars[(id & kMask)];
s.Append(ch);
id >>= kShift;
}
nsIRDFResource* resource;
rv = GetResource((const char*) s, &resource);
if (NS_FAILED(rv)) return rv;
// XXX an ugly but effective way to make sure that this
// resource is really unique in the world.
resource->AddRef();
nsrefcnt refcnt = resource->Release();
if (refcnt == 1) {
*aResult = resource;
break;
}
NS_RELEASE(resource);
} while (1);
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::GetLiteral(const PRUnichar* aValue, nsIRDFLiteral** aLiteral)
{
@ -679,6 +742,35 @@ ServiceImpl::GetIntLiteral(PRInt32 value, nsIRDFInt** literal)
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::IsAnonymousResource(nsIRDFResource* aResource, PRBool* _result)
{
NS_PRECONDITION(aResource != nsnull, "null ptr");
if (! aResource)
return NS_ERROR_NULL_POINTER;
nsresult rv;
const char* uri;
rv = aResource->GetValueConst(&uri);
if (NS_FAILED(rv)) return rv;
if ((uri[0] == 'r') &&
(uri[1] == 'd') &&
(uri[2] == 'f') &&
(uri[3] == ':') &&
(uri[4] == '#') &&
(uri[5] == '$')) {
*_result = PR_TRUE;
}
else {
*_result = PR_FALSE;
}
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::RegisterResource(nsIRDFResource* aResource, PRBool replace)
{

View File

@ -50,100 +50,8 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "prtime.h"
#include "rdfutil.h"
#include "rdf.h"
static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
////////////////////////////////////////////////////////////////////////
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
////////////////////////////////////////////////////////////////////////
nsresult
rdf_CreateAnonymousResource(const nsCString& aContextURI, nsIRDFResource** aResult)
{
static PRUint32 gCounter = 0;
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());
}
nsresult rv;
NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
do {
char buf[128];
CBufDescriptor desc(buf, PR_TRUE, sizeof(buf));
nsCAutoString s(desc);
s = aContextURI;
s.Append("#$");
s.Append(++gCounter, 16);
nsIRDFResource* resource;
rv = rdf->GetResource((const char*) s, &resource);
if (NS_FAILED(rv)) return rv;
// XXX an ugly but effective way to make sure that this
// resource is really unique in the world.
resource->AddRef();
nsrefcnt refcnt = resource->Release();
if (refcnt == 1) {
*aResult = resource;
break;
}
NS_RELEASE(resource);
} while (1);
return NS_OK;
}
PRBool
rdf_IsAnonymousResource(const nsCString& aContextURI, nsIRDFResource* aResource)
{
nsresult rv;
const char* p;
rv = aResource->GetValueConst(&p);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get resource URI");
if (NS_FAILED(rv))
return PR_FALSE;
{
CBufDescriptor desc(NS_CONST_CAST(char*, p), PR_TRUE, -1);
nsCAutoString uri(desc);
if (uri.Find(aContextURI) != 0)
return PR_FALSE;
}
{
CBufDescriptor desc(NS_CONST_CAST(char*, p + aContextURI.Length()), PR_TRUE, -1);
nsCAutoString id(desc);
if (id.CharAt(0) != '#' || id.CharAt(1) != '$')
return PR_FALSE;
for (PRInt32 i = id.Length() - 1; i >= 1; --i) {
if (id.CharAt(i) < '0' || id.CharAt(i) > '9')
return PR_FALSE;
}
}
return PR_TRUE;
}
nsresult
rdf_MakeRelativeRef(const nsString& aBaseURI, nsString& aURI)
{

View File

@ -38,25 +38,10 @@
#include "prtypes.h"
class nsIRDFResource;
class nsCString;
class nsString;
class nsIURI;
/**
* Construct a new, "anonymous" node; that is, a node with an internal
* resource URI.
*/
nsresult
rdf_CreateAnonymousResource(const nsCString& aContextURI, nsIRDFResource** result);
/**
* Determine if a resource is an "anonymous" resource that we've constructed
* ourselves.
*/
PRBool
rdf_IsAnonymousResource(const nsCString& aContextURI, nsIRDFResource* aResource);
nsresult
rdf_MakeRelativeRef(const nsString& aBaseURI, nsString& aURI);

View File

@ -622,7 +622,7 @@ RDFXULBuilderImpl::CreateContents(nsIContent* aElement)
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to test contents-generated attribute");
if (NS_FAILED(rv)) return rv;
if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (attrValue.EqualsIgnoreCase("true")))
if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (attrValue.Equals("true")))
return NS_OK;
#ifdef PR_LOGGING
@ -902,7 +902,7 @@ RDFXULBuilderImpl::OnAssert(nsIRDFResource* aSource,
if (rv == NS_CONTENT_ATTR_NOT_THERE || rv == NS_CONTENT_ATTR_NO_VALUE)
continue;
if (! contentsGenerated.EqualsIgnoreCase("true"))
if (! contentsGenerated.Equals("true"))
continue;
// Okay, it's a "live" element, so go ahead and insert the
@ -1030,7 +1030,7 @@ RDFXULBuilderImpl::OnUnassert(nsIRDFResource* aSource,
if (rv == NS_CONTENT_ATTR_NOT_THERE || rv == NS_CONTENT_ATTR_NO_VALUE)
continue;
if (! contentsGenerated.EqualsIgnoreCase("true"))
if (! contentsGenerated.Equals("true"))
continue;
// Okay, it's a "live" element, so go ahead and remove the
@ -1155,7 +1155,7 @@ RDFXULBuilderImpl::OnChange(nsIRDFResource* aSource,
if (rv == NS_CONTENT_ATTR_NOT_THERE || rv == NS_CONTENT_ATTR_NO_VALUE)
continue;
if (! contentsGenerated.EqualsIgnoreCase("true"))
if (! contentsGenerated.Equals("true"))
continue;
// Okay, it's a "live" element, so go ahead and insert the
@ -1614,25 +1614,35 @@ RDFXULBuilderImpl::CreateHTMLElement(nsINameSpace* aContainingNameSpace,
if (NS_FAILED(rv)) return rv;
if (aResource) {
// Set the 'id' attribute
nsXPIDLCString uri;
rv = aResource->GetValue( getter_Copies(uri) );
#ifdef NO_ID_ON_ANONYMOUS_ELEMENTS
PRBool isAnonymous;
rv = gRDFService->IsAnonymousResource(aResource, &isAnonymous);
if (NS_FAILED(rv)) return rv;
nsAutoString id;
rv = nsRDFContentUtils::MakeElementID(doc, nsAutoString(uri), id);
if (NS_FAILED(rv)) return rv;
if (! isAnonymous) {
#endif
// Set the 'id' attribute
nsXPIDLCString uri;
rv = aResource->GetValue( getter_Copies(uri) );
if (NS_FAILED(rv)) return rv;
nsAutoString id;
rv = nsRDFContentUtils::MakeElementID(doc, nsAutoString(uri), id);
if (NS_FAILED(rv)) return rv;
rv = element->SetAttribute(kNameSpaceID_None, kIdAtom, id, PR_FALSE);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to set element's ID");
if (NS_FAILED(rv)) return rv;
rv = element->SetAttribute(kNameSpaceID_None, kIdAtom, id, PR_FALSE);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to set element's ID");
if (NS_FAILED(rv)) return rv;
// Since we didn't notify when setting the 'id' attribute, we
// need to explicitly add ourselves to the resource-to-element
// map. XUL elements don't need to do this, because they've
// got a hacked SetAttribute() method...
rv = mDocument->AddElementForResource(aResource, element);
if (NS_FAILED(rv)) return rv;
// Since we didn't notify when setting the 'id' attribute, we
// need to explicitly add ourselves to the resource-to-element
// map. XUL elements don't need to do this, because they've
// got a hacked SetAttribute() method...
rv = mDocument->AddElementForResource(aResource, element);
if (NS_FAILED(rv)) return rv;
#ifdef NO_ID_ON_ANONYMOUS_ELEMENTS
}
#endif
// Now iterate through all the properties and add them as
// attributes on the element. First, create a cursor that'll
@ -1785,26 +1795,36 @@ RDFXULBuilderImpl::CreateXULElement(nsINameSpace* aContainingNameSpace,
if (NS_FAILED(rv)) return rv;
if (aResource) {
// Set the element's ID. The XUL document will be listening
// for 'id' and 'ref' attribute changes, so we're sure that
// this will get properly hashed into the document's
// resource-to-element map.
nsXPIDLCString uri;
rv = aResource->GetValue( getter_Copies(uri) );
#ifdef NO_ID_ON_ANONYMOUS_ELEMENTS
PRBool isAnonymous;
rv = gRDFService->IsAnonymousResource(aResource, &isAnonymous);
if (NS_FAILED(rv)) return rv;
nsAutoString id;
rv = nsRDFContentUtils::MakeElementID(document, nsAutoString(uri), id);
if (NS_FAILED(rv)) return rv;
if (! isAnonymous) {
#endif
// Set the element's ID. The XUL document will be listening
// for 'id' and 'ref' attribute changes, so we're sure that
// this will get properly hashed into the document's
// resource-to-element map.
nsXPIDLCString uri;
rv = aResource->GetValue( getter_Copies(uri) );
if (NS_FAILED(rv)) return rv;
rv = element->SetAttribute(kNameSpaceID_None, kIdAtom, id, PR_FALSE);
if (NS_FAILED(rv)) return rv;
nsAutoString id;
rv = nsRDFContentUtils::MakeElementID(document, nsAutoString(uri), id);
if (NS_FAILED(rv)) return rv;
// The XUL element's implementation has a hacked
// SetAttribute() method that'll be smart enough to add the
// element to the document's element-to-resource map, so no
// need to do it ourselves. N.B. that this is _different_ from
// an HTML element...
rv = element->SetAttribute(kNameSpaceID_None, kIdAtom, id, PR_FALSE);
if (NS_FAILED(rv)) return rv;
// The XUL element's implementation has a hacked
// SetAttribute() method that'll be smart enough to add the
// element to the document's element-to-resource map, so no
// need to do it ourselves. N.B. that this is _different_ from
// an HTML element...
#ifdef NO_ID_ON_ANONYMOUS_ELEMENTS
}
#endif
// Now iterate through all the properties and add them as
// attributes on the element. First, create a cursor that'll

View File

@ -183,6 +183,7 @@ protected:
static nsIRDFResource* kRDF_instanceOf;
static nsIRDFResource* kXUL_element;
static nsIRDFResource* kXUL_tag;
static nsIRDFResource* kPosition;
// Text management
nsresult FlushText(PRBool aCreateTextNode=PR_TRUE,
@ -274,6 +275,7 @@ nsIRDFResource* XULContentSinkImpl::kRDF_child;
nsIRDFResource* XULContentSinkImpl::kRDF_instanceOf;
nsIRDFResource* XULContentSinkImpl::kXUL_element;
nsIRDFResource* XULContentSinkImpl::kXUL_tag;
nsIRDFResource* XULContentSinkImpl::kPosition;
////////////////////////////////////////////////////////////////////////
@ -316,6 +318,7 @@ XULContentSinkImpl::XULContentSinkImpl()
gRDFService->GetResource(RDF_NAMESPACE_URI "instanceOf", &kRDF_instanceOf);
gRDFService->GetResource(XUL_NAMESPACE_URI "#element", &kXUL_element);
gRDFService->GetResource(XUL_NAMESPACE_URI "#tag", &kXUL_tag);
gRDFService->GetResource("position", &kPosition);
}
}
@ -445,6 +448,7 @@ XULContentSinkImpl::~XULContentSinkImpl()
NS_IF_RELEASE(kRDF_instanceOf);
NS_IF_RELEASE(kXUL_tag);
NS_IF_RELEASE(kXUL_element);
NS_IF_RELEASE(kPosition);
}
// Delete all the elements from our overlay array
@ -1274,7 +1278,7 @@ XULContentSinkImpl::GetXULIDAttribute(const nsIParserNode& aNode,
// Otherwise, we couldn't find anything, so just gensym one...
nsXPIDLCString url;
mDocumentURL->GetSpec(getter_Copies(url));
return rdf_CreateAnonymousResource(nsCAutoString(url), aResource);
return gRDFService->GetAnonymousResource(aResource);
}
nsresult
@ -1459,14 +1463,8 @@ XULContentSinkImpl::OpenTag(const nsIParserNode& aNode)
// Find out if a position is specified. If so, we use that as the arc
// label instead of appending the object to the end.
// Add the attribute to RDF
nsCOMPtr<nsIRDFResource> property;
nsAutoString attr("#position");
rv = gRDFService->GetUnicodeResource(attr.GetUnicode(), getter_AddRefs(property));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIRDFNode> positionValue;
rv = mDataSource->GetTarget(rdfResource, property, PR_TRUE, getter_AddRefs(positionValue));
rv = mDataSource->GetTarget(rdfResource, kPosition, PR_TRUE, getter_AddRefs(positionValue));
if (NS_FAILED(rv)) return rv;
if (positionValue) {