Cleaned up content model generation.

This commit is contained in:
waterson%netscape.com 1998-12-07 20:09:30 +00:00
parent 4d4668dca4
commit 95c99a86f8
13 changed files with 647 additions and 259 deletions

View File

@ -36,7 +36,10 @@ class nsIRDFNode;
*/
class nsIRDFContent : public nsIXMLContent {
public:
NS_IMETHOD Init(nsIRDFDocument* doc, nsIRDFNode* resource, PRBool childrenMustBeGenerated) = 0;
NS_IMETHOD Init(nsIRDFDocument* doc,
const nsString& tag,
nsIRDFNode* resource,
PRBool childrenMustBeGenerated) = 0;
NS_IMETHOD SetResource(const nsString& aURI) = 0;
NS_IMETHOD GetResource(nsString& rURI) const = 0;

View File

@ -22,9 +22,10 @@
#include "nsIXMLDocument.h"
class nsIRDFNode;
class nsIRDFContent;
class nsIRDFDataBase;
class nsISupportsArray;
class nsIRDFNode;
// {954F0811-81DC-11d2-B52A-000000000000}
#define NS_IRDFDOCUMENT_IID \
@ -35,9 +36,22 @@ class nsISupportsArray;
*/
class nsIRDFDocument : public nsIXMLDocument {
public:
/**
* Retrieve the document's RDF data base.
*/
NS_IMETHOD GetDataBase(nsIRDFDataBase*& rDataBase) = 0;
NS_IMETHOD CreateChildren(nsIRDFNode* resource, nsISupportsArray* children) = 0;
/**
* Given an nsIRDFContent element in the document, create its
* "content children," that is, a set of nsIRDFContent elements that
* should appear as the node's children in the content model.
*/
NS_IMETHOD CreateChildren(nsIRDFContent* element, nsISupportsArray* children) = 0;
// XXX these should probably be strings so you can mess with them
// via the DOM.
NS_IMETHOD AddTreeProperty(nsIRDFNode* resource) = 0;
NS_IMETHOD RemoveTreeProperty(nsIRDFNode* resource) = 0;
};
// factory functions

View File

@ -36,14 +36,7 @@
TO DO ------------------------
1) Using the nsIRDFContent and nsIRDFContainerContent interfaces to
actually build the content model is a red herring. What I
*really* want to do is just build an RDF graph, then let the
presentation actually generate the "content model" on demand.
2) Handle resource references in properties
3) Make sure all shortcut syntax works right.
1) Make sure all shortcut syntax works right.
*/

View File

