[gxml] Fixed GNode implementations of DomNode for insert, replace, append and remove nodes



commit abe8023eba87908aec0a9e2c7a8068eb298f48f2
Author: Daniel Espinosa <esodan gmail com>
Date:   Tue Jul 19 19:12:27 2016 -0500

    Fixed GNode implementations of DomNode for insert, replace, append and remove nodes
    
    * Added Unit Tests

 gxml/DomNode.vala          |    8 +++---
 gxml/GXmlNode.vala         |   64 +++++++++++++++++++++++++++++++++++++------
 test/DomGDocumentTest.vala |   54 +++++++++++++++++++++++++++++++++++-
 3 files changed, 111 insertions(+), 15 deletions(-)
---
diff --git a/gxml/DomNode.vala b/gxml/DomNode.vala
index 0652f75..54355f4 100644
--- a/gxml/DomNode.vala
+++ b/gxml/DomNode.vala
@@ -76,10 +76,10 @@ public interface GXml.DomNode : GLib.Object, GXml.DomEventTarget {
   public abstract string? lookup_namespace_uri (string? prefix);
   public abstract bool is_default_namespace (string? nspace);
 
-  public abstract DomNode insert_before (DomNode node, DomNode? child);
-  public abstract DomNode append_child (DomNode node);
-  public abstract DomNode replace_child (DomNode node, DomNode child);
-  public abstract DomNode remove_child (DomNode child);
+  public abstract DomNode insert_before (DomNode node, DomNode? child) throws GLib.Error;
+  public abstract DomNode append_child (DomNode node) throws GLib.Error;
+  public abstract DomNode replace_child (DomNode node, DomNode child) throws GLib.Error;
+  public abstract DomNode remove_child (DomNode child) throws GLib.Error;
 }
 
 public errordomain GXml.DomError {
diff --git a/gxml/GXmlNode.vala b/gxml/GXmlNode.vala
index 12891cf..cb11953 100644
--- a/gxml/GXmlNode.vala
+++ b/gxml/GXmlNode.vala
@@ -284,22 +284,68 @@ public abstract class GXml.GNode : Object,
     return false;
   }
 
