Implemented RDF container support and improved support for 'anonymous' resources for output of RDF/XML. Cleaned up common RDF vocabularies, placing #defines into rdf.h.

This commit is contained in:
waterson%netscape.com 1999-01-22 06:48:25 +00:00
Родитель 3f64184685
Коммит d1f68358c9
13 изменённых файлов: 346 добавлений и 171 удалений

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

@ -75,6 +75,10 @@ public:
* Determine if two resources are identical. * Determine if two resources are identical.
*/ */
NS_IMETHOD EqualsResource(const nsIRDFResource* resource, PRBool* result) const = 0; NS_IMETHOD EqualsResource(const nsIRDFResource* resource, PRBool* result) const = 0;
/**
* Determine if two resources are identical.
*/
NS_IMETHOD EqualsString(const char* uri, PRBool* result) const = 0; NS_IMETHOD EqualsString(const char* uri, PRBool* result) const = 0;
}; };

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

@ -47,6 +47,13 @@
static const char* kURI##prefix##_##name = ##namespace #name ;\ static const char* kURI##prefix##_##name = ##namespace #name ;\
static const char* kTag##prefix##_##name = kURI##prefix##_##name## + sizeof(##namespace) - 1 static const char* kTag##prefix##_##name = kURI##prefix##_##name## + sizeof(##namespace) - 1
/**
* Core RDF vocabularies that we use to infer semantic actions
*/
#define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
#define WEB_NAMESPACE_URI "http://home.netscape.com/WEB-rdf#"
#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#"
/** /**
* @name Standard RDF error codes * @name Standard RDF error codes

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

@ -63,7 +63,6 @@ static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
#define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI; static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, nextVal); // ad hoc way to make containers fast DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, nextVal); // ad hoc way to make containers fast

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

@ -42,8 +42,6 @@
does namespaces: should we storing tag/namespace pairs instead of does namespaces: should we storing tag/namespace pairs instead of
the entire URI in the elements? the entire URI in the elements?
3) Write a test harness.
*/ */
#include "nsIContentSink.h" #include "nsIContentSink.h"
@ -71,7 +69,6 @@ static const char kNameSpaceDef[] = "xmlns";
// RDF core vocabulary // RDF core vocabulary
#include "rdf.h" #include "rdf.h"
#define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Alt); DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Alt);
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Bag); DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Bag);
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Description); DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Description);
@ -121,7 +118,7 @@ rdf_EntityToUnicode(const char* buf)
(buf[2] == 'p' || buf[2] == 'P')) (buf[2] == 'p' || buf[2] == 'P'))
return PRUnichar('&'); return PRUnichar('&');
PR_ASSERT(0); // XXX this is a named entity that I can't handle... NS_NOTYETIMPLEMENTED("this is a named entity that I can't handle...");
return PRUnichar('?'); return PRUnichar('?');
} }
@ -245,6 +242,7 @@ rdf_StripAndConvert(nsString& aResult)
else if (e == '{') { else if (e == '{') {
// Convert a script entity // Convert a script entity
// XXX write me! // XXX write me!
NS_NOTYETIMPLEMENTED("convert a script entity");
} }
} }
} }
@ -307,13 +305,6 @@ rdf_FullyQualifyURI(const nsIURL* base, nsString& spec)
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
class nsIURL;
class nsVoidArray;
class nsIRDFResource;
class nsIRDFDataSource;
class nsIRDFService;
class nsINameSpaceManager;
typedef enum { typedef enum {
eRDFContentSinkState_InProlog, eRDFContentSinkState_InProlog,
eRDFContentSinkState_InDocumentElement, eRDFContentSinkState_InDocumentElement,
@ -386,8 +377,8 @@ protected:
nsString& rProperty); nsString& rProperty);
// RDF-specific parsing // RDF-specific parsing
nsresult GetIdAboutAttribute(const nsIParserNode& aNode, nsString& rResource); nsresult GetIdAboutAttribute(const nsIParserNode& aNode, nsIRDFResource** aResource);
nsresult GetResourceAttribute(const nsIParserNode& aNode, nsString& rResource); nsresult GetResourceAttribute(const nsIParserNode& aNode, nsIRDFResource** aResource);
nsresult AddProperties(const nsIParserNode& aNode, nsIRDFResource* aSubject); nsresult AddProperties(const nsIParserNode& aNode, nsIRDFResource* aSubject);
virtual nsresult OpenRDF(const nsIParserNode& aNode); virtual nsresult OpenRDF(const nsIParserNode& aNode);
@ -931,8 +922,8 @@ RDFContentSinkImpl::FlushText(PRBool aCreateTextNode, PRBool* aDidFlush)
void void
RDFContentSinkImpl::SplitQualifiedName(const nsString& aQualifiedName, RDFContentSinkImpl::SplitQualifiedName(const nsString& aQualifiedName,
PRInt32& rNameSpaceID, PRInt32& rNameSpaceID,
nsString& rProperty) nsString& rProperty)
{ {
rProperty = aQualifiedName; rProperty = aQualifiedName;
nsIAtom* prefix = CutNameSpacePrefix(rProperty); nsIAtom* prefix = CutNameSpacePrefix(rProperty);
@ -943,13 +934,14 @@ RDFContentSinkImpl::SplitQualifiedName(const nsString& aQualifiedName,
nsresult nsresult
RDFContentSinkImpl::GetIdAboutAttribute(const nsIParserNode& aNode, RDFContentSinkImpl::GetIdAboutAttribute(const nsIParserNode& aNode,
nsString& rResource) nsIRDFResource** aResource)
{ {
// This corresponds to the dirty work of production [6.5] // This corresponds to the dirty work of production [6.5]
nsAutoString k; nsAutoString k;
nsAutoString attr; nsAutoString attr;
PRInt32 nameSpaceID; PRInt32 nameSpaceID;
PRInt32 ac = aNode.GetAttributeCount(); PRInt32 ac = aNode.GetAttributeCount();
nsresult rv;
for (PRInt32 i = 0; i < ac; i++) { for (PRInt32 i = 0; i < ac; i++) {
// Get upper-cased key // Get upper-cased key
@ -963,44 +955,47 @@ RDFContentSinkImpl::GetIdAboutAttribute(const nsIParserNode& aNode,
// first thing that was specified and ignore the other. // first thing that was specified and ignore the other.
if (attr.Equals(kTagRDF_about)) { if (attr.Equals(kTagRDF_about)) {
rResource = aNode.GetValueAt(i); nsAutoString uri = aNode.GetValueAt(i);
rdf_StripAndConvert(rResource); rdf_StripAndConvert(uri);
return NS_OK; return mRDFService->GetUnicodeResource(uri, aResource);
} }
if (attr.Equals(kTagRDF_ID)) { if (attr.Equals(kTagRDF_ID)) {
PRUnichar* str; const char* docURI;
mDocumentURL->ToString(&str); mDocumentURL->GetSpec(&docURI);
rResource = str;
delete str; if (NS_FAILED(rv = mRDFService->GetResource(docURI, aResource)))
return rv;
nsAutoString uri(docURI);
nsAutoString tag = aNode.GetValueAt(i); nsAutoString tag = aNode.GetValueAt(i);
rdf_StripAndConvert(tag); rdf_StripAndConvert(tag);
if (rResource.Last() != '#' && tag.First() != '#') if (uri.Last() != '#' && tag.First() != '#')
rResource.Append('#'); uri.Append('#');
rResource.Append(tag); uri.Append(tag);
return NS_OK;
return mRDFService->GetUnicodeResource(uri, aResource);
} }
// XXX we don't deal with aboutEach... if (attr.Equals(kTagRDF_aboutEach)) {
// XXX we don't deal with aboutEach...
NS_NOTYETIMPLEMENTED("RDF:aboutEach is not understood at this time");
}
} }
// Otherwise, we couldn't find anything, so just gensym one... // Otherwise, we couldn't find anything, so just gensym one...
PRUnichar* str; const char* url;
mDocumentURL->ToString(&str); mDocumentURL->GetSpec(&url);
rResource = str; return rdf_CreateAnonymousResource(url, aResource);
delete str;
rResource.Append("#anonymous$");
rResource.Append(mGenSym++, 10);
return NS_OK;
} }
nsresult nsresult
RDFContentSinkImpl::GetResourceAttribute(const nsIParserNode& aNode, RDFContentSinkImpl::GetResourceAttribute(const nsIParserNode& aNode,
nsString& rResource) nsIRDFResource** aResource)
{ {
nsAutoString k; nsAutoString k;
nsAutoString attr; nsAutoString attr;
@ -1019,15 +1014,15 @@ RDFContentSinkImpl::GetResourceAttribute(const nsIParserNode& aNode,
// first thing that was specified and ignore the other. // first thing that was specified and ignore the other.
if (attr.Equals(kTagRDF_resource)) { if (attr.Equals(kTagRDF_resource)) {
rResource = aNode.GetValueAt(i); nsAutoString uri = aNode.GetValueAt(i);
rdf_StripAndConvert(rResource); rdf_StripAndConvert(uri);
// XXX Take the URI and make it fully qualified by // XXX Take the URI and make it fully qualified by
// sticking it into the document's URL. This may not be // sticking it into the document's URL. This may not be
// appropriate... // appropriate...
rdf_FullyQualifyURI(mDocumentURL, rResource); rdf_FullyQualifyURI(mDocumentURL, uri);
return NS_OK; return mRDFService->GetUnicodeResource(uri, aResource);
} }
} }
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -1035,7 +1030,7 @@ RDFContentSinkImpl::GetResourceAttribute(const nsIParserNode& aNode,
nsresult nsresult
RDFContentSinkImpl::AddProperties(const nsIParserNode& aNode, RDFContentSinkImpl::AddProperties(const nsIParserNode& aNode,
nsIRDFResource* aSubject) nsIRDFResource* aSubject)
{ {
// Add tag attributes to the content attributes // Add tag attributes to the content attributes
nsAutoString k, v; nsAutoString k, v;
@ -1113,12 +1108,8 @@ RDFContentSinkImpl::OpenObject(const nsIParserNode& aNode)
// Figure out the URI of this object, and create an RDF node for it. // Figure out the URI of this object, and create an RDF node for it.
nsresult rv; nsresult rv;
nsAutoString uri;
if (NS_FAILED(rv = GetIdAboutAttribute(aNode, uri)))
return rv;
nsIRDFResource* rdfResource; nsIRDFResource* rdfResource;
if (NS_FAILED(rv = mRDFService->GetUnicodeResource(uri, &rdfResource))) if (NS_FAILED(rv = GetIdAboutAttribute(aNode, &rdfResource)))
return rv; return rv;
// If we're in a member or property element, then this is the cue // If we're in a member or property element, then this is the cue
@ -1223,29 +1214,27 @@ RDFContentSinkImpl::OpenProperty(const nsIParserNode& aNode)
if (NS_FAILED(rv = mRDFService->GetUnicodeResource(ns, &rdfProperty))) if (NS_FAILED(rv = mRDFService->GetUnicodeResource(ns, &rdfProperty)))
return rv; return rv;
nsAutoString resourceURI; nsIRDFResource* rdfResource;
if (NS_SUCCEEDED(GetResourceAttribute(aNode, resourceURI))) { if (NS_SUCCEEDED(GetResourceAttribute(aNode, &rdfResource))) {
// They specified an inline resource for the value of this // They specified an inline resource for the value of this
// property. Create an RDF resource for the inline resource // property. Create an RDF resource for the inline resource
// URI, add the properties to it, and attach the inline // URI, add the properties to it, and attach the inline
// resource to its parent. // resource to its parent.
nsIRDFResource* rdfResource; if (NS_SUCCEEDED(rv = AddProperties(aNode, rdfResource))) {
if (NS_SUCCEEDED(rv = mRDFService->GetUnicodeResource(resourceURI, &rdfResource))) { rv = rdf_Assert(mDataSource,
if (NS_SUCCEEDED(rv = AddProperties(aNode, rdfResource))) { GetContextElement(0),
rv = rdf_Assert(mDataSource, rdfProperty,
GetContextElement(0), rdfResource);
rdfProperty,
rdfResource);
}
} }
// XXX ignore any failure from above... // XXX ignore any failure from above...
PR_ASSERT(rv == NS_OK); NS_ASSERTION(NS_SUCCEEDED(rv), "problem adding properties");
// XXX Technically, we should _not_ fall through here and push // XXX Technically, we should _not_ fall through here and push
// the element onto the stack: this is supposed to be a closed // the element onto the stack: this is supposed to be a closed
// node. But right now I'm lazy and the code will just Do The // node. But right now I'm lazy and the code will just Do The
// Right Thing so long as the RDF is well-formed. // Right Thing so long as the RDF is well-formed.
NS_RELEASE(rdfResource);
} }
// Push the element onto the context stack and change state. // Push the element onto the context stack and change state.
@ -1280,20 +1269,17 @@ RDFContentSinkImpl::OpenMember(const nsIParserNode& aNode)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
nsresult rv; nsresult rv;
nsAutoString resourceURI; nsIRDFResource* resource;
if (NS_SUCCEEDED(rv = GetResourceAttribute(aNode, resourceURI))) { if (NS_SUCCEEDED(rv = GetResourceAttribute(aNode, &resource))) {
// Okay, this node has an RDF:resource="..." attribute. That // Okay, this node has an RDF:resource="..." attribute. That
// means that it's a "referenced item," as covered in [6.29]. // means that it's a "referenced item," as covered in [6.29].
rv = rdf_ContainerAddElement(mDataSource, container, resource);
nsIRDFResource* resource;
if (NS_SUCCEEDED(rv = mRDFService->GetUnicodeResource(resourceURI, &resource))) {
rv = rdf_ContainerAddElement(mDataSource, container, resource);
}
// XXX Technically, we should _not_ fall through here and push // XXX Technically, we should _not_ fall through here and push
// the element onto the stack: this is supposed to be a closed // the element onto the stack: this is supposed to be a closed
// node. But right now I'm lazy and the code will just Do The // node. But right now I'm lazy and the code will just Do The
// Right Thing so long as the RDF is well-formed. // Right Thing so long as the RDF is well-formed.
NS_RELEASE(resource);
} }
// Change state. Pushing a null context element is a bit weird, // Change state. Pushing a null context element is a bit weird,

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

@ -31,10 +31,7 @@
open an arbitrary nsIOutputStream on *any* URL, and Netlib could open an arbitrary nsIOutputStream on *any* URL, and Netlib could
just do the magic. just do the magic.
2) This does not currently output RDF container constructs 2) Implement a more terse output for "typed" nodes; that is, instead
properly. To do this, we just need to implement SerializeContainer().
3) Implement a more terse output for "typed" nodes; that is, instead
of "RDF:Description RDF:type='ns:foo'", just output "ns:foo". of "RDF:Description RDF:type='ns:foo'", just output "ns:foo".
*/ */
@ -88,6 +85,13 @@ static NS_DEFINE_CID(kRDFContentSinkCID, NS_RDFCONTENTSINK_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID); static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID);
////////////////////////////////////////////////////////////////////////
// Vocabulary stuff
#include "rdf.h"
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, instanceOf);
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, nextVal);
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// FileOutputStreamImpl // FileOutputStreamImpl
@ -414,7 +418,11 @@ RDFXMLDataSourceImpl::RDFXMLDataSourceImpl(void)
// Initialize the name space stuff to know about any "standard" // Initialize the name space stuff to know about any "standard"
// namespaces that we want to look the same in all the RDF/XML we // namespaces that we want to look the same in all the RDF/XML we
// generate. // generate.
AddNameSpace(NS_NewAtom("RDF"), "http://www.w3.org/TR/WD-rdf-syntax#"); //
// XXX this is a bit of a hack, because technically, the document
// should've defined the RDF namespace to be _something_, and we
// should just look at _that_ and use it. Oh well.
AddNameSpace(NS_NewAtom("RDF"), RDF_NAMESPACE_URI);
} }
@ -1058,8 +1066,6 @@ RDFXMLDataSourceImpl::SerializeAssertion(nsIOutputStream* aStream,
rdf_BlockingWrite(aStream, "\"", 1); rdf_BlockingWrite(aStream, "\"", 1);
} }
rdf_BlockingWrite(aStream, ">", 1);
nsIRDFResource* resource; nsIRDFResource* resource;
nsIRDFLiteral* literal; nsIRDFLiteral* literal;
@ -1070,7 +1076,14 @@ RDFXMLDataSourceImpl::SerializeAssertion(nsIOutputStream* aStream,
nsAutoString escaped(uri); nsAutoString escaped(uri);
rdf_EscapeAmpersands(escaped); rdf_EscapeAmpersands(escaped);
const char* docURI;
mInner->GetURI(&docURI);
rdf_PossiblyMakeRelative(docURI, escaped);
rdf_BlockingWrite(aStream, " RDF:resource=\"");
rdf_BlockingWrite(aStream, escaped); rdf_BlockingWrite(aStream, escaped);
rdf_BlockingWrite(aStream, "\"/>\n", 4);
NS_RELEASE(resource); NS_RELEASE(resource);
} }
else if (NS_SUCCEEDED(aValue->QueryInterface(kIRDFLiteralIID, (void**) &literal))) { else if (NS_SUCCEEDED(aValue->QueryInterface(kIRDFLiteralIID, (void**) &literal))) {
@ -1081,7 +1094,11 @@ RDFXMLDataSourceImpl::SerializeAssertion(nsIOutputStream* aStream,
rdf_EscapeAmpersands(s); // do these first! rdf_EscapeAmpersands(s); // do these first!
rdf_EscapeAngleBrackets(s); rdf_EscapeAngleBrackets(s);
rdf_BlockingWrite(aStream, ">", 1);
rdf_BlockingWrite(aStream, s); rdf_BlockingWrite(aStream, s);
rdf_BlockingWrite(aStream, "</", 2);
rdf_BlockingWrite(aStream, tag);
rdf_BlockingWrite(aStream, ">\n", 2);
NS_RELEASE(literal); NS_RELEASE(literal);
} }
@ -1090,10 +1107,6 @@ RDFXMLDataSourceImpl::SerializeAssertion(nsIOutputStream* aStream,
NS_ASSERTION(PR_FALSE, "huh?"); NS_ASSERTION(PR_FALSE, "huh?");
} }
rdf_BlockingWrite(aStream, "</", 2);
rdf_BlockingWrite(aStream, tag);
rdf_BlockingWrite(aStream, ">\n", 2);
return NS_OK; return NS_OK;
} }
@ -1222,7 +1235,7 @@ RDFXMLDataSourceImpl::SerializeMember(nsIOutputStream* aStream,
if (NS_SUCCEEDED(rv = literal->GetValue(&value))) { if (NS_SUCCEEDED(rv = literal->GetValue(&value))) {
rdf_BlockingWrite(aStream, " <RDF:li>"); rdf_BlockingWrite(aStream, " <RDF:li>");
rdf_BlockingWrite(aStream, value); rdf_BlockingWrite(aStream, value);
rdf_BlockingWrite(aStream, " </RDF:li>\n"); rdf_BlockingWrite(aStream, "</RDF:li>\n");
} }
NS_RELEASE(literal); NS_RELEASE(literal);
} }
@ -1247,24 +1260,57 @@ nsresult
RDFXMLDataSourceImpl::SerializeContainer(nsIOutputStream* aStream, RDFXMLDataSourceImpl::SerializeContainer(nsIOutputStream* aStream,
nsIRDFResource* aContainer) nsIRDFResource* aContainer)
{ {
static const char kRDFOpenSeq[] = " <RDF:Seq RDF:ID=\""; static const char kRDFBag[] = "RDF:Bag";
static const char kRDFOpenBag[] = " <RDF:Bag RDF:ID=\""; static const char kRDFSeq[] = "RDF:Seq";
static const char kRDFOpenAlt[] = " <RDF:Alt RDF:ID=\""; static const char kRDFAlt[] = "RDF:Alt";
static const char kRDFCloseSeq[] = " </RDF:Seq>\n";
static const char kRDFCloseBag[] = " </RDF:Bag>\n";
static const char kRDFCloseAlt[] = " </RDF:Alt>\n";
nsresult rv; nsresult rv;
const char* tag;
// XXX decide if it's a sequence, bag, or alternation. Print // Decide if it's a sequence, bag, or alternation, and print the
// the appropriate tag-open sequence HERE. // appropriate tag-open sequence
if (rdf_IsBag(mInner, aContainer)) {
tag = kRDFBag;
}
else if (rdf_IsSeq(mInner, aContainer)) {
tag = kRDFSeq;
}
else if (rdf_IsAlt(mInner, aContainer)) {
tag = kRDFAlt;
}
else {
NS_ASSERTION(PR_FALSE, "huh? this is _not_ a container.");
return NS_ERROR_UNEXPECTED;
}
rdf_BlockingWrite(aStream, " <", 3);
rdf_BlockingWrite(aStream, tag);
// Unfortunately, we always need to print out the identity of the
// resource, even if was constructed "anonymously". We need to do
// this because we never really know who else might be referring
// to it...
const char* docURI;
mInner->GetURI(&docURI);
const char* s;
if (NS_SUCCEEDED(aContainer->GetValue(&s))) {
nsAutoString uri(s);
rdf_PossiblyMakeRelative(docURI, uri);
rdf_BlockingWrite(aStream, " RDF:ID=\"", 9);
rdf_BlockingWrite(aStream, uri);
rdf_BlockingWrite(aStream, "\"", 1);
}
rdf_BlockingWrite(aStream, ">\n", 2);
// XXX decide if it's an anonymous bag, or a named one. If it's
// named, then print out its identity HERE.
// We iterate through all of the arcs, in case someone has applied // We iterate through all of the arcs, in case someone has applied
// properties to the bag itself. // properties to the bag itself.
nsIRDFArcsOutCursor* arcs; nsIRDFArcsOutCursor* arcs;
if (NS_FAILED(rv = mInner->ArcLabelsOut(aContainer, &arcs))) if (NS_FAILED(rv = mInner->ArcLabelsOut(aContainer, &arcs)))
return rv; return rv;
@ -1281,9 +1327,26 @@ static const char kRDFCloseAlt[] = " </RDF:Alt>\n";
rv = SerializeMember(aStream, aContainer, property); rv = SerializeMember(aStream, aContainer, property);
} }
else { else {
rv = SerializeProperty(aStream, aContainer, property); do {
} PRBool eq;
// don't serialize RDF:instanceOf -- it's implicit in the tag
if (NS_FAILED(rv = property->EqualsString(kURIRDF_instanceOf, &eq)))
break;
if (eq)
break;
// don't serialize RDF:nextVal -- it's internal state
if (NS_FAILED(rv = property->EqualsString(kURIRDF_nextVal, &eq)))
break;
if (eq)
break;
rv = SerializeProperty(aStream, aContainer, property);
} while (0);
}
NS_RELEASE(property); NS_RELEASE(property);
if (NS_FAILED(rv)) if (NS_FAILED(rv))
@ -1294,6 +1357,13 @@ static const char kRDFCloseAlt[] = " </RDF:Alt>\n";
rv = NS_OK; rv = NS_OK;
NS_RELEASE(arcs); NS_RELEASE(arcs);
// close the container tag
rdf_BlockingWrite(aStream, " </", 4);
rdf_BlockingWrite(aStream, tag);
rdf_BlockingWrite(aStream, ">\n", 2);
return rv; return rv;
} }

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

