diff --git a/rdf/include/nsIRDFDocument.h b/rdf/include/nsIRDFDocument.h index 9c89cd88980..4af2d96c925 100644 --- a/rdf/include/nsIRDFDocument.h +++ b/rdf/include/nsIRDFDocument.h @@ -57,7 +57,7 @@ public: * "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; + NS_IMETHOD CreateChildren(nsIRDFContent* element) = 0; // XXX these should probably be strings so you can mess with them // via the DOM. diff --git a/rdf/src/nsRDFDocument.cpp b/rdf/src/nsRDFDocument.cpp index 76f07eac24e..bb9e91d323b 100644 --- a/rdf/src/nsRDFDocument.cpp +++ b/rdf/src/nsRDFDocument.cpp @@ -1157,7 +1157,7 @@ nsRDFDocument::GetDataBase(nsIRDFDataBase*& result) NS_IMETHODIMP -nsRDFDocument::CreateChildren(nsIRDFContent* element, nsISupportsArray* children) +nsRDFDocument::CreateChildren(nsIRDFContent* element) { nsresult rv; @@ -1205,24 +1205,16 @@ nsRDFDocument::CreateChildren(nsIRDFContent* element, nsISupportsArray* children 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))) { + if (NS_SUCCEEDED(rv = values->GetNext(value, tv /* ignored */))) { + // At this point, the specific nsRDFDocument + // implementations will create an appropriate child + // element (or elements). + rv = AddChild(element, property, value); NS_RELEASE(value); - break; } - // And finally, add the child into the content model - children->AppendElement(child); - - NS_RELEASE(child); - NS_RELEASE(value); + if (NS_FAILED(rv)) + break; } NS_RELEASE(values); diff --git a/rdf/src/nsRDFDocument.h b/rdf/src/nsRDFDocument.h index 6559bed70a9..28d4d61938f 100644 --- a/rdf/src/nsRDFDocument.h +++ b/rdf/src/nsRDFDocument.h @@ -194,7 +194,7 @@ public: NS_IMETHOD Init(void); NS_IMETHOD SetRootResource(nsIRDFNode* resource); NS_IMETHOD GetDataBase(nsIRDFDataBase*& result); - NS_IMETHOD CreateChildren(nsIRDFContent* element, nsISupportsArray* children); + NS_IMETHOD CreateChildren(nsIRDFContent* element); NS_IMETHOD AddTreeProperty(nsIRDFNode* resource); NS_IMETHOD RemoveTreeProperty(nsIRDFNode* resource); @@ -214,9 +214,9 @@ protected: nsIRDFContent*& result, PRBool childrenMustBeGenerated); - virtual nsresult CreateChild(nsIRDFNode* property, - nsIRDFNode* value, - nsIRDFContent*& result) = 0; + virtual nsresult AddChild(nsIRDFContent* parent, + nsIRDFNode* property, + nsIRDFNode* value) = 0; nsIArena* mArena; nsVoidArray mObservers; diff --git a/rdf/src/nsRDFElement.cpp b/rdf/src/nsRDFElement.cpp index b320dbaa956..61b7e666789 100644 --- a/rdf/src/nsRDFElement.cpp +++ b/rdf/src/nsRDFElement.cpp @@ -1045,6 +1045,9 @@ nsRDFElement::GetAttributeCount(PRInt32& aResult) const nsresult rv = NS_OK; aResult = 0; + if (mAttributes) + aResult += mAttributes->Count(); + #if defined(CREATE_PROPERTIES_AS_ATTRIBUTES) PR_ASSERT(0); // XXX need to write this... #endif // defined(CREATE_PROPERTIES_AS_ATTRIBUTES) @@ -1062,9 +1065,6 @@ rdf_Indent(FILE* out, PRInt32 aIndent) NS_IMETHODIMP nsRDFElement::List(FILE* out, PRInt32 aIndent) const { - if (! mResource) - return NS_ERROR_NOT_INITIALIZED; - nsresult rv; { @@ -1219,9 +1219,12 @@ nsRDFElement::Init(nsIRDFDocument* doc, PRBool childrenMustBeGenerated) { NS_PRECONDITION(doc, "null ptr"); - NS_PRECONDITION(resource, "null ptr"); - if (!doc || !resource) + // XXX Not using this because of a hack in nsRDFTreeDocument: need + // to expose generic XML elements! + //NS_PRECONDITION(resource, "null ptr"); + + if (!doc /* || !resource // XXX ibid */) return NS_ERROR_NULL_POINTER; mTag = aTag; @@ -1229,15 +1232,13 @@ nsRDFElement::Init(nsIRDFDocument* doc, mDocument = doc; // not refcounted mResource = resource; - NS_ADDREF(mResource); + NS_IF_ADDREF(mResource); mChildrenMustBeGenerated = childrenMustBeGenerated; - if (! childrenMustBeGenerated) { - nsresult rv; - if (NS_FAILED(rv = NS_NewISupportsArray(&mChildren))) - return rv; - } + nsresult rv; + if (NS_FAILED(rv = NS_NewISupportsArray(&mChildren))) + return rv; return NS_OK; } @@ -1383,11 +1384,17 @@ nsRDFElement::GenerateChildren(void) const unconstThis->mChildren->Clear(); } - if (NS_FAILED(rv = mDocument->CreateChildren(unconstThis, - unconstThis->mChildren))) - return rv; - + // Clear this value *first*, so we can re-enter the nsIContent + // getters if needed. unconstThis->mChildrenMustBeGenerated = PR_FALSE; + + if (NS_FAILED(rv = mDocument->CreateChildren(unconstThis))) { + // Well, maybe it was a transient error. This'll let use try + // again some time in the future. + unconstThis->mChildrenMustBeGenerated = PR_TRUE; + return rv; + } + return NS_OK; } diff --git a/rdf/src/nsRDFHTMLDocument.cpp b/rdf/src/nsRDFHTMLDocument.cpp index 4705f1a503f..2a2033ef0c4 100644 --- a/rdf/src/nsRDFHTMLDocument.cpp +++ b/rdf/src/nsRDFHTMLDocument.cpp @@ -43,9 +43,9 @@ public: virtual ~RDFHTMLDocumentImpl(); protected: - virtual nsresult CreateChild(nsIRDFNode* property, - nsIRDFNode* value, - nsIRDFContent*& result); + virtual nsresult AddChild(nsIRDFContent* parent, + nsIRDFNode* property, + nsIRDFNode* value); }; //////////////////////////////////////////////////////////////////////// @@ -59,9 +59,9 @@ RDFHTMLDocumentImpl::~RDFHTMLDocumentImpl(void) } nsresult -RDFHTMLDocumentImpl::CreateChild(nsIRDFNode* property, - nsIRDFNode* value, - nsIRDFContent*& result) +RDFHTMLDocumentImpl::AddChild(nsIRDFContent* parent, + nsIRDFNode* property, + nsIRDFNode* value) { nsresult rv; nsIRDFContent* child = nsnull; @@ -96,9 +96,6 @@ RDFHTMLDocumentImpl::CreateChild(nsIRDFNode* property, 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 @@ -115,11 +112,10 @@ RDFHTMLDocumentImpl::CreateChild(nsIRDFNode* property, if (NS_FAILED(rv = AttachTextNode(child, value))) goto done; - - result = child; - NS_ADDREF(result); } + rv = parent->AppendChildTo(child, PR_TRUE); + done: NS_IF_RELEASE(child); return rv; diff --git a/rdf/src/nsRDFTreeDocument.cpp b/rdf/src/nsRDFTreeDocument.cpp index 768dbb770ca..88767d1be30 100644 --- a/rdf/src/nsRDFTreeDocument.cpp +++ b/rdf/src/nsRDFTreeDocument.cpp @@ -29,15 +29,36 @@ //////////////////////////////////////////////////////////////////////// +static const char* kChildrenTag = "CHILDREN"; +static const char* kFolderTag = "FOLDER"; +static const char* kItemTag = "ITEM"; + +//////////////////////////////////////////////////////////////////////// + class RDFTreeDocumentImpl : public nsRDFDocument { public: RDFTreeDocumentImpl(); virtual ~RDFTreeDocumentImpl(); protected: - virtual nsresult CreateChild(nsIRDFNode* property, - nsIRDFNode* value, - nsIRDFContent*& result); + virtual nsresult + AddChild(nsIRDFContent* parent, + nsIRDFNode* property, + nsIRDFNode* value); + + nsresult + EnsureChildrenElement(nsIContent* parent, + nsIContent*& result); + + nsresult + AddTreeChild(nsIRDFContent* parent, + nsIRDFNode* property, + nsIRDFNode* value); + + nsresult + AddPropertyChild(nsIRDFContent* parent, + nsIRDFNode* property, + nsIRDFNode* value); }; //////////////////////////////////////////////////////////////////////// @@ -50,70 +71,178 @@ RDFTreeDocumentImpl::~RDFTreeDocumentImpl(void) { } + nsresult -RDFTreeDocumentImpl::CreateChild(nsIRDFNode* property, - nsIRDFNode* value, - nsIRDFContent*& result) +RDFTreeDocumentImpl::EnsureChildrenElement(nsIContent* parent, + nsIContent*& result) { - static const char* kTRTag = "TR"; - static const char* kTDTag = "TD"; + nsresult rv; + result = nsnull; // reasonable default + + nsIAtom* childrenTag = NS_NewAtom(kChildrenTag); + if (! childrenTag) + return NS_ERROR_OUT_OF_MEMORY; + + PRInt32 count; + if (NS_FAILED(rv = parent->ChildCount(count))) { + NS_RELEASE(childrenTag); + return rv; + } + + for (PRInt32 i = 0; i < count; ++i) { + nsIContent* kid; + if (NS_FAILED(rv = parent->ChildAt(i, kid))) + break; + + nsIAtom* tag; + if (NS_FAILED(rv = parent->GetTag(tag))) { + NS_RELEASE(kid); + break; + } + + if (tag == childrenTag) { + NS_RELEASE(tag); + NS_RELEASE(childrenTag); + result = kid; // no need to addref, got it from ChildAt(). + return NS_OK; + } + + NS_RELEASE(tag); + NS_RELEASE(kid); + } + + NS_RELEASE(childrenTag); + + if (NS_FAILED(rv)) + return rv; + + // if we get here, we need to construct a new element. + + // XXX this should be a generic XML element, not an nsRDFElement + nsIRDFContent* children = nsnull; + + if (NS_FAILED(rv = NS_NewRDFElement(&children))) + goto done; + + if (NS_FAILED(rv = children->Init(this, kChildrenTag, nsnull /* XXX */, PR_FALSE))) + goto done; + + if (NS_FAILED(rv = parent->AppendChildTo(children, PR_FALSE))) + goto done; + + result = children; + NS_ADDREF(result); + +done: + NS_IF_RELEASE(children); + return rv; +} + +nsresult +RDFTreeDocumentImpl::AddTreeChild(nsIRDFContent* parent, + nsIRDFNode* property, + nsIRDFNode* value) +{ + // If it's a tree property, then we need to add the new child + // element to a special "children" element in the parent. The + // child element's value will be the value of the + // property. We'll also attach an "ID=" attribute to the new + // child; e.g., + // + // + // ... + // + // + // + // + // + // ... + // nsresult rv; nsIRDFContent* child = nsnull; + nsIContent* children = nsnull; + nsAutoString s; - 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., - // - // - // - // - // - // ... - // + // Ensure that the element exists on the parent. + if (NS_FAILED(rv = EnsureChildrenElement(parent, children))) + goto done; - nsAutoString s; + // Create a new child that represents the "value" + // resource. PR_TRUE indicates that we want the child to + // dynamically generate its own kids. + if (NS_FAILED(rv = NewChild(kFolderTag, value, child, PR_TRUE))) + goto done; - // 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 = value->GetStringValue(s))) - goto done; + if (NS_FAILED(rv = child->SetAttribute("ID", s, PR_FALSE))) + goto done; - if (NS_FAILED(rv = child->SetAttribute("ID", s, PR_FALSE))) - goto done; +#define ALL_NODES_OPEN_HACK +#ifdef ALL_NODES_OPEN_HACK + if (NS_FAILED(rv = child->SetAttribute("OPEN", "TRUE", PR_FALSE))) + goto done; +#endif - 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., - // - // - // value - // ... - // + // Finally, add the thing to the element. + children->AppendChildTo(child, PR_TRUE); - if (NS_FAILED(rv = NewChild(kTDTag, property, child, PR_FALSE))) - goto done; +done: + NS_IF_RELEASE(child); + NS_IF_RELEASE(children); + return rv; +} - if (NS_FAILED(rv = AttachTextNode(child, value))) - goto done; - result = child; - NS_ADDREF(result); - } +nsresult +RDFTreeDocumentImpl::AddPropertyChild(nsIRDFContent* parent, + nsIRDFNode* property, + nsIRDFNode* value) +{ + // 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., + // + // + // value + // ... + // + nsresult rv; + nsIRDFContent* child = nsnull; + + nsAutoString s; + + if (NS_FAILED(rv = property->GetStringValue(s))) + goto done; + + if (NS_FAILED(rv = NewChild(s, property, child, PR_FALSE))) + goto done; + + if (NS_FAILED(rv = AttachTextNode(child, value))) + goto done; + + rv = parent->AppendChildTo(child, PR_TRUE); done: NS_IF_RELEASE(child); return rv; } +nsresult +RDFTreeDocumentImpl::AddChild(nsIRDFContent* parent, + nsIRDFNode* property, + nsIRDFNode* value) +{ + if (IsTreeProperty(property) || rdf_IsContainer(mResourceMgr, mDB, value)) { + return AddTreeChild(parent, property, value); + } + else { + return AddPropertyChild(parent, property, value); + } +} + ////////////////////////////////////////////////////////////////////////