-  public DomNode insert_before (DomNode node, DomNode? child) {
-    int i = children_nodes.index_of (child as GXml.Node);
-    children_nodes.insert (i, (node as GXml.Node));
-    return node;
-  }
-  public DomNode append_child (DomNode node) {
+  public DomNode insert_before (DomNode node, DomNode? child) throws GLib.Error {
+    if (!(node is GXml.GNode))
+      throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid atemp to add invalid node type"));
+    if (child != null && !this.contains (child))
+      throw new DomError.NOT_FOUND_ERROR (_("Can't find child to insert node before"));
+    if (!(this is DomDocument
+          || this is DomElement
+          || this is DomDocumentFragment))
+      throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid atemp to insert a node"));
+    if (!(node is DomDocumentFragment
+          || node is DomDocumentType
+          || node is DomElement
+          || node is DomText
+          || node is DomProcessingInstruction
+          || node is DomComment))
+      throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid atemp to insert an invalid node type"));
+    if ((node is DomText && this is DomDocument)
+          || (node is DomDocumentType && !(this is DomDocument)))
+      throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid atemp to insert a document's type or text node 
to a invalid parent"));
+    //FIXME: We should follow steps for DOM4 observers in https://www.w3.org/TR/dom/#concept-node-pre-insert
+    if (child != null) {
+      int i = this.children_nodes.index_of (child as GXml.Node);
+      children_nodes.insert (i, (node as GXml.Node));
+      return node;
+    }
     children_nodes.add ((node as GXml.Node));
     return node;
   }
-  public DomNode replace_child (DomNode node, DomNode child) {
+  public DomNode append_child (DomNode node) throws GLib.Error {
+    return insert_before (node, null);
+  }
+  public DomNode replace_child (DomNode node, DomNode child) throws GLib.Error {
+    if (!(node is GXml.GNode))
+      throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid atemp to add invalid node type"));
+    if (child == null || !this.contains (child))
+      throw new DomError.NOT_FOUND_ERROR (_("Can't find child node to replace or child have a different 
parent"));
+    if (!(this is DomDocument
+          || this is DomElement
+          || this is DomDocumentFragment))
+      throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid atemp to insert a node"));
+    if (!(node is DomDocumentFragment
+          || node is DomDocumentType
+          || node is DomElement
+          || node is DomText
+          || node is DomProcessingInstruction
+          || node is DomComment))
+      throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid atemp to insert an invalid node type"));
+    if ((node is DomText && this is DomDocument)
+          || (node is DomDocumentType && !(this is DomDocument)))
+      throw new DomError.HIERARCHY_REQUEST_ERROR (_("Invalid atemp to insert a document's type or text node 
to a invalid parent"));
+    //FIXME: Checks for HierarchyRequestError for https://www.w3.org/TR/dom/#concept-node-replace
     int i = children_nodes.index_of ((child as GXml.Node));
     children_nodes.remove_at (i);
-    children_nodes.insert (i, (node as GXml.Node));
+    if (i < children_nodes.size)
+      children_nodes.insert (i, (node as GXml.Node));
+    if (i >= children_nodes.size)
+      child_nodes.add (node);
     return child;
   }
-  public DomNode remove_child (DomNode child) {
+  public DomNode remove_child (DomNode child) throws GLib.Error {
+    if (!this.contains (child))
+      throw new DomError.NOT_FOUND_ERROR (_("Can't find child node to remove or child have a different 
parent"));
     int i = children_nodes.index_of ((child as GXml.Node));
     return (DomNode) children_nodes.remove_at (i);
   }
diff --git a/test/DomGDocumentTest.vala b/test/DomGDocumentTest.vala
index 611e06d..80952ce 100644
--- a/test/DomGDocumentTest.vala
+++ b/test/DomGDocumentTest.vala
@@ -119,7 +119,8 @@ static const string HTMLDOC ="
                        assert (lc[1].get_attribute ("class") == "black block");
                });
                Test.add_func ("/gxml/dom/node", () => {
-                       GLib.message ("Doc: "+HTMLDOC);
+                       try {
+                       Test.message ("Doc: "+HTMLDOC);
                        GDocument doc = new GDocument.from_string (HTMLDOC);
                        assert (doc is DomDocument);
                        assert (doc.document_element.children.size == 1);
@@ -191,10 +192,59 @@ static const string HTMLDOC ="
                        assert (!ng.is_default_namespace ("gxml:http://git.gnome.org/browse/gxml";));
                        var ng2 = doc.create_element_ns ("http://live.gnome.org/GXml";, "OtherNode");
                        b.child_nodes.add (ng2);
-                       GLib.message ("BODY:"+(b as GXml.Node).to_string ());
                        assert (ng2.lookup_prefix ("http://live.gnome.org/GXml";) == null);
                        assert (ng2.lookup_namespace_uri (null) == "http://live.gnome.org/GXml";);
                        assert (ng2.is_default_namespace ("http://live.gnome.org/GXml";));
+                       var pn = doc.create_element ("p") as DomElement;
+                       pn.set_attribute ("id", "insertedp01");
+                       var p = doc.document_element.children[0];
+                       assert (p.node_name == "body");
+                       var cp0 = p.children[0];
+                       assert (cp0.node_name == "p");
+                       assert (cp0.get_attribute ("class") == "black");
+                       assert (p.contains (cp0));
+                       assert (cp0.parent_node.contains (cp0));
+                       p.insert_before (pn, cp0);
+                       var ppn = p.children[0];
+                       assert (ppn.node_name == "p");
+                       assert (ppn.has_attribute ("id"));
+                       assert (ppn.get_attribute ("id") == "insertedp01");
+                       var pn2 = doc.create_element ("p") as DomElement;
+                       pn2.set_attribute ("id", "newp");
+                       p.append_child (pn2);
+                       assert (p.children.length == 7);
+                       assert (p.children[6] is DomElement);
+                       assert (p.children[6].node_name == "p");
+                       assert (p.children[6].get_attribute ("id") == "newp");
+                       var pn3 = doc.create_element ("p") as DomElement;
+                       pn3.set_attribute ("id", "newp1");
+                       pn3.set_attribute ("class", "black");
+                       p.replace_child (pn3, pn2);
+                       assert (p.children.length == 7);
+                       assert (p.children[6] is DomElement);
+                       assert (p.children[6].node_name == "p");
+                       assert (p.children[6].get_attribute ("id") == "newp1");
+                       assert (p.children[6].get_attribute ("class") == "black");
+                       var pn4 = doc.create_element ("p") as DomElement;
+                       pn4.set_attribute ("id", "newp2");
+                       pn4.set_attribute ("class", "black");
+                       p.replace_child (pn4, p.child_nodes[0]);
+                       GLib.message ("BODY:"+(p as GXml.Node).to_string ());
+                       assert (p.children.length == 7);
+                       assert (p.children[0] is DomElement);
+                       assert (p.children[0].node_name == "p");
+                       assert (p.children[0].get_attribute ("id") == "newp2");
+                       assert (p.children[0].get_attribute ("class") == "black");
+                       p.remove_child (p.children[0]);
+                       assert (p.children.length == 6);
+                       assert (p.children[0] is DomElement);
+                       assert (p.children[0].node_name == "p");
+                       assert (!p.has_attribute ("id"));
+                       assert (p.children[0].get_attribute ("class") == "black");
+                       } catch (GLib.Error e) {
+                               GLib.message ("Error: "+e.message);
+                               assert_not_reached ();
+                       }
                });
        }
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]