Improved namespace handling for output of RDF/XML streams. Modified basic data source interface to include GetAllResources(), which enumerates all of the resources in the datasource. Moved code for dumping an RDF/XML stream out of nsInMemoryDataSource into nsRDFXMLDataSource.

This commit is contained in:
waterson%netscape.com 1999-01-21 22:24:32 +00:00
parent 80feb5b0f9
commit aea6df3ac4
14 changed files with 909 additions and 352 deletions

View File

@ -19,7 +19,8 @@
/*
Interfaces for RDF cursors, including nsIRDFCursor,
nsIRDFAssertionCursor, nsIRDFArcsInCursor, and nsIRDFArcsOutCursor.
nsIRDFAssertionCursor, nsIRDFArcsInCursor, nsIRDFArcsOutCursor,
nad nsIRDFResourceCursor.
*/
@ -122,12 +123,6 @@ public:
* @return NS_OK, unless a catastrophic error occurs.
*/
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) = 0;
/**
* Retrieve the truth value of the arc.
* @return NS_OK, unless a catastrophic error occurs.
* xxx rvg --- truth value doesn't make sense here.
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) = 0;
*/
};
@ -154,14 +149,20 @@ public:
* @return NS_OK, unless a catastrophic error occurs.
*/
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) = 0;
/**
* Retrieve the truth value of the arc.
* @return NS_OK, unless a catastrophic error occurs.
* xxx rvg --- truth value doesn't make sense here.
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) = 0;
*/
};
// {C2850C10-B0CF-11d2-A684-00104BDE6048}
#define NS_IRDFRESOURCECURSOR_IID \
{ 0xc2850c10, 0xb0cf, 0x11d2, { 0xa6, 0x84, 0x0, 0x10, 0x4b, 0xde, 0x60, 0x48 } }
/**
* A cursor that enumerates all of the resources in a data source.
*/
class nsIRDFResourceCursor : public nsIRDFCursor {
public:
NS_IMETHOD GetResource(nsIRDFResource** aResource) = 0;
};
#endif /* nsIRDFCursor_h__ */

View File

@ -39,6 +39,7 @@ class nsIRDFDataBase;
class nsIRDFNode;
class nsIRDFObserver;
class nsIRDFResource;
class nsIRDFResourceCursor;
/**
* An RDF data source.
@ -171,6 +172,12 @@ public:
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
nsIRDFArcsOutCursor** labels /* out */) = 0;
/**
* Retrieve all of the resources that the data source currently
* refers to.
*/
NS_IMETHOD GetAllResources(nsIRDFResourceCursor** aCursor) = 0;
/**
* Request that a data source write it's contents out to
* permanent storage if applicable.

View File

@ -31,8 +31,10 @@
#define nsIRDFXMLDataSource_h__
#include "nsIRDFDataSource.h"
class nsIAtom;
class nsIOutputStream;
class nsIURL;
class nsString;
// {EB1A5D30-AB33-11d2-8EC6-00805F29F370}
#define NS_IRDFXMLDOCUMENTOBSERVER_IID \
@ -163,6 +165,11 @@ public:
*/
NS_IMETHOD GetNamedDataSourceURIs(const char* const** aNamedDataSourceURIs, PRInt32* aCount) = 0;
/**
* Add a new namespace declaration to the RDF/XML document.
*/
NS_IMETHOD AddNameSpace(nsIAtom* aPrefix, const nsString& aURI) = 0;
/**
* Add an observer to the document. The observer will be notified of
* RDF/XML events via the nsIRDFXMLDataSourceObserver interface. Note that
@ -174,7 +181,6 @@ public:
* Remove an observer from the document.
*/
NS_IMETHOD RemoveXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver) = 0;
};

View File