@ -32,13 +32,13 @@
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsRDFCID.h" #include "nsRDFCID.h"
#include "nsString.h" #include "nsString.h"
#include "plstr.h"
#include "rdfutil.h" #include "rdfutil.h"
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// RDF core vocabulary // RDF core vocabulary
#include "rdf.h" #include "rdf.h"
#define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI; static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Alt); DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Alt);
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Bag); DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Bag);
@ -65,17 +65,56 @@ static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// XXX This'll permanently leak
static nsIRDFService* gRDFService = nsnull; static nsIRDFService* gRDFService = nsnull;
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;
static nsresult static nsresult
rdf_EnsureRDFService(void) rdf_EnsureRDFService(void)
{ {
if (gRDFService) if (gRDFService)
return NS_OK; return NS_OK;
return nsServiceManager::GetService(kRDFServiceCID, nsresult rv;
kIRDFServiceIID,
(nsISupports**) &gRDFService); if (NS_FAILED(rv = nsServiceManager::GetService(kRDFServiceCID,
kIRDFServiceIID,
(nsISupports**) &gRDFService)))
goto done;
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_instanceOf, &kRDF_instanceOf)))
goto done;
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_Bag, &kRDF_Bag)))
goto done;
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_Seq, &kRDF_Seq)))
goto done;
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_Alt, &kRDF_Alt)))
goto done;
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_nextVal, &kRDF_nextVal)))
goto done;
done:
if (NS_FAILED(rv)) {
NS_IF_RELEASE(kRDF_nextVal);
NS_IF_RELEASE(kRDF_Alt);
NS_IF_RELEASE(kRDF_Seq);
NS_IF_RELEASE(kRDF_Bag);
if (gRDFService) {
nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService);
gRDFService = nsnull;
}
}
return rv;
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -107,72 +146,70 @@ rdf_IsOrdinalProperty(const nsIRDFResource* property)
} }
// XXX This'll permanently leak RDF_Alt, RDF_Seq, RDF_Bag, and
// RDF_instanceOf. Since we do it a lot, it seems like it's worth it.
PRBool PRBool
rdf_IsContainer(nsIRDFDataSource* ds, rdf_IsContainer(nsIRDFDataSource* ds,
nsIRDFResource* resource) nsIRDFResource* resource)
{ {
PRBool result = PR_FALSE; if (rdf_IsBag(ds, resource) ||
rdf_IsSeq(ds, resource) ||
rdf_IsAlt(ds, resource)) {
return PR_TRUE;
}
else {
return PR_FALSE;
}
}
static nsIRDFResource* RDF_instanceOf = nsnull; PRBool
static nsIRDFResource* RDF_Bag = nsnull; rdf_IsBag(nsIRDFDataSource* aDataSource,
static nsIRDFResource* RDF_Seq = nsnull; nsIRDFResource* aResource)
static nsIRDFResource* RDF_Alt = nsnull; {
PRBool result = PR_FALSE;
nsresult rv; nsresult rv;
if (NS_FAILED(rv = rdf_EnsureRDFService())) if (NS_FAILED(rv = rdf_EnsureRDFService()))
goto done; goto done;
if (! RDF_instanceOf) { rv = aDataSource->HasAssertion(aResource, kRDF_instanceOf, kRDF_Bag, PR_TRUE, &result);
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_instanceOf, &RDF_instanceOf)))
goto done;
}
// bag?
if (! RDF_Bag) {
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_Bag, &RDF_Bag)))
goto done;
}
if (NS_FAILED(rv = ds->HasAssertion(resource, RDF_instanceOf, RDF_Bag, PR_TRUE, &result)))
goto done;
if (result)
goto done;
// sequence?
if (! RDF_Seq) {
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_Seq, &RDF_Seq)))
goto done;
}
if (NS_FAILED(rv = ds->HasAssertion(resource, RDF_instanceOf, RDF_Seq, PR_TRUE, &result)))
goto done;
if (result)
goto done;
// alternation?
if (! RDF_Alt) {
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_Alt, &RDF_Alt)))
goto done;
}
if (NS_FAILED(rv = ds->HasAssertion(resource, RDF_instanceOf, RDF_Alt, PR_TRUE, &result)))
goto done;
done: done:
// XXX permanent leak
//NS_IF_RELEASE(RDF_Alt);
//NS_IF_RELEASE(RDF_Seq);
//NS_IF_RELEASE(RDF_Bag);
//NS_IF_RELEASE(RDF_instanceOf);
return result; return result;
} }
PRBool
rdf_IsSeq(nsIRDFDataSource* aDataSource,
nsIRDFResource* aResource)
{
PRBool result = PR_FALSE;
nsresult rv;
if (NS_FAILED(rv = rdf_EnsureRDFService()))
goto done;
rv = aDataSource->HasAssertion(aResource, kRDF_instanceOf, kRDF_Seq, PR_TRUE, &result);
done:
return result;
}
PRBool
rdf_IsAlt(nsIRDFDataSource* aDataSource,
nsIRDFResource* aResource)
{
PRBool result = PR_FALSE;
nsresult rv;
if (NS_FAILED(rv = rdf_EnsureRDFService()))
goto done;
rv = aDataSource->HasAssertion(aResource, kRDF_instanceOf, kRDF_Alt, PR_TRUE, &result);
done:
return result;
}
// A complete hack that looks at the string value of a node and // A complete hack that looks at the string value of a node and
// guesses if it's a resource // guesses if it's a resource
static PRBool static PRBool
@ -377,20 +414,83 @@ rdf_Assert(nsIRDFDataSource* ds,
nsresult nsresult
rdf_CreateAnonymousResource(nsIRDFResource** result) rdf_CreateAnonymousResource(const nsString& aContextURI, nsIRDFResource** result)
{ {
static PRUint32 gCounter = 0; static PRUint32 gCounter = 0;
nsAutoString s = "$";
s.Append(++gCounter, 10);
nsresult rv; nsresult rv;
if (NS_FAILED(rv = rdf_EnsureRDFService())) if (NS_FAILED(rv = rdf_EnsureRDFService()))
return rv; return rv;
return gRDFService->GetUnicodeResource(s, result); do {
nsAutoString s(aContextURI);
s.Append('$');
s.Append(++gCounter, 10);
nsIRDFResource* resource;
if (NS_FAILED(rv = gRDFService->GetUnicodeResource(s, &resource)))
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) {
*result = resource;
break;
}
} while (1);
return NS_OK;
} }
PRBool
rdf_IsAnonymousResource(const nsString& aContextURI, nsIRDFResource* aResource)
{
nsresult rv;
const char* s;
if (NS_FAILED(rv = aResource->GetValue(&s))) {
NS_ASSERTION(PR_FALSE, "unable to get resource URI");
return PR_FALSE;
}
nsAutoString uri(s);
// 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]+"
if (uri[0] != '$')
return PR_FALSE;
for (PRInt32 i = uri.Length() - 1; i >= 1; --i) {
if (uri[i] < '0' || uri[i] > '9')
return PR_FALSE;
}
return PR_TRUE;
}
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());
return NS_OK;
}
nsresult nsresult
rdf_MakeBag(nsIRDFDataSource* ds, rdf_MakeBag(nsIRDFDataSource* ds,
nsIRDFResource* bag) nsIRDFResource* bag)
@ -466,7 +566,6 @@ rdf_ContainerGetNextValue(nsIRDFDataSource* ds,
if (NS_FAILED(rv = rdf_EnsureRDFService())) if (NS_FAILED(rv = rdf_EnsureRDFService()))
return rv; return rv;
nsIRDFResource* RDF_nextVal = nsnull;
nsIRDFNode* nextValNode = nsnull; nsIRDFNode* nextValNode = nsnull;
nsIRDFLiteral* nextValLiteral = nsnull; nsIRDFLiteral* nextValLiteral = nsnull;
const PRUnichar* s; const PRUnichar* s;
@ -476,10 +575,7 @@ rdf_ContainerGetNextValue(nsIRDFDataSource* ds,
// Get the next value, which hangs off of the bag via the // Get the next value, which hangs off of the bag via the
// RDF:nextVal property. // RDF:nextVal property.
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_nextVal, &RDF_nextVal))) if (NS_FAILED(rv = ds->GetTarget(container, kRDF_nextVal, PR_TRUE, &nextValNode)))
goto done;
if (NS_FAILED(rv = ds->GetTarget(container, RDF_nextVal, PR_TRUE, &nextValNode)))
goto done; goto done;
if (NS_FAILED(rv = nextValNode->QueryInterface(kIRDFLiteralIID, (void**) &nextValLiteral))) if (NS_FAILED(rv = nextValNode->QueryInterface(kIRDFLiteralIID, (void**) &nextValLiteral)))
@ -502,7 +598,7 @@ rdf_ContainerGetNextValue(nsIRDFDataSource* ds,
goto done; goto done;
// Now increment the RDF:nextVal property. // Now increment the RDF:nextVal property.
if (NS_FAILED(rv = ds->Unassert(container, RDF_nextVal, nextValLiteral))) if (NS_FAILED(rv = ds->Unassert(container, kRDF_nextVal, nextValLiteral)))
goto done; goto done;
NS_RELEASE(nextValLiteral); NS_RELEASE(nextValLiteral);
@ -514,13 +610,12 @@ rdf_ContainerGetNextValue(nsIRDFDataSource* ds,
if (NS_FAILED(rv = gRDFService->GetLiteral(nextValStr, &nextValLiteral))) if (NS_FAILED(rv = gRDFService->GetLiteral(nextValStr, &nextValLiteral)))
goto done; goto done;
if (NS_FAILED(rv = rdf_Assert(ds, container, RDF_nextVal, nextValLiteral))) if (NS_FAILED(rv = rdf_Assert(ds, container, kRDF_nextVal, nextValLiteral)))
goto done; goto done;
done: done:
NS_IF_RELEASE(nextValLiteral); NS_IF_RELEASE(nextValLiteral);
NS_IF_RELEASE(nextValNode); NS_IF_RELEASE(nextValNode);
NS_IF_RELEASE(RDF_nextVal);
return rv; return rv;
} }

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

