From d05a1b9db342cbedbd1bd03e6f8e84898930a959 Mon Sep 17 00:00:00 2001
From: "waterson%netscape.com" <waterson%netscape.com>
Date: Wed, 17 Feb 1999 11:57:57 +0000
Subject: [PATCH] Added nsIDOMElementObserver interface, implemented
 OnSetAttribute(). Fixed so that a shared namespace manager is held.

---
 rdf/content/src/nsRDFXULBuilder.cpp | 153 ++++++++++++++++++++++++----
 1 file changed, 132 insertions(+), 21 deletions(-)

diff --git a/rdf/content/src/nsRDFXULBuilder.cpp b/rdf/content/src/nsRDFXULBuilder.cpp
index 7648bf0ce16b0..c795c909691a1 100644
--- a/rdf/content/src/nsRDFXULBuilder.cpp
+++ b/rdf/content/src/nsRDFXULBuilder.cpp
@@ -37,6 +37,8 @@
 #include "nsIAtom.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
+#include "nsIDOMElement.h"
+#include "nsIDOMElementObserver.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeObserver.h"
 #include "nsINameSpaceManager.h"
@@ -102,7 +104,8 @@ DEFINE_RDF_VOCAB(XUL_NAMESPACE_URI_PREFIX, XUL, element);
 
 class RDFXULBuilderImpl : public nsIRDFContentModelBuilder,
                           public nsIRDFObserver,
-                          public nsIDOMNodeObserver
+                          public nsIDOMNodeObserver,
+                          public nsIDOMElementObserver
 {
 private:
     nsIRDFCompositeDataSource* mDB;
@@ -111,7 +114,8 @@ private:
 
     // pseudo-constants
     static PRInt32 gRefCnt;
-    static nsIRDFService*  gRDFService;
+    static nsIRDFService*       gRDFService;
+    static nsINameSpaceManager* gNameSpaceManager;
 
     static PRInt32  kNameSpaceID_RDF;
     static PRInt32  kNameSpaceID_XUL;
@@ -150,6 +154,9 @@ public:
     // nsIDOMNodeObserver interface
     NS_DECL_IDOMNODEOBSERVER
 
+    // nsIDOMElementObserver interface
+    NS_DECL_IDOMELEMENTOBSERVER
+
     // Implementation methods
     nsresult AppendChild(nsIContent* aElement,
                          nsIRDFNode* aValue);
@@ -199,17 +206,18 @@ public:
 ////////////////////////////////////////////////////////////////////////
 // Pseudo-constants
 
-PRInt32         RDFXULBuilderImpl::gRefCnt = 0;
-nsIRDFService*  RDFXULBuilderImpl::gRDFService = nsnull;
+PRInt32              RDFXULBuilderImpl::gRefCnt;
+nsIRDFService*       RDFXULBuilderImpl::gRDFService;
+nsINameSpaceManager* RDFXULBuilderImpl::gNameSpaceManager;
 
 PRInt32         RDFXULBuilderImpl::kNameSpaceID_RDF = kNameSpaceID_Unknown;
 PRInt32         RDFXULBuilderImpl::kNameSpaceID_XUL = kNameSpaceID_Unknown;
 
-nsIAtom*        RDFXULBuilderImpl::kContainerAtom         = nsnull;
-nsIAtom*        RDFXULBuilderImpl::kContentsGeneratedAtom = nsnull;
-nsIAtom*        RDFXULBuilderImpl::kIdAtom                = nsnull;
-nsIAtom*        RDFXULBuilderImpl::kDataSourcesAtom       = nsnull;
-nsIAtom*        RDFXULBuilderImpl::kTreeAtom              = nsnull;
+nsIAtom*        RDFXULBuilderImpl::kContainerAtom;
+nsIAtom*        RDFXULBuilderImpl::kContentsGeneratedAtom;
+nsIAtom*        RDFXULBuilderImpl::kIdAtom;
+nsIAtom*        RDFXULBuilderImpl::kDataSourcesAtom;
+nsIAtom*        RDFXULBuilderImpl::kTreeAtom;
 
 nsIRDFResource* RDFXULBuilderImpl::kRDF_instanceOf;
 nsIRDFResource* RDFXULBuilderImpl::kRDF_nextVal;
@@ -246,19 +254,16 @@ RDFXULBuilderImpl::RDFXULBuilderImpl(void)
     if (gRefCnt++ == 0) {
         // XXX should hold on to the manager for the duration, as well.
         nsresult rv;
-        nsINameSpaceManager* mgr;
         if (NS_SUCCEEDED(rv = nsRepository::CreateInstance(kNameSpaceManagerCID,
                                                            nsnull,
                                                            kINameSpaceManagerIID,
-                                                           (void**) &mgr))) {
+                                                           (void**) &gNameSpaceManager))) {
 
-            rv = mgr->RegisterNameSpace(kXULNameSpaceURI, kNameSpaceID_XUL);
+            rv = gNameSpaceManager->RegisterNameSpace(kXULNameSpaceURI, kNameSpaceID_XUL);
             NS_ASSERTION(NS_SUCCEEDED(rv), "unable to register XUL namespace");
 
-            rv = mgr->RegisterNameSpace(kRDFNameSpaceURI, kNameSpaceID_RDF);
+            rv = gNameSpaceManager->RegisterNameSpace(kRDFNameSpaceURI, kNameSpaceID_RDF);
             NS_ASSERTION(NS_SUCCEEDED(rv), "unable to register RDF namespace");
-
-            NS_RELEASE(mgr);
         }
         else {
             NS_ERROR("couldn't create namepsace manager");
@@ -309,6 +314,8 @@ RDFXULBuilderImpl::~RDFXULBuilderImpl(void)
         if (gRDFService)
             nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService);
 