@ -126,6 +126,8 @@ public:
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
nsIRDFArcsOutCursor** labels);
NS_IMETHOD GetAllResources(nsIRDFResourceCursor** aCursor);
NS_IMETHOD Flush();
NS_IMETHOD IsCommandEnabled(const char* aCommand,
@ -765,6 +767,13 @@ CompositeDataSourceImpl::ArcLabelsOut(nsIRDFResource* source,
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::GetAllResources(nsIRDFResourceCursor** aCursor)
{
NS_ASSERTION(PR_FALSE, "not implemented");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
CompositeDataSourceImpl::Flush()
{

View File

@ -37,7 +37,6 @@
#include "nsIRDFDataSource.h"
#include "nsIRDFNode.h"
#include "nsIRDFObserver.h"
#include "nsIRDFXMLSource.h"
#include "nsIServiceManager.h"
#include "nsVoidArray.h" // XXX introduces dependency on raptorbase
#include "nsRDFCID.h"
@ -54,7 +53,7 @@ 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);
static NS_DEFINE_IID(kIRDFXMLSourceIID, NS_IRDFXMLSOURCE_IID);
static NS_DEFINE_IID(kIRDFResourceCursorIID, NS_IRDFRESOURCECURSOR_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
enum Direction {
@ -96,48 +95,12 @@ rdf_CompareNodes(const void* v1, const void* v2)
return (PRIntn) result;
}
static nsresult
rdf_BlockingWrite(nsIOutputStream* stream, const char* buf, PRUint32 size)
{
PRUint32 written = 0;
PRUint32 remaining = size;
while (remaining > 0) {
nsresult rv;
PRUint32 cb;
if (NS_FAILED(rv = stream->Write(buf, written, remaining, &cb)))
return rv;
written += cb;
remaining -= cb;
}
return NS_OK;
}
static nsresult
rdf_BlockingWrite(nsIOutputStream* stream, const nsString& s)
{
char buf[256];
char* p = buf;
if (s.Length() >= sizeof(buf))
p = new char[s.Length() + 1];
nsresult rv = rdf_BlockingWrite(stream, s.ToCString(p, s.Length() + 1), s.Length());
if (p != buf)
delete[](p);
return rv;
}
////////////////////////////////////////////////////////////////////////
// InMemoryDataSource
class InMemoryResourceCursor;
class InMemoryDataSource : public nsIRDFDataSource,
public nsIRDFXMLSource
class InMemoryDataSource : public nsIRDFDataSource
{
protected:
char* mURL;
@ -154,6 +117,8 @@ protected:
static const PRInt32 kInitialTableSize;
friend class InMemoryResourceCursor; // b/c it needs to enumerate mForwardArcs
public:
InMemoryDataSource(void);
virtual ~InMemoryDataSource(void);
@ -211,6 +176,8 @@ public:
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
nsIRDFArcsOutCursor** labels);
NS_IMETHOD GetAllResources(nsIRDFResourceCursor** aCursor);
NS_IMETHOD Flush();
NS_IMETHOD IsCommandEnabled(const char* aCommand,
@ -220,9 +187,6 @@ public:
NS_IMETHOD DoCommand(const char* aCommand,
nsIRDFResource* aCommandTarget);
// nsIRDFXMLSource methods
NS_IMETHOD Serialize(nsIOutputStream* aStream);
// Implemenatation methods
Assertion* GetForwardArcs(nsIRDFResource* u);
Assertion* GetReverseArcs(nsIRDFNode* v);
@ -269,10 +233,10 @@ public:
// nsIRDFCursor interface
NS_IMETHOD Advance(void);
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource);
NS_IMETHOD GetValue(nsIRDFNode** aValue);
// nsIRDFAssertionCursor interface
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource);
NS_IMETHOD GetSubject(nsIRDFResource** aResource);
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate);
NS_IMETHOD GetObject(nsIRDFNode** aObject);
@ -489,10 +453,10 @@ public:
// nsIRDFCursor interface
NS_IMETHOD Advance(void);
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource);
NS_IMETHOD GetValue(nsIRDFNode** aValue);
// nsIRDFArcsOutCursor interface
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource);
NS_IMETHOD GetSubject(nsIRDFResource** aSubject);
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate);
NS_IMETHOD GetTruthValue(PRBool* aTruthValue);
@ -682,6 +646,127 @@ InMemoryArcsCursor::GetTruthValue(PRBool* aTruthValue)
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
// 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)
{
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;
}
////////////////////////////////////////////////////////////////////////
// InMemoryDataSource
@ -700,11 +785,6 @@ InMemoryDataSource::QueryInterface(REFNSIID iid, void** result)
NS_ADDREF(this);
return NS_OK;
}
else if (iid.Equals(kIRDFXMLSourceIID)) {
*result = NS_STATIC_CAST(nsIRDFXMLSource*, this);
NS_ADDREF(this);
return NS_OK;
}
else {
*result = nsnull;
return NS_NOINTERFACE;
@ -1152,6 +1232,24 @@ InMemoryDataSource::ArcLabelsOut(nsIRDFResource* source, nsIRDFArcsOutCursor** l
return NS_OK;
}
NS_IMETHODIMP
InMemoryDataSource::GetAllResources(nsIRDFResourceCursor** aCursor)
{
NS_PRECONDITION(aCursor != nsnull, "null ptr");
if (! aCursor)
return NS_ERROR_NULL_POINTER;
InMemoryResourceCursor* result =
new InMemoryResourceCursor(this);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
*aCursor = result;
NS_ADDREF(result);
return NS_OK;
}
NS_IMETHODIMP
InMemoryDataSource::Flush()
{
@ -1174,220 +1272,6 @@ InMemoryDataSource::DoCommand(const char* aCommand,
return NS_OK;
}
// XXX This is a total kludge that takes a property resource (like
// "http://www.w3.org/TR/WD-rdf-syntax#Description") and converts it
// into a property ("Description"), a namespace prefix ("RDF"), and a
// namespace URI ("http://www.w3.org/TR/WD-rdf-syntax#").
//
// It should really do this by looking at some feature of the document
// or something. The stuff it spits out is valid, but probably pretty
// damn illegible and verbose. It generates a new, unique namespace
// identifier for every qualified name.
//
// How To Fix It.
//
// 1) We could improve this by refactoring the code between
// nsRDFDocument, nsRDFContentSink, and nsMemoryDataSource: this is
// probably The Right Thing To Do, but it's a lot of work and may even
// involve writing an RDF DTD processer in mozilla/htmlparser. At a
// minimum, it involves keeping track of namespace URIs and
// identifiers as they appear in the document, and maybe even
// implementing an nsIRDFProperty subclass that can tell you the
// difference between a the namespace URI and the unqualified
// property.
//
// 2) Alternatively, we could do a quick n' dirty hack where we grovel
// through all the properties in the data source, guess what the
// namespace URI prefixes are, sort-unique on the namespace prefixes,
// assign unique namespace identifiers to each, and then make a second
// pass where we write everything out.
//
// 3) Even worse, we could just hard-code in a couple of well-known
// namespaces (e.g., the Netscape vocabulary), and punt on all the
// rest.
//
// 4) Another idea might be to pass in a "namespace identifier set" to
// the Serialize() method. Then, any namespace prefix that you find in
// the set can be written up-front, and any namespace prefix that you
// don't find, you just generate. This is probably the easiest thing
// to do...
static void
rdf_MakeQName(nsIRDFResource* resource,
nsString& property,
nsString& nameSpacePrefix,
nsString& nameSpaceURI)
{
const char* uri;
resource->GetValue(&uri);
PRInt32 index;
nameSpaceURI = uri;
index = nameSpaceURI.RFind('#'); // first try a '#'
if (index == -1) {
index = nameSpaceURI.RFind('/');
if (index == -1) {
// Okay, just punt and assume there is _no_ namespace on
// this thing...
nameSpaceURI.Truncate();
nameSpacePrefix.Truncate();
property = uri;
return;
}
}
// Take whatever is to the right of the '#' and call it the
// property.
property.Truncate();
nameSpaceURI.Right(property, nameSpaceURI.Length() - (index + 1));
// Truncate the namespace URI down to the string up to and
// including the '#'.
nameSpaceURI.Truncate(index + 1);
// XXX hack any common prefixes here
if (nameSpaceURI.Equals("http://www.w3.org/TR/WD-rdf-syntax#")) {
nameSpacePrefix = "RDF";
}
else {
// Just generate a random prefix
static PRInt32 gPrefixID = 0;
nameSpacePrefix = "NS";
nameSpacePrefix.Append(++gPrefixID, 10);
}
}
// convert '<' and '>' into '&lt;' and '&gt', respectively.
static void
rdf_EscapeAngleBrackets(nsString& s)
{
PRInt32 index;
while ((index = s.Find('<')) != -1) {
s[index] = '&';
s.Insert(nsAutoString("lt;"), index + 1);
}
while ((index = s.Find('>')) != -1) {
s[index] = '&';
s.Insert(nsAutoString("gt;"), index + 1);
}
}
static void
rdf_EscapeAmpersands(nsString& s)
{
PRInt32 index = 0;
while ((index = s.Find('&', index)) != -1) {
s[index] = '&';
s.Insert(nsAutoString("amp;"), index + 1);
index += 4;
}
}
static PRIntn
rdf_SerializeEnumerator(PLHashEntry* he, PRIntn index, void* closure)
{
nsIOutputStream* stream = NS_STATIC_CAST(nsIOutputStream*, closure);
nsIRDFResource* node =
NS_CONST_CAST(nsIRDFResource*, NS_STATIC_CAST(const nsIRDFResource*, he->key));
const char* s;
node->GetValue(&s);
static const char kRDFDescription1[] = " <RDF:Description RDF:about=\"";
static const char kRDFDescription2[] = "\">\n";
nsAutoString escaped(s);
rdf_EscapeAmpersands(escaped);
rdf_BlockingWrite(stream, kRDFDescription1, sizeof(kRDFDescription1) - 1);
rdf_BlockingWrite(stream, escaped);
rdf_BlockingWrite(stream, kRDFDescription2, sizeof(kRDFDescription2) - 1);
for (Assertion* as = (Assertion*) he->value; as != nsnull; as = as->mNext) {
nsAutoString property, nameSpacePrefix, nameSpaceURI;
nsAutoString tag;
rdf_MakeQName(as->mProperty, property, nameSpacePrefix, nameSpaceURI);
if (nameSpacePrefix.Length()) {
tag.Append(nameSpacePrefix);
tag.Append(':');
}
tag.Append(property);
rdf_BlockingWrite(stream, " <", 5);
rdf_BlockingWrite(stream, tag);
if (nameSpacePrefix.Length()) {
rdf_BlockingWrite(stream, " xmlns:", 7);
rdf_BlockingWrite(stream, nameSpacePrefix);
rdf_BlockingWrite(stream, "=\"", 2);
rdf_BlockingWrite(stream, nameSpaceURI);
rdf_BlockingWrite(stream, "\"");
}
rdf_BlockingWrite(stream, ">", 1);
nsIRDFResource* resource;
nsIRDFLiteral* literal;
if (NS_SUCCEEDED(as->mTarget->QueryInterface(kIRDFResourceIID, (void**) &resource))) {
const char* uri;
resource->GetValue(&uri);
nsAutoString escaped(uri);
rdf_EscapeAmpersands(escaped);
rdf_BlockingWrite(stream, escaped);
NS_RELEASE(resource);
}
else if (NS_SUCCEEDED(as->mTarget->QueryInterface(kIRDFLiteralIID, (void**) &literal))) {
const PRUnichar* value;
literal->GetValue(&value);
nsAutoString s(value);
rdf_EscapeAmpersands(s); // do these first!
rdf_EscapeAngleBrackets(s);
rdf_BlockingWrite(stream, s);
NS_RELEASE(literal);
}
else {
PR_ASSERT(0);
}
rdf_BlockingWrite(stream, "</", 2);
rdf_BlockingWrite(stream, tag);
rdf_BlockingWrite(stream, ">\n", 2);
}
static const char kRDFDescription3[] = " </RDF:Description>\n";
rdf_BlockingWrite(stream, kRDFDescription3, sizeof(kRDFDescription3) - 1);
return HT_ENUMERATE_NEXT;
}
NS_IMETHODIMP
InMemoryDataSource::Serialize(nsIOutputStream* aStream)
{
static const char kOpenRDF[] = "<RDF:RDF xmlns:RDF=\"http://www.w3.org/TR/WD-rdf-syntax#\">\n";
static const char kCloseRDF[] = "</RDF:RDF>\n";
nsresult rv;
if (NS_FAILED(rv = rdf_BlockingWrite(aStream, kOpenRDF, sizeof(kOpenRDF) - 1)))
return rv;
PL_HashTableEnumerateEntries(mForwardArcs, rdf_SerializeEnumerator, aStream);
if (NS_FAILED(rv = rdf_BlockingWrite(aStream, kCloseRDF, sizeof(kCloseRDF) - 1)))
return rv;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////

View File

@ -1421,7 +1421,7 @@ RDFContentSinkImpl::PushNameSpacesFrom(const nsIParserNode& aNode)
// Get the attribute value (the URI for the namespace)
uri = aNode.GetValueAt(i);
rdf_StripAndConvert(uri);
// Open a local namespace
nsIAtom* prefixAtom = ((0 < prefix.Length()) ? NS_NewAtom(prefix) : nsnull);
nsINameSpace* child = nsnull;
@ -1430,6 +1430,10 @@ RDFContentSinkImpl::PushNameSpacesFrom(const nsIParserNode& aNode)
NS_RELEASE(nameSpace);
nameSpace = child;
}
// Add it to the set of namespaces used in the RDF/XML document.
mDataSource->AddNameSpace(prefixAtom, uri);
NS_IF_RELEASE(prefixAtom);
}
}