@ -43,7 +43,7 @@ class nsRDFContentSink : public nsIRDFContentSink
{
public:
nsRDFContentSink();
~nsRDFContentSink();
virtual ~nsRDFContentSink();
virtual nsresult Init(nsIURL* aURL);

View File

@ -23,11 +23,16 @@
#include "nsIDocumentObserver.h"
#include "nsIHTMLStyleSheet.h"
#include "nsIParser.h"
#include "nsIRDFContent.h"
#include "nsIRDFCursor.h"
#include "nsIRDFDataBase.h"
#include "nsIRDFDataSource.h"
#include "nsIRDFNode.h"
#include "nsIRDFResourceManager.h"
#include "nsIPresShell.h"
#include "nsIScriptContextOwner.h"
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#if XP_NEW_SELECTION
#include "nsICollection.h"
#else
@ -44,32 +49,42 @@
#include "nsRDFCID.h"
#include "nsRDFContentSink.h"
#include "nsRDFDocument.h"
#include "nsITextContent.h"
#include "nsIDTD.h"
#include "nsLayoutCID.h"
#include "rdfutil.h"
////////////////////////////////////////////////////////////////////////
static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
static NS_DEFINE_IID(kIHTMLStyleSheetIID, NS_IHTML_STYLE_SHEET_IID);
static NS_DEFINE_IID(kIParserIID, NS_IPARSER_IID);
static NS_DEFINE_IID(kIPresShellIID, NS_IPRESSHELL_IID);
static NS_DEFINE_IID(kIRDFDataBaseIID, NS_IRDFDATABASE_IID);
static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID);
static NS_DEFINE_IID(kIRDFDocumentIID, NS_IRDFDOCUMENT_IID);
static NS_DEFINE_IID(kIRDFResourceManagerIID, NS_IRDFRESOURCEMANAGER_IID);
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID); // XXX grr...
static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID);
static NS_DEFINE_IID(kIXMLDocumentIID, NS_IXMLDOCUMENT_IID);
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
static NS_DEFINE_IID(kIHTMLStyleSheetIID, NS_IHTML_STYLE_SHEET_IID);
#if XP_NEW_SELECTION
static NS_DEFINE_IID(kICollectionIID, NS_ICOLLECTION_IID);
#else
static NS_DEFINE_IID(kISelectionIID, NS_ISELECTION_IID);
#endif
static NS_DEFINE_CID(kHTMLStyleSheetCID, NS_HTMLSTYLESHEET_CID);
static NS_DEFINE_CID(kParserCID, NS_PARSER_IID); // XXX
static NS_DEFINE_CID(kPresShellCID, NS_PRESSHELL_CID);
static NS_DEFINE_CID(kRDFMemoryDataSourceCID, NS_RDFMEMORYDATASOURCE_CID);
static NS_DEFINE_CID(kRDFSimpleDataBaseCID, NS_RDFSIMPLEDATABASE_CID);
static NS_DEFINE_CID(kParserCID, NS_PARSER_IID); // XXX
static NS_DEFINE_CID(kRDFResourceManagerCID, NS_RDFRESOURCEMANAGER_CID);
static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID);
static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID);
static NS_DEFINE_CID(kHTMLStyleSheetCID, NS_HTMLSTYLESHEET_CID);
#if XP_NEW_SELECTION
static NS_DEFINE_CID(kRangeListCID, NS_RANGELIST_CID);
#else
@ -94,7 +109,9 @@ nsRDFDocument::nsRDFDocument()
mDisplaySelection(PR_FALSE),
mAttrStyleSheet(nsnull),
mParser(nsnull),
mDB(nsnull)
mDB(nsnull),
mResourceMgr(nsnull),
mTreeProperties(nsnull)
{
NS_INIT_REFCNT();
@ -113,6 +130,8 @@ nsRDFDocument::nsRDFDocument()
(void**) &mSelection)))
#endif
PR_ASSERT(0);
}
nsRDFDocument::~nsRDFDocument()
@ -129,10 +148,17 @@ nsRDFDocument::~nsRDFDocument()
delete ns;
}
if (mResourceMgr) {
nsServiceManager::ReleaseService(kRDFResourceManagerCID, mResourceMgr);
mResourceMgr = nsnull;
}
// mParentDocument is never refcounted
NS_IF_RELEASE(mSelection);
NS_IF_RELEASE(mScriptContextOwner);
NS_IF_RELEASE(mAttrStyleSheet);
NS_IF_RELEASE(mTreeProperties);
NS_IF_RELEASE(mRootContent);
NS_IF_RELEASE(mDB);
NS_IF_RELEASE(mDocumentURLGroup);
NS_IF_RELEASE(mDocumentURL);
@ -171,6 +197,17 @@ nsRDFDocument::Init()
if (NS_FAILED(rv = NS_NewHeapArena(&mArena, nsnull)))
return rv;
if (NS_FAILED(rv = nsRepository::CreateInstance(kRDFSimpleDataBaseCID,
nsnull,
kIRDFDataBaseIID,
(void**) &mDB)))
return rv;
if (NS_FAILED(rv = nsServiceManager::GetService(kRDFResourceManagerCID,
kIRDFResourceManagerIID,
(nsISupports**) &mResourceMgr)))
return rv;
return NS_OK;
}
@ -224,10 +261,7 @@ nsRDFDocument::StartDocumentLoad(nsIURL *aURL,
nsIHTMLStyleSheet* sheet = nsnull;
nsIDTD* dtd = nsnull;
if (NS_FAILED(rv = nsRepository::CreateInstance(kRDFSimpleDataBaseCID,
nsnull,
kIRDFDataBaseIID,
(void**) &mDB))) {
if (NS_FAILED(rv = Init())) {
PR_ASSERT(0);
goto done;
}
@ -287,7 +321,6 @@ nsRDFDocument::StartDocumentLoad(nsIURL *aURL,
goto done;
}
// XXX Use a factory!!!
if (NS_FAILED(rv = nsRepository::CreateInstance(kWellFormedDTDCID,
nsnull,
kIDTDIID,
@ -1104,6 +1137,128 @@ nsRDFDocument::GetDataBase(nsIRDFDataBase*& result)
return NS_OK;
}
NS_IMETHODIMP
nsRDFDocument::CreateChildren(nsIRDFContent* element, nsISupportsArray* children)
{
nsresult rv;
NS_ASSERTION(mDB, "not initialized");
if (! mDB)
return NS_ERROR_NOT_INITIALIZED;
NS_ASSERTION(mResourceMgr, "not initialized");
if (! mResourceMgr)
return NS_ERROR_NOT_INITIALIZED;
nsIRDFNode* resource = nsnull;
nsIRDFCursor* properties = nsnull;
PRBool moreProperties;
if (NS_FAILED(rv = element->GetResource(resource)))
goto done;
// Create a cursor that'll enumerate all of the outbound arcs
if (NS_FAILED(rv = mDB->ArcLabelsOut(resource, properties)))
goto done;
while (NS_SUCCEEDED(rv = properties->HasMoreElements(moreProperties)) && moreProperties) {
nsIRDFNode* property = nsnull;
PRBool tv;
if (NS_FAILED(rv = properties->GetNext(property, tv /* ignored */)))
break;
nsAutoString uri;
if (NS_FAILED(rv = property->GetStringValue(uri))) {
NS_RELEASE(property);
break;
}
// Create a second cursor that'll enumerate all of the values
// for all of the arcs.
nsIRDFCursor* values;
if (NS_FAILED(rv = mDB->GetTargets(resource, property, PR_TRUE, values))) {
NS_RELEASE(property);
break;
}
PRBool moreValues;
while (NS_SUCCEEDED(rv = values->HasMoreElements(moreValues)) && moreValues) {
nsIRDFNode* value = nsnull;
if (NS_FAILED(rv = values->GetNext(value, tv /* ignored */)))
break;
// XXX At this point, we need to decide exactly what kind
// of kid to create in the content model. For example, for
// leaf nodes, we probably want to create some kind of
// text element.
nsIRDFContent* child;
if (NS_FAILED(rv = CreateChild(property, value, child))) {
NS_RELEASE(value);
break;
}
// And finally, add the child into the content model
children->AppendElement(child);
NS_RELEASE(child);
NS_RELEASE(value);
}
NS_RELEASE(values);
NS_RELEASE(property);
if (NS_FAILED(rv))
break;
}
done:
NS_IF_RELEASE(resource);
NS_IF_RELEASE(properties);
return rv;
}
NS_IMETHODIMP
nsRDFDocument::AddTreeProperty(nsIRDFNode* resource)
{
nsresult rv;
if (! mTreeProperties) {
if (NS_FAILED(rv = NS_NewISupportsArray(&mTreeProperties)))
return rv;
}
// ensure uniqueness
if (mTreeProperties->IndexOf(resource) != -1) {
PR_ASSERT(0);
return NS_OK;
}
mTreeProperties->AppendElement(resource);
return NS_OK;
}
NS_IMETHODIMP
nsRDFDocument::RemoveTreeProperty(nsIRDFNode* resource)
{
if (! mTreeProperties) {
// XXX no properties have ever been inserted!
PR_ASSERT(0);
return NS_OK;
}
if (! mTreeProperties->RemoveElement(resource)) {
// XXX that specific property has never been inserted!
PR_ASSERT(0);
return NS_OK;
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
// Implementation methods
@ -1134,3 +1289,95 @@ nsRDFDocument::FindContent(const nsIContent* aStartNode,
return nsnull;
}
PRBool
nsRDFDocument::IsTreeProperty(const nsIRDFNode* property) const
{
#define TREE_PROPERTY_HACK
#if defined(TREE_PROPERTY_HACK)
nsAutoString s;
property->GetStringValue(s);
if (s.Equals("http://home.netscape.com/NC-rdf#Bookmark") ||
s.Equals("http://home.netscape.com/NC-rdf#Folder")) {
return PR_TRUE;
}
#endif // defined(TREE_PROPERTY_HACK)
if (rdf_IsOrdinalProperty(property)) {
return PR_TRUE;
}
if (! mTreeProperties) {
return PR_FALSE;
}
if (mTreeProperties->IndexOf(property) == -1) {
return PR_FALSE;
}
return PR_TRUE;
}
nsresult
nsRDFDocument::NewChild(const nsString& tag,
nsIRDFNode* resource,
nsIRDFContent*& result,
PRBool childrenMustBeGenerated)
{
nsresult rv;
nsIRDFContent* child;
if (NS_FAILED(rv = NS_NewRDFElement(&child)))
return rv;
if (NS_FAILED(rv = child->Init(this, tag, resource, childrenMustBeGenerated))) {
NS_RELEASE(child);
return rv;
}
result = child;
return NS_OK;
}
nsresult
nsRDFDocument::AttachTextNode(nsIContent* parent,
nsIRDFNode* value)
{
nsresult rv;
nsAutoString s;
nsIContent* node = nsnull;
nsITextContent* text = nsnull;
nsIDocument* doc = nsnull;
if (NS_FAILED(rv = value->GetStringValue(s)))
goto error;
if (NS_FAILED(rv = nsRepository::CreateInstance(kTextNodeCID,
nsnull,
kIContentIID,
(void**) &node)))
goto error;
if (NS_FAILED(rv = QueryInterface(kIDocumentIID, (void**) &doc)))
goto error;
if (NS_FAILED(rv = node->SetDocument(doc, PR_FALSE)))
goto error;
if (NS_FAILED(rv = node->QueryInterface(kITextContentIID, (void**) &text)))
goto error;
if (NS_FAILED(rv = text->SetText(s.GetUnicode(), s.Length(), PR_FALSE)))
goto error;
// hook it up to the child
if (NS_FAILED(rv = node->SetParent(parent)))
goto error;
if (NS_FAILED(rv = parent->AppendChildTo(NS_STATIC_CAST(nsIContent*, node), PR_TRUE)))
goto error;
error:
NS_IF_RELEASE(node);
NS_IF_RELEASE(text);
NS_IF_RELEASE(doc);
return rv;
}

View File

@ -199,7 +199,11 @@ public:
// nsIRDFDocument interface
NS_IMETHOD GetDataBase(nsIRDFDataBase*& result);
NS_IMETHOD CreateChildren(nsIRDFNode* resource, nsISupportsArray* children) = 0;
NS_IMETHOD CreateChildren(nsIRDFContent* element, nsISupportsArray* children);
NS_IMETHOD AddTreeProperty(nsIRDFNode* resource);
NS_IMETHOD RemoveTreeProperty(nsIRDFNode* resource);
protected:
nsIContent*
@ -207,6 +211,20 @@ protected:
const nsIContent* aTest1,
const nsIContent* aTest2) const;
PRBool IsTreeProperty(const nsIRDFNode* resource) const;
nsresult AttachTextNode(nsIContent* parent,
nsIRDFNode* value);
nsresult NewChild(const nsString& tag,
nsIRDFNode* resource,
nsIRDFContent*& result,
PRBool childrenMustBeGenerated);
virtual nsresult CreateChild(nsIRDFNode* property,
nsIRDFNode* value,
nsIRDFContent*& result) = 0;
nsIArena* mArena;
nsVoidArray mObservers;
nsAutoString mDocumentTitle;
@ -228,6 +246,8 @@ protected:
nsIStyleSheet* mAttrStyleSheet;
nsIParser* mParser;
nsIRDFDataBase* mDB;
nsIRDFResourceManager* mResourceMgr;
nsISupportsArray* mTreeProperties;
};

View File

@ -41,7 +41,14 @@
*/
// #define the following if you want properties to show up as
// attributes on an element. I know, this sucks, but I'm just not
// really sure if this is necessary...
//#define CREATE_PROPERTIES_AS_ATTRIBUTES
#include "nsDOMEvent.h"
#include "nsHashtable.h"
#include "nsIAtom.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMScriptObjectFactory.h"
@ -137,6 +144,49 @@ RDFDOMNodeListImpl::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
return rv;
}
////////////////////////////////////////////////////////////////////////
// AttributeKey
class AttributeKey : public nsHashKey
{
private:
nsIAtom* mAttr;
public:
AttributeKey(const nsString& s) {
mAttr = NS_NewAtom(s);
}
AttributeKey(nsIAtom* atom) {
mAttr = atom;
NS_IF_ADDREF(mAttr);
}
virtual ~AttributeKey(void) {
NS_IF_RELEASE(mAttr);
}
virtual PRUint32 HashValue(void) const {
return (PRUint32) mAttr;
}
virtual PRBool Equals(const nsHashKey* aKey) const {
AttributeKey* that = NS_DYNAMIC_CAST(AttributeKey*, aKey);
return ((that) && (this->mAttr == that->mAttr));
}
virtual nsHashKey* Clone(void) const {
return new AttributeKey(mAttr);
}
nsresult GetAtomValue(nsIAtom*& result) {
result = mAttr;
NS_IF_ADDREF(mAttr);
return NS_OK;
}
};
////////////////////////////////////////////////////////////////////////
// nsRDFElement
@ -163,13 +213,34 @@ nsRDFElement::nsRDFElement(void)
mResource(nsnull),
mChildren(nsnull),
mChildrenMustBeGenerated(PR_TRUE),
mParent(nsnull)
mParent(nsnull),
mAttributes(nsnull)
{
NS_INIT_REFCNT();
}
static PRBool
rdf_AttributeDestroyEnumFunc(nsHashKey* key, void* aData, void* closure)
{
// XXX this doesn't seem to work...
//nsHashtable* attributes = NS_DYNAMIC_CAST(nsHashtable*, closure);
//attributes->Remove(key);
nsString* value = NS_DYNAMIC_CAST(nsString*, aData);
delete value;
return PR_TRUE;
}
nsRDFElement::~nsRDFElement()
{
if (mAttributes) {
mAttributes->Enumerate(rdf_AttributeDestroyEnumFunc, mAttributes);
delete mAttributes;
}
// mDocument is not refcounted
//NS_IF_RELEASE(mScriptObject); XXX don't forget!
NS_IF_RELEASE(mChildren);
NS_IF_RELEASE(mNameSpace);
NS_IF_RELEASE(mResource);
}
@ -583,17 +654,17 @@ nsRDFElement::GetDocument(nsIDocument*& aResult) const
NS_IMETHODIMP
nsRDFElement::SetDocument(nsIDocument* aDocument, PRBool aDeep)
{
NS_IF_RELEASE(mDocument);
nsresult rv;
if (aDocument) {
nsIRDFDocument* doc;
if (NS_FAILED(rv = aDocument->QueryInterface(kIRDFDocumentIID,
(void**) &mDocument)))
(void**) &doc)))
return rv;
}
// implicit AddRef() from QI
mDocument = doc;
NS_RELEASE(doc); // not refcounted
}
if (aDeep && mChildren) {
for (PRInt32 i = mChildren->Count() - 1; i >= 0; --i) {
@ -640,6 +711,7 @@ nsRDFElement::SetParent(nsIContent* aParent)
NS_IMETHODIMP
nsRDFElement::CanContainChildren(PRBool& aResult) const
{
// XXX Hmm -- not sure if this is unilaterally true...
aResult = PR_TRUE;
return NS_OK;
}
@ -779,20 +851,11 @@ nsRDFElement::IsSynthetic(PRBool& aResult)
NS_IMETHODIMP
nsRDFElement::GetTag(nsIAtom*& aResult) const
{
PR_ASSERT(mResource);
if (! mResource)
return NS_ERROR_NOT_INITIALIZED;
// XXX the problem with this is that we only have a
// fully-qualified URI, not "just" the tag. And I think the style
// system ain't gonna work right with that. So this is a complete
// hack to parse what probably _was_ the tag out.
nsresult rv;
nsAutoString s;
if (NS_FAILED(rv = mResource->GetStringValue(s)))
return rv;
nsAutoString s = mTag;
PRInt32 index;
if ((index = s.RFind('#')) >= 0)
@ -812,22 +875,49 @@ nsRDFElement::SetAttribute(const nsString& aName,
const nsString& aValue,
PRBool aNotify)
{
PR_ASSERT(0); // this should be done via RDF
return NS_ERROR_UNEXPECTED;
if (! mAttributes) {
// Construct the attribute table on demand.
if (! (mAttributes = new nsHashtable(7)))
return NS_ERROR_OUT_OF_MEMORY;
}
AttributeKey key(aName);
nsString* value = new nsString(aValue);
if (! value)
return NS_ERROR_OUT_OF_MEMORY;
nsString* old = NS_STATIC_CAST(nsString*, mAttributes->Put(&key, value));
delete old;
return NS_OK;
}
NS_IMETHODIMP
nsRDFElement::GetAttribute(const nsString& aName, nsString& aResult) const
{
nsresult rv;
nsresult rv = NS_ERROR_FAILURE; // XXX is this right?
if (mAttributes) {
AttributeKey key(aName);
nsString* value = NS_STATIC_CAST(nsString*, mAttributes->Get(&key));
if (value) {
aResult = *value;
return NS_OK;
}
}
#if defined(CREATE_PROPERTIES_AS_ATTRIBUTES)
// XXX I'm not sure if we should support properties as attributes
// or not...
nsIRDFResourceManager* mgr = nsnull;
if (NS_FAILED(rv = nsServiceManager::GetService(kRDFResourceManagerCID,
kIRDFResourceManagerIID,
(nsISupports**) &mgr)))
return rv;
nsIRDFDataBase* db = nsnull;
nsIRDFDataBase* db = nsnull;
nsIRDFNode* property = nsnull;
nsIRDFNode* value = nsnull;
@ -851,14 +941,35 @@ done:
NS_IF_RELEASE(db);
nsServiceManager::ReleaseService(kRDFResourceManagerCID, mgr);
#endif // defined(CREATE_PROPERTIES_AS_ATTRIBUTES)
return rv;
}
NS_IMETHODIMP
nsRDFElement::UnsetAttribute(nsIAtom* aAttribute, PRBool aNotify)
{
PR_ASSERT(0); // this should be done via RDF
return NS_ERROR_UNEXPECTED;
if (! mAttributes)
return NS_OK; // never set
AttributeKey key(aAttribute);
nsString* old = NS_STATIC_CAST(nsString*, mAttributes->Remove(&key));
delete old;
return NS_OK;
}
static PRBool
rdf_AttributeNameEnumFunc(nsHashKey* key, void* aData, void* closure)
{
nsISupportsArray* array = NS_DYNAMIC_CAST(nsISupportsArray*, closure);
AttributeKey* k = NS_DYNAMIC_CAST(AttributeKey*, key);
nsIAtom* atom;
if (NS_SUCCEEDED(k->GetAtomValue(atom))) {
array->AppendElement(atom);
NS_RELEASE(atom);
}
return PR_TRUE;
}
NS_IMETHODIMP
@ -867,7 +978,18 @@ nsRDFElement::GetAllAttributeNames(nsISupportsArray* aArray, PRInt32& aResult) c
if (! aArray)
return NS_ERROR_NULL_POINTER;
nsresult rv;
nsresult rv = NS_OK;
aArray->Clear(); // XXX or did you want me to append?
if (mAttributes)
mAttributes->Enumerate(rdf_AttributeNameEnumFunc, aArray);
aResult = aArray->Count();
#if defined(CREATE_PROPERTIES_AS_ATTRIBUTES)
// XXX I'm not sure if we should support attributes or not...
nsIRDFResourceManager* mgr = nsnull;
if (NS_FAILED(rv = nsServiceManager::GetService(kRDFResourceManagerCID,
kIRDFResourceManagerIID,
@ -884,9 +1006,6 @@ nsRDFElement::GetAllAttributeNames(nsISupportsArray* aArray, PRInt32& aResult) c
if (NS_FAILED(rv = db->ArcLabelsOut(mResource, properties)))
goto done;
aArray->Clear(); // XXX or did you want me to append?
aResult = 0;
while (NS_SUCCEEDED(rv = properties->HasMoreElements(moreProperties)) && moreProperties) {
nsIRDFNode* property = nsnull;
PRBool tv;
@ -916,21 +1035,28 @@ done:
NS_IF_RELEASE(db);
nsServiceManager::ReleaseService(kRDFResourceManagerCID, mgr);
#endif // defined(CREATE_PROPERTIES_AS_ATTRIBUTES)
return rv;
}
NS_IMETHODIMP
nsRDFElement::GetAttributeCount(PRInt32& aResult) const
{
PR_ASSERT(0);
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv = NS_OK;
aResult = 0;
#if defined(CREATE_PROPERTIES_AS_ATTRIBUTES)
PR_ASSERT(0); // XXX need to write this...
#endif // defined(CREATE_PROPERTIES_AS_ATTRIBUTES)
return rv;
}
static void
rdf_Indent(FILE* out, PRInt32 aIndent)
{
for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
}
NS_IMETHODIMP
@ -949,7 +1075,6 @@ nsRDFElement::List(FILE* out, PRInt32 aIndent) const
rdf_Indent(out, aIndent);
fputs("[RDF ", out);
fputs(tag->GetUnicode(), out);
fputs("\n", out);
NS_RELEASE(tag);
}
@ -972,12 +1097,10 @@ nsRDFElement::List(FILE* out, PRInt32 aIndent) const
nsAutoString v;
GetAttribute(s, v);
rdf_Indent(out, aIndent);
fputs(" ", out);
fputs(s, out);
fputs("=", out);
fputs(v, out);
fputs("\n", out);
}
}
@ -987,7 +1110,6 @@ nsRDFElement::List(FILE* out, PRInt32 aIndent) const
return rv;
}
rdf_Indent(out, aIndent);
fputs("]\n", out);
{
@ -1091,7 +1213,10 @@ nsRDFElement::GetNameSpaceIdentifier(PRInt32& aNameSpaceId)
// nsIRDFContent
NS_IMETHODIMP
nsRDFElement::Init(nsIRDFDocument* doc, nsIRDFNode* resource, PRBool childrenMustBeGenerated)
nsRDFElement::Init(nsIRDFDocument* doc,
const nsString& aTag,
nsIRDFNode* resource,
PRBool childrenMustBeGenerated)
{
NS_PRECONDITION(doc, "null ptr");
NS_PRECONDITION(resource, "null ptr");
@ -1099,8 +1224,9 @@ nsRDFElement::Init(nsIRDFDocument* doc, nsIRDFNode* resource, PRBool childrenMus
if (!doc || !resource)
return NS_ERROR_NULL_POINTER;
mDocument = doc;
NS_ADDREF(mDocument);
mTag = aTag;
mDocument = doc; // not refcounted
mResource = resource;
NS_ADDREF(mResource);
@ -1257,7 +1383,7 @@ nsRDFElement::GenerateChildren(void) const
unconstThis->mChildren->Clear();
}
if (NS_FAILED(rv = mDocument->CreateChildren(unconstThis->mResource,
if (NS_FAILED(rv = mDocument->CreateChildren(unconstThis,
unconstThis->mChildren)))
return rv;

View File

@ -20,17 +20,18 @@
#ifndef nsRDFElement_h___
#define nsRDFElement_h___
#include "nsString.h"
#include "nsIDOMElement.h"
#include "nsIScriptObjectOwner.h"
#include "nsIDOMEventReceiver.h"
#include "nsIRDFContent.h"
#include "nsIJSScriptObject.h"
class nsHashtable;
class nsIContent;
class nsIRDFDocument;
class nsIAtom;
class nsIEventListenerManager;
class nsIHTMLAttributes;
class nsIRDFNode;
class nsISupportsArray;
@ -103,7 +104,10 @@ public:
NS_IMETHOD GetNameSpaceIdentifier(PRInt32& aNameSpeceId);
// nsIRDFContent
NS_IMETHOD Init(nsIRDFDocument* doc, nsIRDFNode* resource, PRBool childrenMustBeGenerated);
NS_IMETHOD Init(nsIRDFDocument* doc,
const nsString& tag,
nsIRDFNode* resource,
PRBool childrenMustBeGenerated);
NS_IMETHOD SetResource(const nsString& aURI);
NS_IMETHOD GetResource(nsString& rURI) const;
@ -132,15 +136,42 @@ public:
virtual void Finalize(JSContext *aContext);
protected:
/** The document in which the element lives. */
nsIRDFDocument* mDocument;
/** The tag's namespace */
nsIAtom* mNameSpace;
/** The tag's namespace ID */
PRInt32 mNameSpaceId;
/** XXX */
void* mScriptObject;
/** The RDF resource that the element corresponds to */
nsIRDFNode* mResource;
/** An array of child nodes */
nsISupportsArray* mChildren;
/** On initialization, set to PR_TRUE if the child nodes must
be generated by walking the RDF graph. Set to PR_FALSE if
the constructor will do it "by hand". */
PRBool mChildrenMustBeGenerated;
/** The element's parent. NOT refcounted. */
nsIContent* mParent;
/** The element's tag */
nsAutoString mTag;
/** A hashtable that maps attribute names to values. Instantiated
lazily if attributes are required */
nsHashtable* mAttributes;
/**
* Dynamically generate the element's children from the RDF graph
*/
nsresult GenerateChildren(void) const;
};

View File

@ -32,40 +32,20 @@
#include "nsIRDFResourceManager.h"
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#include "nsITextContent.h"
#include "nsLayoutCID.h"
#include "nsRDFCID.h"
#include "nsRDFDocument.h"
#include "rdfutil.h"
////////////////////////////////////////////////////////////////////////
static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
static NS_DEFINE_IID(kIRDFResourceManagerIID, NS_IRDFRESOURCEMANAGER_IID);
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID); // XXX grr...
static NS_DEFINE_CID(kRDFResourceManagerCID, NS_RDFRESOURCEMANAGER_CID);
static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID);
////////////////////////////////////////////////////////////////////////
class RDFHTMLDocumentImpl : public nsRDFDocument {
public:
RDFHTMLDocumentImpl();
virtual ~RDFHTMLDocumentImpl();
// nsIRDFDocument interface
NS_IMETHOD CreateChildren(nsIRDFNode* resource, nsISupportsArray* children);
protected:
nsresult NewChild(nsIRDFNode* resource,
nsIRDFContent*& result,
PRBool childrenMustBeGenerated);
nsresult CreateChild(nsIRDFNode* property,
nsIRDFNode* value,
nsIRDFContent*& result);
virtual nsresult CreateChild(nsIRDFNode* property,
nsIRDFNode* value,
nsIRDFContent*& result);
};
////////////////////////////////////////////////////////////////////////
@ -78,121 +58,6 @@ RDFHTMLDocumentImpl::~RDFHTMLDocumentImpl(void)
{
}
NS_IMETHODIMP
RDFHTMLDocumentImpl::CreateChildren(nsIRDFNode* resource, nsISupportsArray* children)
{
nsresult rv;
NS_ASSERTION(mDB, "not initialized");
if (! mDB)
return NS_ERROR_NOT_INITIALIZED;
nsIRDFResourceManager* mgr;
if (NS_FAILED(rv = nsServiceManager::GetService(kRDFResourceManagerCID,
kIRDFResourceManagerIID,
(nsISupports**) &mgr)))
return rv;
nsIRDFCursor* properties = nsnull;
PRBool moreProperties;
#ifdef ONLY_CREATE_RDF_CONTAINERS_AS_CONTENT
if (! rdf_IsContainer(mgr, mDB, resource))
goto done;
#endif
// Create a cursor that'll enumerate all of the outbound arcs
if (NS_FAILED(rv = mDB->ArcLabelsOut(resource, properties)))
goto done;
while (NS_SUCCEEDED(rv = properties->HasMoreElements(moreProperties)) && moreProperties) {
nsIRDFNode* property = nsnull;
PRBool tv;
if (NS_FAILED(rv = properties->GetNext(property, tv /* ignored */)))
break;
nsAutoString uri;
if (NS_FAILED(rv = property->GetStringValue(uri))) {
NS_RELEASE(property);
break;
}
#ifdef ONLY_CREATE_RDF_CONTAINERS_AS_CONTENT
if (! rdf_IsOrdinalProperty(uri)) {
NS_RELEASE(property);
continue;
}
#endif
// Create a second cursor that'll enumerate all of the values
// for all of the arcs.
nsIRDFCursor* values;
if (NS_FAILED(rv = mDB->GetTargets(resource, property, PR_TRUE, values))) {
NS_RELEASE(property);
break;
}
PRBool moreValues;
while (NS_SUCCEEDED(rv = values->HasMoreElements(moreValues)) && moreValues) {
nsIRDFNode* value = nsnull;
if (NS_FAILED(rv = values->GetNext(value, tv /* ignored */)))
break;
// XXX At this point, we need to decide exactly what kind
// of kid to create in the content model. For example, for
// leaf nodes, we probably want to create some kind of
// text element.
nsIRDFContent* child;
if (NS_FAILED(rv = CreateChild(property, value, child))) {
NS_RELEASE(value);
break;
}
// And finally, add the child into the content model
children->AppendElement(child);
NS_RELEASE(child);
NS_RELEASE(value);
}
NS_RELEASE(values);
NS_RELEASE(property);
if (NS_FAILED(rv))
break;
}
done:
NS_IF_RELEASE(properties);
nsServiceManager::ReleaseService(kRDFResourceManagerCID, mgr);
return rv;
}
nsresult
RDFHTMLDocumentImpl::NewChild(nsIRDFNode* resource,
nsIRDFContent*& result,
PRBool childrenMustBeGenerated)
{
nsresult rv;
nsIRDFContent* child;
if (NS_FAILED(rv = NS_NewRDFElement(&child)))
return rv;
if (NS_FAILED(rv = child->Init(this, resource, childrenMustBeGenerated))) {
NS_RELEASE(child);
return rv;
}
result = child;
return NS_OK;
}
nsresult
RDFHTMLDocumentImpl::CreateChild(nsIRDFNode* property,
nsIRDFNode* value,
@ -200,71 +65,62 @@ RDFHTMLDocumentImpl::CreateChild(nsIRDFNode* property,
{
nsresult rv;
nsIRDFContent* child = nsnull;
nsIRDFContent* grandchild = nsnull;
nsIContent* grandchild2 = nsnull;
nsITextContent* text = nsnull;
nsIDocument* doc = nsnull;
nsAutoString v;
// Construct a new child node. We will explicitly be generating
// all of this node's kids, so set the
// "children-must-be-generated" flag to false.
if (NS_FAILED(rv = NewChild(property, child, PR_FALSE)))
goto error;
// The tag we'll use for the new child will be the string value of
// the property.
nsAutoString tag;
if (NS_FAILED(rv = property->GetStringValue(tag)))
goto done;
// If this is NOT a resource, then construct a grandchild which is
// just a vanilla text node.
if (! rdf_IsResource(value)) {
if (NS_FAILED(rv = value->GetStringValue(v)))
goto error;
if (IsTreeProperty(property) || rdf_IsContainer(mResourceMgr, mDB, value)) {
// If it's a tree property, then create a child element whose
// value is the value of the property. We'll also attach an "ID="
// attribute to the new child; e.g.,
//
// <parent>
// <property id="value">
// <!-- recursively generated -->
// </property>
// ...
// </parent>
if (NS_FAILED(rv = nsRepository::CreateInstance(kTextNodeCID,
nsnull,
kIContentIID,
(void**) &grandchild2)))
goto error;
nsAutoString s;
if (NS_FAILED(rv = QueryInterface(kIDocumentIID, (void**) &doc)))
goto error;
// PR_TRUE indicates that we want the child to dynamically
// generate its own kids.
if (NS_FAILED(rv = NewChild(tag, value, child, PR_TRUE)))
goto done;
if (NS_FAILED(rv = grandchild2->SetDocument(doc, PR_FALSE)))
goto error;
if (NS_FAILED(rv = value->GetStringValue(s)))
goto done;
NS_RELEASE(doc);
if (NS_FAILED(rv = child->SetAttribute("ID", s, PR_FALSE)))
goto done;
if (NS_FAILED(rv = grandchild2->QueryInterface(kITextContentIID, (void**) &text)))
goto error;
result = child;
NS_ADDREF(result);
}
else {
// Otherwise, it's not a tree property. So we'll just create a
// new element for the property, and a simple text node for
// its value; e.g.,
//
// <parent>
// <property>value</property>
// ...
// </parent>
if (NS_FAILED(rv = text->SetText(v.GetUnicode(), v.Length(), PR_FALSE)))
goto error;
if (NS_FAILED(rv = NewChild(tag, property, child, PR_FALSE)))
goto done;
NS_RELEASE(text);
if (NS_FAILED(rv = AttachTextNode(child, value)))
goto done;
// hook it up to the child
if (NS_FAILED(rv = grandchild2->SetParent(child)))
goto error;
if (NS_FAILED(rv = child->AppendChildTo(NS_STATIC_CAST(nsIContent*, grandchild2), PR_TRUE)))
goto error;
result = child;
NS_ADDREF(result);
}
// Construct a grandchild which is another RDF resource node. This
// node *will* need to recursively generate its children on
// demand, so set the children-must-be-generated flag to true.
if (NS_FAILED(rv = NewChild(value, grandchild, PR_TRUE)))
goto error;
if (NS_FAILED(rv = child->AppendChildTo(NS_STATIC_CAST(nsIContent*, grandchild), PR_TRUE)))
goto error;
// whew!
result = child;
return NS_OK;
error:
NS_IF_RELEASE(text);
NS_IF_RELEASE(doc);
NS_IF_RELEASE(grandchild);
done:
NS_IF_RELEASE(child);
return rv;
}

View File

@ -24,17 +24,108 @@
#include "nsIRDFResourceManager.h"
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#include "nsLayoutCID.h"
#include "nsRDFCID.h"
#include "nsRDFDocument.h"
#include "rdfutil.h"
// XXX just a stub for now.
////////////////////////////////////////////////////////////////////////
class RDFTreeDocumentImpl : public nsRDFDocument {
public:
RDFTreeDocumentImpl();
virtual ~RDFTreeDocumentImpl();
protected:
virtual nsresult CreateChild(nsIRDFNode* property,
nsIRDFNode* value,
nsIRDFContent*& result);
};
////////////////////////////////////////////////////////////////////////
RDFTreeDocumentImpl::RDFTreeDocumentImpl(void)
{
}
RDFTreeDocumentImpl::~RDFTreeDocumentImpl(void)
{
}
nsresult
RDFTreeDocumentImpl::CreateChild(nsIRDFNode* property,
nsIRDFNode* value,
nsIRDFContent*& result)
{
static const char* kTRTag = "TR";
static const char* kTDTag = "TD";
nsresult rv;
nsIRDFContent* child = nsnull;
if (IsTreeProperty(property) || rdf_IsContainer(mResourceMgr, mDB, value)) {
// If it's a tree property, then create a child element whose
// value is the value of the property. We'll also attach an "ID="
// attribute to the new child; e.g.,
//
// <parent>
// <tr id="value">
// <!-- recursively generated -->
// </tr>
// ...
// </parent>
nsAutoString s;
// PR_TRUE indicates that we want the child to dynamically
// generate its own kids.
if (NS_FAILED(rv = NewChild(kTRTag, value, child, PR_TRUE)))
goto done;
if (NS_FAILED(rv = value->GetStringValue(s)))
goto done;
if (NS_FAILED(rv = child->SetAttribute("ID", s, PR_FALSE)))
goto done;
result = child;
NS_ADDREF(result);
}
else {
// Otherwise, it's not a tree property. So we'll just create a
// new element for the property, and a simple text node for
// its value; e.g.,
//
// <parent>
// <td>value</td>
// ...
// </parent>
if (NS_FAILED(rv = NewChild(kTDTag, property, child, PR_FALSE)))
goto done;
if (NS_FAILED(rv = AttachTextNode(child, value)))
goto done;
result = child;
NS_ADDREF(result);
}
done:
NS_IF_RELEASE(child);
return rv;
}
////////////////////////////////////////////////////////////////////////
nsresult NS_NewRDFTreeDocument(nsIRDFDocument** result)
{
*result = nsnull;
return NS_NOINTERFACE;
nsIRDFDocument* doc = new RDFTreeDocumentImpl();
if (! doc)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(doc);
*result = doc;
return NS_OK;
}

View File

@ -344,6 +344,7 @@ nsSimpleDataBase::nsSimpleDataBase(void)
{
NS_INIT_REFCNT();
#if 0
// Add standard data sources here.
// XXX this is so wrong.
nsIRDFDataSource* ds;
@ -354,6 +355,7 @@ nsSimpleDataBase::nsSimpleDataBase(void)
AddDataSource(ds);
NS_RELEASE(ds);
}
#endif
}

View File

@ -45,8 +45,13 @@ DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, resource);
////////////////////////////////////////////////////////////////////////
PRBool
rdf_IsOrdinalProperty(const nsString& uri)
rdf_IsOrdinalProperty(const nsIRDFNode* property)
{
nsAutoString uri;
if (NS_FAILED(property->GetStringValue(uri)))
return PR_FALSE;
if (uri.Find(kRDFNameSpaceURI) != 0)
return PR_FALSE;

View File

@ -32,7 +32,7 @@ class nsString;
* rdf:_2, etc.
*/
PRBool
rdf_IsOrdinalProperty(const nsString& uri);
rdf_IsOrdinalProperty(const nsIRDFNode* property);
/**