+        NS_IF_RELEASE(gNameSpaceManager);
+
         NS_IF_RELEASE(kRDF_instanceOf);
         NS_IF_RELEASE(kRDF_nextVal);
         NS_IF_RELEASE(kRDF_type);
@@ -338,23 +345,22 @@ RDFXULBuilderImpl::QueryInterface(REFNSIID iid, void** aResult)
     if (iid.Equals(kIRDFContentModelBuilderIID) ||
         iid.Equals(kISupportsIID)) {
         *aResult = NS_STATIC_CAST(nsIRDFContentModelBuilder*, this);
-        NS_ADDREF(this);
-        return NS_OK;
     }
     else if (iid.Equals(kIRDFObserverIID)) {
         *aResult = NS_STATIC_CAST(nsIRDFObserver*, this);
-        NS_ADDREF(this);
-        return NS_OK;
     }
     else if (iid.Equals(nsIDOMNodeObserver::IID())) {
         *aResult = NS_STATIC_CAST(nsIDOMNodeObserver*, this);
-        NS_ADDREF(this);
-        return NS_OK;
+    }
+    else if (iid.Equals(nsIDOMElementObserver::IID())) {
+        *aResult = NS_STATIC_CAST(nsIDOMElementObserver*, this);
     }
     else {
         *aResult = nsnull;
         return NS_NOINTERFACE;
     }
+    NS_ADDREF(this);
+    return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////
@@ -828,6 +834,111 @@ RDFXULBuilderImpl::OnAppendChild(nsIDOMNode* aParent, nsIDOMNode* aNewChild)
 }
 
 
+////////////////////////////////////////////////////////////////////////
+// nsIDOMElementObserver interface
+
+
+NS_IMETHODIMP
+RDFXULBuilderImpl::OnSetAttribute(nsIDOMElement* aElement, const nsString& aName, const nsString& aValue)
+{
+    nsresult rv;
+
+    nsCOMPtr<nsIRDFResource> resource;
+    if (NS_FAILED(rv = GetDOMNodeResource(aElement, getter_AddRefs(resource)))) {
+        // XXX it's not a resource element, so there's no assertions
+        // we need to make on the back-end. Should we just do the
+        // update?
+        return NS_OK;
+    }
+
+    // Get the nsIContent interface, it's a bit more utilitarian
+    nsCOMPtr<nsIContent> element( do_QueryInterface(aElement) );
+    if (! element) {
+        NS_ERROR("element doesn't support nsIContent");
+        return NS_ERROR_UNEXPECTED;
+    }
+
+    // Split the property name into its namespace and tag components
+    PRInt32  nameSpaceID;
+    nsCOMPtr<nsIAtom> nameAtom;
+    if (NS_FAILED(rv = element->ParseAttributeString(aName, *getter_AddRefs(nameAtom), nameSpaceID))) {
+        NS_ERROR("unable to parse attribute string");
+        return rv;
+    }
+
+    NS_ASSERTION(nameAtom != nsnull, "no name");
+    NS_ASSERTION(nameSpaceID != kNameSpaceID_Unknown, "no namespace");
+
+    // construct a fully-qualified URI from the namespace/tag pair.
+    nsAutoString uri;
+    gNameSpaceManager->GetNameSpaceURI(nameSpaceID, uri);
+
+    // XXX check to see if we need to insert a '/' or a '#'
+    nsAutoString tag(nameAtom->GetUnicode());
+    if (uri.Last() != '#' && uri.Last() != '/' && tag.First() != '#')
+        uri.Append('#');
+
+    uri.Append(tag);
+
+    nsCOMPtr<nsIRDFResource> property;
+    if (NS_FAILED(rv = gRDFService->GetUnicodeResource(uri, getter_AddRefs(property)))) {
+        NS_ERROR("unable to get property resource");
+        return rv;
+    }
+
+    // Unassert the old value, if there was one.
+    nsAutoString oldValue;
+    if (NS_CONTENT_ATTR_HAS_VALUE == element->GetAttribute(nameSpaceID, nameAtom, oldValue)) {
+        nsCOMPtr<nsIRDFLiteral> value;
+        if (NS_FAILED(rv = gRDFService->GetLiteral(oldValue, getter_AddRefs(value)))) {
+            NS_ERROR("unable to construct literal");
+            return rv;
+        }
+
+        rv = mDB->Unassert(resource, property, value);
+        NS_ASSERTION(NS_SUCCEEDED(rv), "unable to unassert old property value");
+    }
+
+    // Assert the new value
+    {
+        nsCOMPtr<nsIRDFLiteral> value;
+        if (NS_FAILED(rv = gRDFService->GetLiteral(aValue, getter_AddRefs(value)))) {
+            NS_ERROR("unable to construct literal");
+            return rv;
+        }
+
+        if (NS_FAILED(rv = mDB->Assert(resource, property, value, PR_TRUE))) {
+            NS_ERROR("unable to assert new property value");
+            return rv;
+        }
+    }
+    
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+RDFXULBuilderImpl::OnRemoveAttribute(nsIDOMElement* aElement, const nsString& aName)
+{
+    NS_NOTYETIMPLEMENTED("write me!");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+RDFXULBuilderImpl::OnSetAttributeNode(nsIDOMElement* aElement, nsIDOMAttr* aNewAttr)
+{
+    NS_NOTYETIMPLEMENTED("write me!");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+RDFXULBuilderImpl::OnRemoveAttributeNode(nsIDOMElement* aElement, nsIDOMAttr* aOldAttr)
+{
+    NS_NOTYETIMPLEMENTED("write me!");
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
 ////////////////////////////////////////////////////////////////////////
 // Implementation methods
 
-- 
GitLab