View File

@ -24,20 +24,18 @@
TO DO
-----
1) Right now, the only kind of stream data sources that are writable
are "file:" URIs. (In fact, <em>all</em> "file:" URIs are
writable, modulo flie system permissions; this may lead to some
surprising behavior.) Eventually, it'd be great if we could open
an arbitrary nsIOutputStream on *any* URL, and Netlib could just
do the magic.
1) Right now, the only kind of stream data sources that are _really_
writable are "file:" URIs. (In fact, <em>all</em> "file:" URIs
are writable, modulo flie system permissions; this may lead to
some surprising behavior.) Eventually, it'd be great if we could
open an arbitrary nsIOutputStream on *any* URL, and Netlib could
just do the magic.
2) We need a way to decide whether or not the stream should be read
with a blocking read or an asynchronous read. This issue is
particularly important for consumers that expect to be able to
Init() a data source and then have it be 100% ready for use
(e.g., the regsitry). Does this warrant a new interface? Right
now, we just assume that "file:" and "resource:" URIs should be
read synchronously.
2) This does not currently output RDF container constructs
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".
*/
@ -64,6 +62,7 @@
#include "plstr.h"
#include "prio.h"
#include "prthread.h"
#include "rdfutil.h"
////////////////////////////////////////////////////////////////////////
@ -72,8 +71,10 @@ static NS_DEFINE_IID(kIInputStreamIID, NS_IINPUTSTREAM_IID);
static NS_DEFINE_IID(kINameSpaceManagerIID, NS_INAMESPACEMANAGER_IID);
static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
static NS_DEFINE_IID(kIParserIID, NS_IPARSER_IID);
static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID);
static NS_DEFINE_IID(kIRDFContentSinkIID, NS_IRDFCONTENTSINK_IID);
static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID);
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
static NS_DEFINE_IID(kIRDFXMLDataSourceIID, NS_IRDFXMLDATASOURCE_IID);
static NS_DEFINE_IID(kIRDFXMLSourceIID, NS_IRDFXMLSOURCE_IID);
@ -90,6 +91,9 @@ static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID);
////////////////////////////////////////////////////////////////////////
// FileOutputStreamImpl
// XXX Eventually, it'd be nice if we could just open an output stream
// on a URL. That'd obsolete the need for this...
class FileOutputStreamImpl : public nsIOutputStream
{
private:
@ -198,6 +202,12 @@ class RDFXMLDataSourceImpl : public nsIRDFXMLDataSource,
public nsIRDFXMLSource
{
protected:
struct NameSpaceMap {
nsString URI;
nsIAtom* Prefix;
NameSpaceMap* Next;
};
nsIRDFDataSource* mInner;
PRBool mIsSynchronous; // true if the document should be loaded synchronously
PRBool mIsWritable; // true if the document can be written back
@ -209,6 +219,7 @@ protected:
PRInt32 mNumCSSStyleSheetURLs;
nsIRDFResource* mRootResource;
PRBool mIsLoading; // true while the document is loading
NameSpaceMap* mNameSpaces;
public:
RDFXMLDataSourceImpl(void);
@ -287,6 +298,10 @@ public:
return mInner->ArcLabelsOut(source, labels);
}
NS_IMETHOD GetAllResources(nsIRDFResourceCursor** aCursor) {
return mInner->GetAllResources(aCursor);
}
NS_IMETHOD Flush(void);
NS_IMETHOD IsCommandEnabled(const char* aCommand,
@ -317,11 +332,47 @@ public:
NS_IMETHOD GetNamedDataSourceURIs(const char* const** aNamedDataSourceURIs, PRInt32* aCount);
NS_IMETHOD AddXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver);
NS_IMETHOD RemoveXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver);
NS_IMETHOD AddNameSpace(nsIAtom* aPrefix, const nsString& aURI);
// nsIRDFXMLSource interface
NS_IMETHOD Serialize(nsIOutputStream* aStream);
// Implementation methods
PRBool
MakeQName(nsIRDFResource* aResource,
nsString& property,
nsString& nameSpacePrefix,
nsString& nameSpaceURI);
nsresult
SerializeAssertion(nsIOutputStream* aStream,
nsIRDFResource* aResource,
nsIRDFResource* aProperty,
nsIRDFNode* aValue);
nsresult
SerializeProperty(nsIOutputStream* aStream,
nsIRDFResource* aResource,
nsIRDFResource* aProperty);
nsresult
SerializeDescription(nsIOutputStream* aStream,
nsIRDFResource* aResource);
nsresult
SerializeMember(nsIOutputStream* aStream,
nsIRDFResource* aContainer,
nsIRDFResource* aProperty);
nsresult
SerializeContainer(nsIOutputStream* aStream,
nsIRDFResource* aContainer);
nsresult
SerializePrologue(nsIOutputStream* aStream);
nsresult
SerializeEpilogue(nsIOutputStream* aStream);
};
@ -348,7 +399,8 @@ RDFXMLDataSourceImpl::RDFXMLDataSourceImpl(void)
mNumNamedDataSourceURIs(0),
mCSSStyleSheetURLs(nsnull),
mNumCSSStyleSheetURLs(0),
mIsLoading(PR_FALSE)
mIsLoading(PR_FALSE),
mNameSpaces(nsnull)
{
nsresult rv;
if (NS_FAILED(rv = nsRepository::CreateInstance(kRDFInMemoryDataSourceCID,
@ -358,6 +410,11 @@ RDFXMLDataSourceImpl::RDFXMLDataSourceImpl(void)
PR_ASSERT(0);
NS_INIT_REFCNT();
// Initialize the name space stuff to know about any "standard"
// namespaces that we want to look the same in all the RDF/XML we
// generate.
AddNameSpace(NS_NewAtom("RDF"), "http://www.w3.org/TR/WD-rdf-syntax#");
}
@ -382,6 +439,14 @@ RDFXMLDataSourceImpl::~RDFXMLDataSourceImpl(void)
NS_RELEASE(mCSSStyleSheetURLs[mNumCSSStyleSheetURLs]);
delete mCSSStyleSheetURLs;
while (mNameSpaces) {
NameSpaceMap* doomed = mNameSpaces;
mNameSpaces = mNameSpaces->Next;
NS_RELEASE(doomed->Prefix);
delete doomed;
}
}
@ -818,20 +883,499 @@ RDFXMLDataSourceImpl::RemoveXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObse
}
NS_IMETHODIMP
RDFXMLDataSourceImpl::AddNameSpace(nsIAtom* aPrefix, const nsString& aURI)
{
NameSpaceMap* entry;
// ensure that URIs are unique
for (entry = mNameSpaces; entry != nsnull; entry = entry->Next) {
if (aURI.Equals(entry->URI))
return NS_OK;
}
// okay, it's a new one: let's add it.
entry = new NameSpaceMap;
if (! entry)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(aPrefix);
entry->Prefix = aPrefix;
entry->URI = aURI;
entry->Next = mNameSpaces;
mNameSpaces = entry;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
// nsIRDFXMLSource methods
NS_IMETHODIMP
RDFXMLDataSourceImpl::Serialize(nsIOutputStream* stream)
static nsresult
rdf_BlockingWrite(nsIOutputStream* stream, const char* buf, PRUint32 size)
{
nsresult rv;
nsIRDFXMLSource* source;
if (NS_SUCCEEDED(rv = mInner->QueryInterface(kIRDFXMLSourceIID, (void**) &source))) {
rv = source->Serialize(stream);
NS_RELEASE(source);
PRUint32 written = 0;
PRUint32 remaining = size;
while (remaining > 0) {
nsresult rv;
PRUint32 cb;
if (NS_FAILED(rv = stream->Write(buf, written, remaining, &cb)))
return rv;
written += cb;
remaining -= cb;
}
return NS_OK;
}
static nsresult
rdf_BlockingWrite(nsIOutputStream* stream, const nsString& s)
{
char buf[256];
char* p = buf;
if (s.Length() >= sizeof(buf))
p = new char[s.Length() + 1];
nsresult rv = rdf_BlockingWrite(stream, s.ToCString(p, s.Length() + 1), s.Length());
if (p != buf)
delete[](p);
return rv;
}
// This converts a property resource (like
// "http://www.w3.org/TR/WD-rdf-syntax#Description") into a property
// ("Description"), a namespace prefix ("RDF"), and a namespace URI
// ("http://www.w3.org/TR/WD-rdf-syntax#").
PRBool
RDFXMLDataSourceImpl::MakeQName(nsIRDFResource* resource,
nsString& property,
nsString& nameSpacePrefix,
nsString& nameSpaceURI)
{
const char* s;
resource->GetValue(&s);
nsAutoString uri(s);
for (NameSpaceMap* entry = mNameSpaces; entry != nsnull; entry = entry->Next) {
if (uri.Find(entry->URI) == 0) {
nameSpaceURI = entry->URI;
entry->Prefix->ToString(nameSpacePrefix);
uri.Right(property, uri.Length() - nameSpaceURI.Length());
return PR_TRUE;
}
}
// Okay, so we don't have it in our map. Try to make one up.
PRInt32 index = uri.RFind('#'); // first try a '#'
if (index == -1) {
index = uri.RFind('/');
if (index == -1) {
// Okay, just punt and assume there is _no_ namespace on
// this thing...
NS_ASSERTION(PR_FALSE, "couldn't find reasonable namespace prefix");
nameSpaceURI.Truncate();
nameSpacePrefix.Truncate();
property = uri;
return PR_TRUE;
}
}
// Take whatever is to the right of the '#' and call it the
// property.
property.Truncate();
nameSpaceURI.Right(property, uri.Length() - (index + 1));
// Truncate the namespace URI down to the string up to and
// including the '#'.
nameSpaceURI = uri;
nameSpaceURI.Truncate(index + 1);
// Just generate a random prefix
static PRInt32 gPrefixID = 0;
nameSpacePrefix = "NS";
nameSpacePrefix.Append(++gPrefixID, 10);
return PR_FALSE;
}
// convert '<' and '>' into '&lt;' and '&gt', respectively.
static void
rdf_EscapeAngleBrackets(nsString& s)
{
PRInt32 index;
while ((index = s.Find('<')) != -1) {
s[index] = '&';
s.Insert(nsAutoString("lt;"), index + 1);
}
while ((index = s.Find('>')) != -1) {
s[index] = '&';
s.Insert(nsAutoString("gt;"), index + 1);
}
}
static void
rdf_EscapeAmpersands(nsString& s)
{
PRInt32 index = 0;
while ((index = s.Find('&', index)) != -1) {
s[index] = '&';
s.Insert(nsAutoString("amp;"), index + 1);
index += 4;
}
}
nsresult
RDFXMLDataSourceImpl::SerializeAssertion(nsIOutputStream* aStream,
nsIRDFResource* aResource,
nsIRDFResource* aProperty,
nsIRDFNode* aValue)
{
nsAutoString property, nameSpacePrefix, nameSpaceURI;
nsAutoString tag;
PRBool wasDefinedAtGlobalScope =
MakeQName(aProperty, property, nameSpacePrefix, nameSpaceURI);
if (nameSpacePrefix.Length()) {
tag.Append(nameSpacePrefix);
tag.Append(':');
}
tag.Append(property);
rdf_BlockingWrite(aStream, " <", 5);
rdf_BlockingWrite(aStream, tag);
if (!wasDefinedAtGlobalScope && nameSpacePrefix.Length()) {
rdf_BlockingWrite(aStream, " xmlns:", 7);
rdf_BlockingWrite(aStream, nameSpacePrefix);
rdf_BlockingWrite(aStream, "=\"", 2);
rdf_BlockingWrite(aStream, nameSpaceURI);
rdf_BlockingWrite(aStream, "\"", 1);
}
rdf_BlockingWrite(aStream, ">", 1);
nsIRDFResource* resource;
nsIRDFLiteral* literal;
if (NS_SUCCEEDED(aValue->QueryInterface(kIRDFResourceIID, (void**) &resource))) {
const char* uri;
resource->GetValue(&uri);
nsAutoString escaped(uri);
rdf_EscapeAmpersands(escaped);
rdf_BlockingWrite(aStream, escaped);
NS_RELEASE(resource);
}
else if (NS_SUCCEEDED(aValue->QueryInterface(kIRDFLiteralIID, (void**) &literal))) {
const PRUnichar* value;
literal->GetValue(&value);
nsAutoString s(value);
rdf_EscapeAmpersands(s); // do these first!
rdf_EscapeAngleBrackets(s);
rdf_BlockingWrite(aStream, s);
NS_RELEASE(literal);
}
else {
// XXX it doesn't support nsIRDFResource _or_ nsIRDFLiteral???
NS_ASSERTION(PR_FALSE, "huh?");
}
rdf_BlockingWrite(aStream, "</", 2);
rdf_BlockingWrite(aStream, tag);
rdf_BlockingWrite(aStream, ">\n", 2);
return NS_OK;
}
nsresult
RDFXMLDataSourceImpl::SerializeProperty(nsIOutputStream* aStream,
nsIRDFResource* aResource,
nsIRDFResource* aProperty)
{
nsresult rv;
nsIRDFAssertionCursor* assertions = nsnull;
if (NS_FAILED(rv = mInner->GetTargets(aResource, aProperty, PR_TRUE, &assertions)))
return rv;
while (NS_SUCCEEDED(rv = assertions->Advance())) {
nsIRDFNode* value;
if (NS_FAILED(rv = assertions->GetValue(&value)))
break;
rv = SerializeAssertion(aStream, aResource, aProperty, value);
NS_RELEASE(value);
if (NS_FAILED(rv))
break;
}
if (rv == NS_ERROR_RDF_CURSOR_EMPTY)
rv = NS_OK;
NS_RELEASE(assertions);
return rv;
}
nsresult
RDFXMLDataSourceImpl::SerializeDescription(nsIOutputStream* aStream,
nsIRDFResource* aResource)
{
static const char kRDFDescription1[] = " <RDF:Description RDF:about=\"";
static const char kRDFDescription2[] = "\">\n";
static const char kRDFDescription3[] = " </RDF:Description>\n";
nsresult rv;
// XXX Look for an "RDF:type" property: if one exists, then output
// as a "typed node" instead of the more verbose "RDF:Description
// RDF:type='...'".
const char* s;
if (NS_FAILED(rv = aResource->GetValue(&s)))
return rv;
nsAutoString escaped(s);
rdf_EscapeAmpersands(escaped);
rdf_BlockingWrite(aStream, kRDFDescription1, sizeof(kRDFDescription1) - 1);
rdf_BlockingWrite(aStream, escaped);
rdf_BlockingWrite(aStream, kRDFDescription2, sizeof(kRDFDescription2) - 1);
nsIRDFArcsOutCursor* arcs = nsnull;
if (NS_FAILED(rv = mInner->ArcLabelsOut(aResource, &arcs)))
return rv;
while (NS_SUCCEEDED(rv = arcs->Advance())) {
nsIRDFResource* property;
if (NS_FAILED(rv = arcs->GetPredicate(&property)))
break;
rv = SerializeProperty(aStream, aResource, property);
NS_RELEASE(property);
if (NS_FAILED(rv))
break;
}
if (rv == NS_ERROR_RDF_CURSOR_EMPTY)
rv = NS_OK;
NS_IF_RELEASE(arcs);
rdf_BlockingWrite(aStream, kRDFDescription3, sizeof(kRDFDescription3) - 1);
return rv;
}
nsresult
RDFXMLDataSourceImpl::SerializeMember(nsIOutputStream* aStream,
nsIRDFResource* aContainer,
nsIRDFResource* aProperty)
{
nsresult rv;
// We open a cursor rather than just doing GetTarget() because
// there may for some random reason be two or more elements with
// the same ordinal value. Okay, I'm paranoid.
nsIRDFAssertionCursor* cursor;
if (NS_FAILED(rv = mInner->GetTargets(aContainer, aProperty, PR_TRUE, &cursor)))
return rv;
while (NS_SUCCEEDED(rv = cursor->Advance())) {
nsIRDFNode* node;
if (NS_FAILED(rv = cursor->GetObject(&node)))
break;
// If it's a resource, then output a "<RDF:li resource=... />"
// tag, because we'll be dumping the resource separately. (We
// iterate thru all the resources in the datasource,
// remember?) Otherwise, output the literal value.
nsIRDFResource* resource = nsnull;
nsIRDFLiteral* literal = nsnull;
if (NS_SUCCEEDED(rv = node->QueryInterface(kIRDFResourceIID, (void**) &resource))) {
const char* uri;
if (NS_SUCCEEDED(rv = resource->GetValue(&uri))) {
rdf_BlockingWrite(aStream, " <RDF:li RDF:resource=\"");
rdf_BlockingWrite(aStream, uri);
rdf_BlockingWrite(aStream, "\"/>\n");
}
NS_RELEASE(resource);
}
else if (NS_SUCCEEDED(rv = node->QueryInterface(kIRDFLiteralIID, (void**) &literal))) {
const PRUnichar* value;
if (NS_SUCCEEDED(rv = literal->GetValue(&value))) {
rdf_BlockingWrite(aStream, " <RDF:li>");
rdf_BlockingWrite(aStream, value);
rdf_BlockingWrite(aStream, " </RDF:li>\n");
}
NS_RELEASE(literal);
}
else {
NS_ASSERTION(PR_FALSE, "uhh -- it's not a literal or a resource?");
}
NS_RELEASE(node);
if (NS_FAILED(rv))
break;
}
if (rv == NS_ERROR_RDF_CURSOR_EMPTY)
rv = NS_OK;
NS_RELEASE(cursor);
return rv;
}
nsresult
RDFXMLDataSourceImpl::SerializeContainer(nsIOutputStream* aStream,
nsIRDFResource* aContainer)
{
static const char kRDFOpenSeq[] = " <RDF:Seq RDF:ID=\"";
static const char kRDFOpenBag[] = " <RDF:Bag RDF:ID=\"";
static const char kRDFOpenAlt[] = " <RDF:Alt RDF:ID=\"";
static const char kRDFCloseSeq[] = " </RDF:Seq>\n";
static const char kRDFCloseBag[] = " </RDF:Bag>\n";
static const char kRDFCloseAlt[] = " </RDF:Alt>\n";
nsresult rv;
// XXX decide if it's a sequence, bag, or alternation. Print
// the appropriate tag-open sequence HERE.
// 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
// properties to the bag itself.
nsIRDFArcsOutCursor* arcs;
if (NS_FAILED(rv = mInner->ArcLabelsOut(aContainer, &arcs)))
return rv;
while (NS_SUCCEEDED(rv = arcs->Advance())) {
nsIRDFResource* property;
if (NS_FAILED(rv = arcs->GetPredicate(&property)))
break;
// If it's a membership property, then output a "LI"
// tag. Otherwise, output a property.
if (rdf_IsOrdinalProperty(property)) {
rv = SerializeMember(aStream, aContainer, property);
}
else {
rv = SerializeProperty(aStream, aContainer, property);
}
NS_RELEASE(property);
if (NS_FAILED(rv))
break;
}
if (rv == NS_ERROR_RDF_CURSOR_EMPTY)
rv = NS_OK;
NS_RELEASE(arcs);
return rv;
}
nsresult
RDFXMLDataSourceImpl::SerializePrologue(nsIOutputStream* aStream)
{
static const char kXMLVersion[] = "<?xml version=\"1.0\"?>\n";
static const char kOpenRDF[] = "<RDF:RDF";
static const char kXMLNS[] = "\n xmlns:";
rdf_BlockingWrite(aStream, kXMLVersion, sizeof(kXMLVersion) - 1);
// XXX write out any style sheet and datasource includes here
// global name space declarations
rdf_BlockingWrite(aStream, kOpenRDF, sizeof(kOpenRDF) - 1);
for (NameSpaceMap* entry = mNameSpaces; entry != nsnull; entry = entry->Next) {
rdf_BlockingWrite(aStream, kXMLNS, sizeof(kXMLNS) - 1);
nsAutoString prefix;
entry->Prefix->ToString(prefix);
rdf_BlockingWrite(aStream, prefix);
rdf_BlockingWrite(aStream, "=\"", 2);
rdf_BlockingWrite(aStream, entry->URI);
rdf_BlockingWrite(aStream, "\"", 1);
}
rdf_BlockingWrite(aStream, ">\n", 2);
return NS_OK;
}
nsresult
RDFXMLDataSourceImpl::SerializeEpilogue(nsIOutputStream* aStream)
{
static const char kCloseRDF[] = "</RDF:RDF>\n";
rdf_BlockingWrite(aStream, kCloseRDF);
return NS_OK;
}
NS_IMETHODIMP
RDFXMLDataSourceImpl::Serialize(nsIOutputStream* aStream)
{
nsresult rv;
nsIRDFResourceCursor* resources = nsnull;
if (NS_FAILED(rv = mInner->GetAllResources(&resources)))
goto done;
if (NS_FAILED(rv = SerializePrologue(aStream)))
goto done;
while (NS_SUCCEEDED(rv = resources->Advance())) {
nsIRDFResource* resource;
if (NS_FAILED(rv = resources->GetResource(&resource)))
break;
if (rdf_IsContainer(mInner, resource)) {
rv = SerializeContainer(aStream, resource);
}
else {
rv = SerializeDescription(aStream, resource);
}
NS_RELEASE(resource);
if (NS_FAILED(rv))
break;
}
if (rv == NS_ERROR_RDF_CURSOR_EMPTY)
rv = NS_OK;
if (NS_FAILED(rv))
goto done;
rv = SerializeEpilogue(aStream);
done:
NS_IF_RELEASE(resources);
return rv;
}

View File

@ -107,25 +107,34 @@ 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
rdf_IsContainer(nsIRDFDataSource* ds,
nsIRDFResource* resource)
{
PRBool result = PR_FALSE;
nsIRDFResource* RDF_instanceOf = nsnull;
nsIRDFResource* RDF_Bag = nsnull;
nsIRDFResource* RDF_Seq = nsnull;
static nsIRDFResource* RDF_instanceOf = nsnull;
static nsIRDFResource* RDF_Bag = nsnull;
static nsIRDFResource* RDF_Seq = nsnull;
static nsIRDFResource* RDF_Alt = nsnull;
nsresult rv;
if (NS_FAILED(rv = rdf_EnsureRDFService()))
goto done;
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_instanceOf, &RDF_instanceOf)))
goto done;
if (! RDF_instanceOf) {
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_instanceOf, &RDF_instanceOf)))
goto done;
}
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_Bag, &RDF_Bag)))
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;
@ -133,16 +142,33 @@ rdf_IsContainer(nsIRDFDataSource* ds,
if (result)
goto done;
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_Seq, &RDF_Seq)))
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:
NS_IF_RELEASE(RDF_Seq);
NS_IF_RELEASE(RDF_Bag);
NS_IF_RELEASE(RDF_instanceOf);
// 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;
}