@ -53,6 +53,17 @@ PR_EXTERN(PRBool)
rdf_IsContainer(nsIRDFDataSource* db, rdf_IsContainer(nsIRDFDataSource* db,
nsIRDFResource* resource); nsIRDFResource* resource);
PR_EXTERN(PRBool)
rdf_IsBag(nsIRDFDataSource* aDataSource,
nsIRDFResource* aResource);
PR_EXTERN(PRBool)
rdf_IsSeq(nsIRDFDataSource* aDataSource,
nsIRDFResource* aResource);
PR_EXTERN(PRBool)
rdf_IsAlt(nsIRDFDataSource* aDataSource,
nsIRDFResource* aResource);
/** /**
* Various utilities routines for making assertions in a data source * Various utilities routines for making assertions in a data source
@ -105,8 +116,20 @@ rdf_Assert(nsIRDFDataSource* ds,
* resource URI. * resource URI.
*/ */
PR_EXTERN(nsresult) PR_EXTERN(nsresult)
rdf_CreateAnonymousResource(nsIRDFResource** result); rdf_CreateAnonymousResource(const nsString& aContextURI, nsIRDFResource** result);
/**
* Determine if a resource is an "anonymous" resource that we've constructed
* ourselves.
*/
PR_EXTERN(PRBool)
rdf_IsAnonymousResource(const nsString& aContextURI, nsIRDFResource* aResource);
/**
* Try to convert the absolute URL into a relative URL.
*/
PR_EXTERN(nsresult)
rdf_PossiblyMakeRelative(const nsString& aContextURI, nsString& aURI);
/** /**
* Create a bag resource. * Create a bag resource.

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

@ -1658,8 +1658,8 @@ RDFDocumentImpl::IsTreeProperty(nsIRDFResource* aProperty, PRBool* aResult) cons
const char* p; const char* p;
aProperty->GetValue(&p); aProperty->GetValue(&p);
nsAutoString s(p); nsAutoString s(p);
if (s.Equals("http://home.netscape.com/NC-rdf#child") || if (s.Equals(NC_NAMESPACE_URI "child") ||
s.Equals("http://home.netscape.com/NC-rdf#Folder")) { s.Equals(NC_NAMESPACE_URI "Folder")) {
*aResult = PR_TRUE; *aResult = PR_TRUE;
return NS_OK; return NS_OK;
} }

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

@ -45,7 +45,6 @@
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#"
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Columns); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Columns);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Column); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Column);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Title); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Title);

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

@ -47,7 +47,6 @@ static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static const char kURINC_BookmarksRoot[] = "NC:BookmarksRoot"; // XXX? static const char kURINC_BookmarksRoot[] = "NC:BookmarksRoot"; // XXX?
#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#"
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, child); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, child);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, BookmarkAddDate); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, BookmarkAddDate);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Description); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Description);
@ -55,13 +54,9 @@ DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Folder);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, PersonalToolbarFolderCategory); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, PersonalToolbarFolderCategory);
#define WEB_NAMESPACE_URI "http://home.netscape.com/WEB-rdf#"
DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastVisitDate); DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastVisitDate);
DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastModifiedDate); DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastModifiedDate);
#define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, instanceOf); DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, instanceOf);
static const char kPersonalToolbar[] = "Personal Toolbar"; static const char kPersonalToolbar[] = "Personal Toolbar";

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

@ -62,7 +62,6 @@ static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID)
static const char kURIHistoryRoot[] = "HistoryRoot"; static const char kURIHistoryRoot[] = "HistoryRoot";
#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#"
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, child); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, child);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Folder); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Folder);
@ -70,7 +69,6 @@ DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Column);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Columns); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Columns);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Title); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Title);
#define WEB_NAMESPACE_URI "http://home.netscape.com/WEB-rdf#"
DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastVisitDate); DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastVisitDate);
DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastModifiedDate); DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastModifiedDate);

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

@ -110,7 +110,6 @@ static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
static const char kURINC_MailRoot[] = "NC:MailRoot"; static const char kURINC_MailRoot[] = "NC:MailRoot";
#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#"
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, child); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, child);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, subject); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, subject);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, from); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, from);

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

@ -209,7 +209,7 @@ main(int argc, char** argv)
if (NS_FAILED(rv = theRDFService->GetResource("http://home.netscape.com", &theHomePage))) if (NS_FAILED(rv = theRDFService->GetResource("http://home.netscape.com", &theHomePage)))
goto done; goto done;
if (NS_FAILED(rv = theRDFService->GetResource("http://home.nescape.com/NC-rdf#title", &NC_title))) if (NS_FAILED(rv = theRDFService->GetResource(NC_NAMESPACE_URI "title", &NC_title)))
goto done; goto done;
if (NS_FAILED(rv = theRDFService->GetLiteral(nsAutoString("Netscape's Home Page"), &theTitle))) if (NS_FAILED(rv = theRDFService->GetLiteral(nsAutoString("Netscape's Home Page"), &theTitle)))