[gxml] Split of XParser.read_current_node in methods



commit d05b41c3bdd839c901857190fad2eeee4f13fa26
Author: Daniel Espinosa <esodan gmail com>
Date:   Wed Jan 18 12:43:51 2017 -0600

    Split of XParser.read_current_node in methods

 gxml/GomAttr.vala              |    1 -
 gxml/GomCollections.vala       |    2 +-
 gxml/GomElement.vala           |   16 ++-
 gxml/XParser.vala              |  329 +++++++++++++++++++++++++++++++++++++++-
 test/GomSerializationTest.vala |   19 ++-
 test/gxml-performance.vala     |   14 ++-
 6 files changed, 361 insertions(+), 20 deletions(-)
---
diff --git a/gxml/GomAttr.vala b/gxml/GomAttr.vala
index 89ca0ff..2c0ac34 100644
--- a/gxml/GomAttr.vala
+++ b/gxml/GomAttr.vala
@@ -26,7 +26,6 @@ using Gee;
 
 public class GXml.GomAttr : GXml.GomNode, GXml.DomAttr {
   protected string _namespace_uri;
-  protected string _prefix;
   public string local_name { owned get { return _local_name; } }
   public string name {
     owned get {
diff --git a/gxml/GomCollections.vala b/gxml/GomCollections.vala
index be068a8..ee62328 100644
--- a/gxml/GomCollections.vala
+++ b/gxml/GomCollections.vala
@@ -266,7 +266,7 @@ public abstract class GXml.BaseCollection : Object {
 public class GXml.GomArrayList : GXml.BaseCollection, GomCollection {
   public override bool validate_add (int index, DomElement element) throws GLib.Error {
 #if DEBUG
-    GLib.message ("Adding node:"+n.node_name);
+    GLib.message ("Adding node:"+element.node_name);
 #endif
     return true;
   }
diff --git a/gxml/GomElement.vala b/gxml/GomElement.vala
index 96cf77d..a0284da 100644
--- a/gxml/GomElement.vala
+++ b/gxml/GomElement.vala
@@ -39,16 +39,24 @@ public class GXml.GomElement : GomNode,
   protected Attributes _attributes;
   // Convenient Serialization methods
   /**
-   * Uses element's {@link GomDocument} to parse an XML file, deserializing it.
+   * Parsing a URI file.
+   */
+  public void read_from_uri (string uri) throws GLib.Error {
+    this.read_from_file (File.new_for_uri (uri));
+  }
+  /**
+   * Parses an XML file, deserializing it over {@link GomElemen}.
    */
   public void read_from_file (GLib.File f) throws GLib.Error {
-    (this.owner_document as GomDocument).read_from_file (f);
+    var parser = new XParser (this);
+    parser.read_file (f, null);
   }
   /**
-   * Uses element's {@link GomDocument} to parse an XML string, deserializing it.
+   * Parses an XML string, deserializing it over {@link GomElemen}.
    */
   public void read_from_string (string str) throws GLib.Error {
-    (this.owner_document as GomDocument).read_from_string (str);
+    var parser = new XParser (this);
+    parser.read_string (str, null);
   }
   /**
    * Uses element's {@link GomDocument} to write an XML to a file, serializing it.
diff --git a/gxml/XParser.vala b/gxml/XParser.vala
index 6f272af..f26d6f1 100644
--- a/gxml/XParser.vala
+++ b/gxml/XParser.vala
@@ -104,8 +104,326 @@ public class GXml.XParser : Object, GXml.Parser {
     while (read_current_node (_node, true));
   }
   /**
-   * Read current node from a TextReader
+   * Reads a node using current parser.
    */
+  public void read_node (DomNode node) {
+    if (node is DomElement) read_element (node as DomElement);
+    read_child_nodes (node);
+  }
+  /**
+   * Creates a new {@link DomElement} and append it as a child of parent.
+   */
+  public DomElement? create_element (DomNode parent) {
+    DomElement n = null;
+#if DEBUG
+    GLib.message ("Creating a standard element: "
+                  +tr.const_local_name ());
+    GLib.message ("Reading: Element: "+tr.const_local_name ());
+#endif
+    string prefix = tr.prefix ();
+    if (prefix != null) {
+#if DEBUG
+      GLib.message ("Is namespaced element");
+#endif
+      string nsuri = tr.lookup_namespace (prefix);
+      n = _document.create_element_ns (nsuri, tr.prefix () +":"+ tr.const_local_name ());
+    } else
+      n = _document.create_element (tr.const_local_name ());
+    parent.append_child (n);
+    return n;
+  }
+  /**
+   * Reads a {@link DomElement}
+   */
+  public void read_element (DomElement element) throws GLib.Error {
+    var nattr = tr.attribute_count ();
+#if DEBUG
+    GLib.message ("Number of Attributes:"+nattr.to_string ());
+#endif
+    for (int i = 0; i < nattr; i++) {
+      var c = tr.move_to_attribute_no (i);
+#if DEBUG
+      GLib.message ("Current Attribute: "+i.to_string ());
+#endif
+      if (c != 1) {
+        throw new DomError.HIERARCHY_REQUEST_ERROR (_("Parsing ERROR: Fail to move to attribute number: 
%i").printf (i));
+      }
+      if (tr.is_namespace_decl () == 1) {
+#if DEBUG
+        GLib.message ("Is Namespace Declaration...");
+#endif
+        string nsp = tr.const_local_name ();
+        string aprefix = tr.prefix ();
+        tr.read_attribute_value ();
+        if (tr.node_type () == Xml.ReaderType.TEXT) {
+          string ansuri = tr.read_string ();
+#if DEBUG
+          GLib.message ("Property Read: "+aprefix+":"+nsp+"="+ansuri);
+#endif
+          string ansp = nsp;
+          if (nsp != "xmlns")
+            ansp = aprefix+":"+nsp;
+#if DEBUG
+          GLib.message ("To append: "+ansp+"="+ansuri);
+#endif
+          element.set_attribute_ns ("http://www.w3.org/2000/xmlns/";,
+                                               ansp, ansuri);
+        }
+      } else {
+        var attrname = tr.const_local_name ();
+        string prefix = tr.prefix ();
+#if DEBUG
+        GLib.message ("Attribute: "+tr.const_local_name ());
+#endif
+        tr.read_attribute_value ();
+        if (tr.node_type () == Xml.ReaderType.TEXT) {
+          var attrval = tr.read_string ();
+#if DEBUG
+          GLib.message ("Attribute:"+attrname+" Value: "+attrval);
+#endif
+          bool processed = false;
+          if (node is GomObject) {
+            processed = (element as GomObject).set_attribute (attrname, attrval);
+          }
+          if (!processed) {
+            if (prefix != null) {
+#if DEBUG
+              GLib.message ("Prefix found: "+prefix);
+#endif
+              string nsuri = null;
+              if (prefix == "xml")
+                nsuri = "http://www.w3.org/2000/xmlns/";;
+              else
+                nsuri = tr.lookup_namespace (prefix);
+              element.set_attribute_ns (nsuri, prefix+":"+attrname, attrval);
+            } else
+              element.set_attribute (attrname, attrval);
+          }
+        }
+      }
+    }
+  }
+  /**
+   * Iterates in all child nodes and append them to node.
+   */
+  private void read_child_nodes (DomNode node) throws GLib.Error {
+    if (tr.is_empty_element () == 1) return;
+    DomNode n = null;
+    bool cont = true;
+    while (cont) {
+      int res = tr.read ();
+      if (res == -1)
+        throw new ParserError.INVALID_DATA_ERROR (_("Can't read node data"));
+      if (res == 0) {
+#if DEBUG
+        GLib.message ("ReadNode: No more nodes");
+#endif
+        return;
+      }
+      var t = tr.node_type ();
+      switch (t) {
+      case Xml.ReaderType.NONE:
+#if DEBUG
+        GLib.message ("Type NONE");
+#endif
+        res = tr.read ();
+        if (res == -1)
+          throw new ParserError.INVALID_DATA_ERROR (_("Can't read node data"));
+        break;
+      case Xml.ReaderType.ATTRIBUTE:
+#if DEBUG
+        GLib.message ("Type ATTRIBUTE");
+#endif
+        break;
+      case Xml.ReaderType.TEXT:
+        var txtval = tr.read_string ();
+#if DEBUG
+        GLib.message ("Type TEXT");
+        GLib.message ("ReadNode: Text Node : '"+txtval+"'");
+#endif
+        n = _document.create_text_node (txtval);
+        node.append_child (n);
+        break;
+      case Xml.ReaderType.CDATA:
+        break;
+      case Xml.ReaderType.ENTITY_REFERENCE:
+#if DEBUG
+        GLib.message ("Type ENTITY_REFERENCE");
+#endif
+        break;
+      case Xml.ReaderType.ENTITY:
+#if DEBUG
+        GLib.message ("Type ENTITY");
+#endif
+        break;
+      case Xml.ReaderType.PROCESSING_INSTRUCTION:
+        var pit = tr.const_local_name ();
+        var pival = tr.value ();
+#if DEBUG
+        GLib.message ("Type PROCESSING_INSTRUCTION");
+        GLib.message ("ReadNode: PI Node : '"+pit+"' : '"+pival+"'");
+#endif
+        n = node.owner_document.create_processing_instruction (pit,pival);
+        node.append_child (n);
+        break;
+      case Xml.ReaderType.COMMENT:
+        var commval = tr.value ();
+#if DEBUG
+        GLib.message ("Type COMMENT");
+        GLib.message ("ReadNode: Comment Node : '"+commval+"'");
+#endif
+        n = node.owner_document.create_comment (commval);
+        node.append_child (n);
+        break;
+      case Xml.ReaderType.DOCUMENT:
+#if DEBUG
+        GLib.message ("Type DOCUMENT");
+#endif
+        break;
+      case Xml.ReaderType.DOCUMENT_TYPE:
+#if DEBUG
+        GLib.message ("Type DOCUMENT_TYPE");
+#endif
+        break;
+      case Xml.ReaderType.DOCUMENT_FRAGMENT:
+#if DEBUG
+        GLib.message ("Type DOCUMENT_FRAGMENT");
+#endif
+        break;
+      case Xml.ReaderType.NOTATION:
+#if DEBUG
+        GLib.message ("Type NOTATION");
+#endif
+        break;
+      case Xml.ReaderType.WHITESPACE:
+#if DEBUG
+        GLib.message ("Type WHITESPACE");
+#endif
+        break;
+      case Xml.ReaderType.SIGNIFICANT_WHITESPACE:
+        var stxtval = tr.read_string ();
+#if DEBUG
+        GLib.message ("ReadNode: Text Node : '"+stxtval+"'");
+        GLib.message ("Type SIGNIFICANT_WHITESPACE");
+#endif
+        n = _document.create_text_node (stxtval);
+        node.append_child (n);
+        break;
+      case Xml.ReaderType.END_ELEMENT:
+#if DEBUG
+        GLib.message ("Type END_ELEMENT");
+#endif
+        return;
+      case Xml.ReaderType.END_ENTITY:
+#if DEBUG
+        GLib.message ("Type END_ENTITY");
+#endif
+        return;
+      case Xml.ReaderType.XML_DECLARATION:
+#if DEBUG
+        GLib.message ("Type XML_DECLARATION");
+#endif
+        break;
+      case Xml.ReaderType.ELEMENT:
+#if DEBUG
+        GLib.debug ("Type ELEMENT_NODE");
+#endif
+        if (!read_element_property (node, out n))
+          n = create_element (node);
+        if (n == null) return;
+        read_element (n as DomElement);
+        read_child_nodes (n);
+        break;
+      }
+    }
+  }
+  /**
+   * Creates a new {@link DomElement} as a child of parent: for current
+   * read node, only if :
+   *
+   * # parent: have a property as {@link DomElement} type and current
+   * node have same local name as property element.
+   * # parent: have a property as {@link GomCollection} type and current
+   * node have same local name as collection {@link GomCollection.items_name}
+   *
+   * Returns: true if element is set to a new object, it is set as a parent:
+   * property or has been added to a parent: collection property.
+   */
+  public bool read_element_property (DomNode parent,
+                  out DomNode element) throws GLib.Error {
+    if (!(parent is GomObject)) return false;
+    GomElement node = parent as GomElement;
+#if DEBUG
+    GLib.message ("Searching for Properties Nodes for:"+
+                  (node as DomElement).local_name+
+                  " Current node name: "+ tr.const_local_name ());
+#endif
+    foreach (ParamSpec pspec in
+              (node as GomObject).get_property_element_list ()) {
+      if (pspec.value_type.is_a (typeof (GomCollection))) {
+#if DEBUG
+        GLib.message (" Is Collection in: "+(node as DomElement).local_name);
+#endif
+        GomCollection col;
+        Value vc = Value (pspec.value_type);
+        node.get_property (pspec.name, ref vc);
+        col = vc.get_object () as GomCollection;
+        if (col == null) {
+#if DEBUG
+          GLib.message ("Initializing Collection property...");
+#endif
+          col = Object.new (pspec.value_type,
+                            "element", node) as GomCollection;
+          vc.set_object (col);
+          node.set_property (pspec.name, vc);
+        }
+        if (col.items_type == GLib.Type.INVALID
+            || !(col.items_type.is_a (typeof (GomObject)))) {
+          throw new DomError.INVALID_NODE_TYPE_ERROR
+                      (_("Invalid object type set to Collection"));
+        }
+        if (col.items_name == "" || col.items_name == null) {
+          throw new DomError.INVALID_NODE_TYPE_ERROR
+                      (_("Invalid DomElement name for objects in Collection"));
+        }
+        if (col.element == null || !(col.element is GomElement)) {
+          throw new DomError.INVALID_NODE_TYPE_ERROR
+                      (_("Invalid Element set to Collection"));
+        }
+        if (col.items_name.down () == tr.const_local_name ().down ()) {
+#if DEBUG
+          GLib.message ("Is a Node to append in collection");
+#endif
+          if (node.owner_document == null)
+            throw new DomError.HIERARCHY_REQUEST_ERROR
+                        (_("No document is set to node"));
+          var obj = Object.new (col.items_type,
+                                "owner-document", _document);
+#if DEBUG
+          GLib.message ("Object Element to add in Collection: "
+                          +(_node as DomNode).node_name);
+#endif
+          col.append (obj as DomElement);
+          element = obj as DomNode;
+          return true;
+        }
+      } else {
+        var obj = Object.new (pspec.value_type,
+                              "owner-document", _document);
+        if ((obj as DomElement).local_name.down ()
+               == tr.const_local_name ().down ()) {
+          Value v = Value (pspec.value_type);
+          read_current_node (obj as DomNode, true, true);
+          node.append_child (obj as DomNode);
+          v.set_object (obj);
+          node.set_property (pspec.name, v);
+          element = obj as DomNode;
+          return true;
+        }
+      }
+    }
+    return false;
+  }
   public bool read_current_node (DomNode node,
                                 bool read_current = false,
                                 bool read_property = false)
@@ -238,12 +556,10 @@ public class GXml.XParser : Object, GXml.Parser {
                         .printf ((node as DomElement).local_name));
       }
       if (!isproperty) {
-#if DEBUG
-        GLib.message ("No object Property is set. Creating a standard element: "
-                        +tr.const_local_name ());
-#endif
         if (node is DomDocument || !read_current) {
 #if DEBUG
+          GLib.message ("No object Property is set. Creating a standard element: "
+                        +tr.const_local_name ());
           GLib.message ("No deserializing current node");
           if (isempty) GLib.message ("Is Empty node:"+node.node_name);
           GLib.message ("ReadNode: Element: "+tr.const_local_name ());
@@ -336,9 +652,6 @@ public class GXml.XParser : Object, GXml.Parser {
       GLib.message ("Getting child nodes in element");
 #endif
       while (read_current_node (n) == true);
-#if DEBUG
-      GLib.message ("Current Document: "+node.document.to_string ());
-#endif
       break;
     case Xml.ReaderType.ATTRIBUTE:
 #if DEBUG
diff --git a/test/GomSerializationTest.vala b/test/GomSerializationTest.vala
index 0437ab8..7fb54fa 100644
--- a/test/GomSerializationTest.vala
+++ b/test/GomSerializationTest.vala
@@ -114,6 +114,7 @@ class GomBook : GomElement
     resumes = Object.new (typeof (GomResume.Map),
                                       "element", this)
                                     as GomResume.Map;
+    assert (this.local_name == "Book");
   }
   public class Array : GomArrayList {
     construct { initialize (typeof (GomBook)); }
@@ -124,13 +125,23 @@ class GomBookStore : GomElement
 {
   [Description (nick="::name")]
   public string name { get; set; }
+  public GomBook.Array books { get; set; }
   construct {
+    message ("Initialization of GomBookStore");
     initialize ("BookStore");
-    assert (this != null);
     books = Object.new (typeof(GomBook.Array),"element", this) as GomBook.Array;
-    assert_not_reached ();
   }
-  public GomBook.Array books { get; set; }
+  public string to_string () {
+    var parser = new XParser (this);
+    string s = "";
+    try {
+      s = parser.write_string ();
+    } catch (GLib.Error e) {
+      GLib.message ("Error: "+e.message);
+      assert_not_reached ();
+    }
+    return s;
+  }
 }
 
 class GomSerializationTest : GXmlTest  {
@@ -243,6 +254,8 @@ class GomSerializationTest : GXmlTest  {
     construct { initialize_with_key (typeof (Book), "name"); }
   }
   public class BookStore : GomElement {
+    [Description (nick="::Name")]
+    public string name { get; set; }
     public Books books { get; set; }
     construct {
       initialize ("BookStore");
diff --git a/test/gxml-performance.vala b/test/gxml-performance.vala
index 0852830..f5ae85e 100644
--- a/test/gxml-performance.vala
+++ b/test/gxml-performance.vala
@@ -242,17 +242,24 @@ public class Performance
       try {
         double time;
         GomDocument doc;
-        var f = GLib.File.new_for_path (GXmlTestConfig.TEST_DIR + "/test-large.xml");
+        var f = GLib.File.new_for_path (GXmlTestConfig.TEST_DIR + "/test-collection.xml");
         assert (f.query_exists ());
         Test.timer_start ();
         var bs = new GomBookStore ();
-        assert_not_reached ();
         assert (bs != null);
+        assert (bs.books != null);
+        assert (bs.books.element != null);
+        assert (bs.books.items_type.is_a (typeof(GomBook)));
+        assert (bs.books.items_name == "Book");
+        GLib.message ("Empty XML:"+bs.to_string ());
         bs.read_from_file (f);
+        GLib.message ("XML:"+bs.to_string ());
+        assert_not_reached ();
         assert (bs.local_name == "BookStore");
+        assert (bs.get_attribute ("name") != null);
+        assert (bs.name != null);
         assert (bs.name == "The Great Book");
         time = Test.timer_elapsed ();
-        assert_not_reached ();
         Test.minimized_result (time, "deserialize/performance: %g seconds", time);
         var of = GLib.File.new_for_path (GXmlTestConfig.TEST_SAVE_DIR + "/test-large-new.xml");
         Test.timer_start ();
@@ -266,6 +273,7 @@ public class Performance
         assert (bs.owner_document.document_element.node_name.down () == "bookstore");
         assert (bs.child_nodes.length > 0);
         var ns = bs.get_elements_by_tag_name ("book");
+        GLib.message ("Query Books: "+ns.length.to_string ());
         assert (ns.length > 0);
         GLib.message ("Books: "+bs.books.length.to_string ());
         /*assert (bs.books.length > 0);


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