View File

@ -491,6 +491,10 @@ public:
return mInner->ArcLabelsOut(source, labels);
}
NS_IMETHOD GetAllResources(nsIRDFResourceCursor** aCursor) {
return mInner->GetAllResources(aCursor);
}
NS_IMETHOD Flush(void);
NS_IMETHOD IsCommandEnabled(const char* aCommand,

View File

@ -519,6 +519,13 @@ MailDataSource::ArcLabelsOut(nsIRDFResource* source,
}
}
NS_IMETHODIMP
MailDataSource::GetAllResources(nsIRDFResourceCursor** aCursor)
{
NS_NOTYETIMPLEMENTED("sorry!");
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
MailDataSource::InitAccountList(void)
{

View File

@ -153,6 +153,8 @@ public:
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
nsIRDFArcsOutCursor** labels);
NS_IMETHOD GetAllResources(nsIRDFResourceCursor** aCursor);
NS_IMETHOD Flush();
NS_IMETHOD IsCommandEnabled(const char* aCommand,

View File

@ -92,7 +92,7 @@ static NS_DEFINE_CID(kNetServiceCID, NS_NETSERVICE_CID);
static NS_DEFINE_CID(kRDFBookMarkDataSourceCID, NS_RDFBOOKMARKDATASOURCE_CID);
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kRDFDataBaseCID, NS_RDFDATABASE_CID);
static NS_DEFINE_CID(kRDFCompositeDataSourceCID, NS_RDFCOMPOSITEDATASOURCE_CID);
static NS_DEFINE_CID(kRDFContentSinkCID, NS_RDFCONTENTSINK_CID);
static NS_DEFINE_CID(kRDFXMLDataSourceCID, NS_RDFXMLDATASOURCE_CID);
@ -130,7 +130,7 @@ SetupRegistry(void)
nsRepository::RegisterFactory(kRDFInMemoryDataSourceCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFServiceCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFContentSinkCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFDataBaseCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFCompositeDataSourceCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFXMLDataSourceCID, RDF_DLL, PR_FALSE, PR_FALSE);
// parser
@ -167,11 +167,10 @@ main(int argc, char** argv)
nsIEventQueueService* theEventQueueService = nsnull;
PLEventQueue* mainQueue = nsnull;
nsIRDFService* theRDFService = nsnull;
nsIRDFDataSource* ds = nsnull;
nsIRDFXMLDataSource* ds = nsnull;
nsIRDFResource* theHomePage = nsnull;
nsIRDFResource* NC_title = nsnull;
nsIRDFLiteral* theTitle = nsnull;
PRInt32 i;
// Get netlib off the floor...
if (NS_FAILED(rv = nsServiceManager::GetService(kEventQueueServiceCID,
@ -195,14 +194,12 @@ main(int argc, char** argv)
(void**) &ds)))
goto done;
if (NS_FAILED(rv = ds->Init(argv[1])))
if (NS_FAILED(rv = ds->SetSynchronous(PR_TRUE)))
goto done;
// XXX This is really gross. I need to figure out the right way to do it...
for (i = 0; i < 1000000; ++i) {
PLEvent* event = PL_GetEvent(mainQueue);
PL_HandleEvent(event);
}
// Okay, this should load the XML file...
if (NS_FAILED(rv = ds->Init(argv[1])))
goto done;
// Now take the graph and munge it a little bit...
if (NS_FAILED(rv = nsServiceManager::GetService(kRDFServiceCID,
@ -213,7 +210,7 @@ main(int argc, char** argv)
if (NS_FAILED(rv = theRDFService->GetResource("http://home.netscape.com", &theHomePage)))
goto done;
if (NS_FAILED(rv = theRDFService->GetResource("http://rdf.nescape.com/NC#title", &NC_title)))
if (NS_FAILED(rv = theRDFService->GetResource("http://home.nescape.com/NC-rdf#title", &NC_title)))
goto done;
if (NS_FAILED(rv = theRDFService->GetLiteral(nsAutoString("Netscape's Home Page"), &theTitle)))

View File

@ -30,6 +30,7 @@ PROGRAM= .\$(OBJDIR)\$(EXENAME).exe
OBJS= .\$(OBJDIR)\rdfsink.obj
LINCS= -I$(PUBLIC)\rdf \
-I$(PUBLIC)\dom \
-I$(LIBNSPR) \
-I$(PUBLIC)\xpcom \
-I$(PUBLIC)\netlib \

View File

@ -18,13 +18,14 @@
#include <io.h>
#include "nsIContent.h"
#include "nsIEventQueueService.h"
#include "nsIInputStream.h"
#include "nsINetService.h"
#include "nsINetService.h"
#include "nsIOutputStream.h"
#include "nsIPostToServer.h"
#include "nsIRDFDataBase.h"
#include "nsIRDFDataSource.h"
#include "nsIRDFCompositeDataSource.h"
#include "nsIRDFXMLDataSource.h"
#include "nsIRDFDocument.h"
#include "nsIRDFNode.h"
#include "nsIRDFService.h"
@ -32,11 +33,13 @@
#include "nsIServiceManager.h"
#include "nsIStreamListener.h"
#include "nsIURL.h"
#include "nsDOMCID.h" // for NS_SCRIPT_NAMESET_REGISTRY_CID
#include "nsLayoutCID.h" // for NS_NAMESPACEMANAGER_CID
#include "nsParserCIID.h"
#include "nsRDFCID.h"
#include "nsRDFCID.h"
#include "nsRepository.h"
#include "nsXPComCIID.h"
#include "plevent.h"
#include "plstr.h"
@ -45,13 +48,30 @@
#define FAILURE -1
#ifdef XP_PC
#if defined(XP_PC)
#define DOM_DLL "jsdom.dll"
#define LAYOUT_DLL "raptorhtml.dll"
#define NETLIB_DLL "netlib.dll"
#define PARSER_DLL "raptorhtmlpars.dll"
#define RDF_DLL "rdf.dll"
#define LAYOUT_DLL "raptorhtml.dll"
#define XPCOM_DLL "xpcom32.dll"
#elif defined(XP_UNIX)
#define DOM_DLL "libjsdom.so"
#define LAYOUT_DLL "libraptorhtml.so"
#define NETLIB_DLL "libnetlib.so"
#define PARSER_DLL "libraptorhtmlpars.so"
#define RDF_DLL "librdf.so"
#define XPCOM_DLL "libxpcom.so"
#elif defined(XP_MAC)
#define DOM_DLL "DOM_DLL"
#define LAYOUT_DLL "LAYOUT_DLL"
#define NETLIB_DLL "NETLIB_DLL"
#define PARSER_DLL "PARSER_DLL"
#define RDF_DLL "RDF_DLL"
#define XPCOM_DLL "XPCOM_DLL"
#endif
////////////////////////////////////////////////////////////////////////
// CIDs
@ -62,9 +82,9 @@ static NS_DEFINE_CID(kNetServiceCID, NS_NETSERVICE_CID);
static NS_DEFINE_CID(kRDFBookMarkDataSourceCID, NS_RDFBOOKMARKDATASOURCE_CID);
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kRDFDataBaseCID, NS_RDFDATABASE_CID);
static NS_DEFINE_CID(kRDFCompositeDataSourceCID, NS_RDFCOMPOSITEDATASOURCE_CID);
static NS_DEFINE_CID(kRDFContentSinkCID, NS_RDFCONTENTSINK_CID);
static NS_DEFINE_CID(kRDFStreamDataSourceCID, NS_RDFSTREAMDATASOURCE_CID);
static NS_DEFINE_CID(kRDFXMLDataSourceCID, NS_RDFXMLDATASOURCE_CID);
// parser
static NS_DEFINE_CID(kParserCID, NS_PARSER_IID);
@ -73,33 +93,48 @@ static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID);
// layout
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
// dom
static NS_DEFINE_IID(kScriptNameSetRegistryCID, NS_SCRIPT_NAMESET_REGISTRY_CID);
// xpcom
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
////////////////////////////////////////////////////////////////////////
// IIDs
//NS_DEFINE_IID(kIPostToServerIID, NS_IPOSTTOSERVER_IID);
NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID);
NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID);
NS_DEFINE_IID(kIRDFXMLDataSourceIID, NS_IRDFXMLDATASOURCE_IID);
NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
NS_DEFINE_IID(kIRDFXMLSourceIID, NS_IRDFXMLSOURCE_IID);
static nsresult
SetupRegistry(void)
{
// netlib
nsRepository::RegisterFactory(kNetServiceCID, NETLIB_DLL, PR_FALSE, PR_FALSE);
// rdf
nsRepository::RegisterFactory(kRDFBookMarkDataSourceCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFInMemoryDataSourceCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFServiceCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFContentSinkCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFDataBaseCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFStreamDataSourceCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFCompositeDataSourceCID, RDF_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kRDFXMLDataSourceCID, RDF_DLL, PR_FALSE, PR_FALSE);
// parser
nsRepository::RegisterFactory(kParserCID, PARSER_DLL, PR_FALSE, PR_FALSE);
nsRepository::RegisterFactory(kWellFormedDTDCID, PARSER_DLL, PR_FALSE, PR_FALSE);
// layout
nsRepository::RegisterFactory(kNameSpaceManagerCID, LAYOUT_DLL, PR_FALSE, PR_FALSE);
// dom
nsRepository::RegisterFactory(kScriptNameSetRegistryCID, DOM_DLL, PR_FALSE, PR_FALSE);
// xpcom
nsRepository::RegisterFactory(kEventQueueServiceCID, XPCOM_DLL, PR_FALSE, PR_FALSE);
return NS_OK;
}
@ -143,38 +178,68 @@ main(int argc, char** argv)
return 1;
}
PL_InitializeEventsLib("");
PLEventQueue* mainQueue = PL_GetMainEventQueue();
SetupRegistry();
nsIRDFDataSource* ds = nsnull;
nsIRDFXMLSource* xmlSource = nsnull;
PRInt32 i;
nsIEventQueueService* theEventQueueService = nsnull;
PLEventQueue* mainQueue = nsnull;
nsIRDFService* theRDFService = nsnull;
nsIRDFXMLDataSource* ds = nsnull;
nsIOutputStream* out = nsnull;
nsIRDFXMLSource* source = nsnull;
if (NS_FAILED(rv = nsRepository::CreateInstance(kRDFStreamDataSourceCID,
// Get netlib off the floor...
if (NS_FAILED(rv = nsServiceManager::GetService(kEventQueueServiceCID,
kIEventQueueServiceIID,
(nsISupports**) &theEventQueueService)))
goto done;
if (NS_FAILED(rv = theEventQueueService->CreateThreadEventQueue()))
goto done;
if (NS_FAILED(rv = theEventQueueService->GetThreadEventQueue(PR_GetCurrentThread(),
&mainQueue)))
goto done;
// Create a stream data source and initialize it on argv[1], which
// is hopefully a "file:" URL. (Actually, we can do _any_ kind of
// URL, but only a "file:" URL will be written back to disk.)
if (NS_FAILED(rv = nsRepository::CreateInstance(kRDFXMLDataSourceCID,
nsnull,
kIRDFDataSourceIID,
kIRDFXMLDataSourceIID,
(void**) &ds)))
goto done;
if (NS_FAILED(rv = ds->SetSynchronous(PR_TRUE)))
goto done;
// Okay, this should load the XML file...
if (NS_FAILED(rv = ds->Init(argv[1])))
goto done;
// XXX This is really gross. I need to figure out the right way to do it...
for (i = 0; i < 1000000; ++i) {
PLEvent* event = PL_GetEvent(mainQueue);
PL_HandleEvent(event);
// And finally, write it back out.
if ((out = new ConsoleOutputStreamImpl()) == nsnull) {
rv = NS_ERROR_OUT_OF_MEMORY;
goto done;
}
if (NS_SUCCEEDED(ds->QueryInterface(kIRDFXMLSourceIID, (void**) &xmlSource))) {
ConsoleOutputStreamImpl* out = new ConsoleOutputStreamImpl();
xmlSource->Serialize(out);
NS_RELEASE(xmlSource);
}
NS_ADDREF(out);
if (NS_FAILED(rv = ds->QueryInterface(kIRDFXMLSourceIID, (void**) &source)))
goto done;
if (NS_FAILED(rv = source->Serialize(out)))
goto done;
done:
NS_IF_RELEASE(out);
NS_IF_RELEASE(ds);
if (theRDFService) {
nsServiceManager::ReleaseService(kRDFServiceCID, theRDFService);
theRDFService = nsnull;
}
if (theEventQueueService) {
nsServiceManager::ReleaseService(kEventQueueServiceCID, theEventQueueService);
theEventQueueService = nsnull;
}
return (NS_FAILED(rv) ? 1 : 0);
}