[gxml] DomDocument: API improvements



commit 7da6bd6a7b08a1d452ce6df18dce3050fd5567b7
Author: Daniel Espinosa <esodan gmail com>
Date:   Thu Mar 21 13:06:23 2019 -0600

    DomDocument: API improvements
    
    Parser API improvementes, more reusable code

 gxml/DomDocument.vala                 | 105 ++++++++++++++++++++----
 gxml/DomElement.vala                  |   8 +-
 gxml/GXmlDocument.vala                |  43 +++++-----
 gxml/GomDocument.vala                 | 145 +++++++++++++---------------------
 gxml/GomElement.vala                  |  29 ++++---
 gxml/GomObject.vala                   |  19 +++--
 gxml/Makefile.am                      |   1 +
 gxml/Parser.vala                      |  62 ++++++---------
 gxml/XParser.vala                     |  51 +++++-------
 gxml/meson.build                      |   1 +
 test/GElementTest.vala                |  13 +++
 test/GXmlDocumentPerformanceTest.vala |  34 ++++----
 test/GXmlTest.vala                    |   5 +-
 test/GomDocumentTest.vala             |  39 +++++++++
 test/GomSerializationTest.vala        |   6 +-
 15 files changed, 322 insertions(+), 239 deletions(-)
---
diff --git a/gxml/DomDocument.vala b/gxml/DomDocument.vala
index a671132..86ee5e4 100644
--- a/gxml/DomDocument.vala
+++ b/gxml/DomDocument.vala
@@ -1,7 +1,7 @@
 /* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
 /*
  *
- * Copyright (C) 2016  Daniel Espinosa <esodan gmail com>
+ * Copyright (C) 2016-2019  Daniel Espinosa <esodan gmail com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -71,65 +71,142 @@ public interface GXml.DomDocument : GLib.Object,
    */
   public abstract DomTreeWalker create_tree_walker (DomNode root, int what_to_show = (int) 0xFFFFFFFF, 
DomNodeFilter? filter = null);
 
-
   /**
    * Writes a dump XML representation of document to a file.
    */
-  public virtual void write_file (GLib.File file) throws GLib.Error {}
+  public virtual void write_file (GLib.File file, Cancellable? cancellable = null) throws GLib.Error
+  {
+    Parser parser = get_xml_parser ();
+    parser.write_file (file);
+  }
   /**
    * Writes asynchronically a dump XML representation of document to a file.
    */
   public virtual async void write_file_async (GLib.File file,
-                            Cancellable? cancellable = null) throws GLib.Error {}
+                            Cancellable? cancellable = null) throws GLib.Error
+  {
+    Parser parser = get_xml_parser ();
+    yield parser.write_file_async (file);
+  }
   /**
    * Writes a dump XML representation of document to a stream.
    */
-  public virtual void write_stream (GLib.OutputStream stream) throws GLib.Error {}
+  public virtual void write_stream (GLib.OutputStream stream,
+                            Cancellable? cancellable = null) throws GLib.Error
+  {
+    Parser parser = get_xml_parser ();
+    parser.write_stream (stream);
+  }
   /**
    * Writes a dump XML representation of document to a stream.
    */
   public virtual async void write_stream_async (GLib.OutputStream stream,
-                            Cancellable? cancellable = null) throws GLib.Error {}
+                            Cancellable? cancellable = null) throws GLib.Error
+  {
+    Parser parser = get_xml_parser ();
+    yield parser.write_stream_async (stream);
+  }
   /**
    * Creates an {@link GLib.InputStream} to write a string representation
    * in XML of {@link GomDocument}
    */
   public virtual InputStream create_stream () throws GLib.Error {
-    return new MemoryInputStream ();
+    Parser parser = get_xml_parser ();
+    return parser.create_stream ();
   }
   /**
    * Creates an {@link GLib.InputStream} to write a string representation
    * in XML of {@link GomDocument}
    */
   public virtual async InputStream create_stream_async (Cancellable? cancellable = null) throws GLib.Error {
-    return new MemoryInputStream ();
+    Parser parser = get_xml_parser ();
+    parser.cancellable = cancellable;
+    return yield parser.create_stream_async ();
   }
   /**
    * Serialize {@link GomDocument} to a string.
    */
-  public virtual string write_string () throws GLib.Error { return ""; }
+  public virtual string write_string (Cancellable? cancellable = null) throws GLib.Error {
+    Parser parser = get_xml_parser ();
+    parser.cancellable = cancellable;
+    return parser.write_string ();
+  }
   /**
    * Serialize {@link GomDocument} to a string.
    */
-  public virtual async string write_string_async (Cancellable? cancellable = null) throws GLib.Error { 
return ""; }
+  public virtual async string write_string_async (Cancellable? cancellable = null) throws GLib.Error
+  {
+    Idle.add (write_string_async.callback);
+    yield;
+    return write_string (cancellable);
+  }
   /**
    * Reads a file contents and parse it to document.
    */
-  public virtual void read_from_file (GLib.File file) throws GLib.Error {}
+  public virtual void read_from_file (GLib.File file,
+                              Cancellable? cancellable = null) throws GLib.Error {
+    Parser parser = get_xml_parser ();
+    parser.cancellable = cancellable;
+    parser.read_file (file);
+  }
   /**
    * Reads a file contents and parse it to document.
    */
   public virtual async void read_from_file_async (GLib.File file,
-                              Cancellable? cancellable = null) throws GLib.Error {}
+                              Cancellable? cancellable = null) throws GLib.Error {
+    Parser parser = get_xml_parser ();
+    parser.cancellable = cancellable;
+    yield parser.read_file_async (file);
+  }
   /**
    * Reads a string and parse it to document.
    */
-  public virtual void read_from_string (string str) throws GLib.Error {}
+  public virtual void read_from_string (string str, Cancellable? cancellable = null) throws GLib.Error {
+    Parser parser = get_xml_parser ();
+    parser.cancellable = cancellable;
+    parser.read_string (str);
+  }
   /**
    * Reads a string and parse it to document.
    */
   public virtual async void read_from_string_async (string str,
-                              Cancellable? cancellable = null) throws GLib.Error {}
+                              Cancellable? cancellable = null) throws GLib.Error {
+    Parser parser = get_xml_parser ();
+    parser.cancellable = cancellable;
+    yield parser.read_string_async (str);
+  }
+  /**
+   * Reads a string and parse it to document.
+   */
+  public virtual void read_from_stream (GLib.InputStream stream,
+                              Cancellable? cancellable = null) throws GLib.Error
+  {
+    Parser parser = get_xml_parser ();
+    parser.cancellable = cancellable;
+    parser.read_stream (stream);
+  }
+  /**
+   * Reads a string and parse it to document.
+   */
+  public virtual async void read_from_stream_async (GLib.InputStream stream,
+                              Cancellable? cancellable = null) throws GLib.Error
+  {
+    Parser parser = get_xml_parser ();
+    parser.cancellable = cancellable;
+    yield parser.read_stream_async (stream);
+  }
+  /**
+   * Returns a default XML {@link Parser} to use with this object.
+   */
+  public abstract Parser get_xml_parser ();
+  /**
+   * Set a default XML {@link Parser} to use with this object.
+   */
+  public abstract void set_xml_parser (Parser parser);
+}
+
+public errordomain GXml.DomDocumentError {
+  FILE_NOT_FOUND_ERROR
 }
 
 public interface GXml.DomXMLDocument : GLib.Object, GXml.DomDocument {}
diff --git a/gxml/DomElement.vala b/gxml/DomElement.vala
index 6d80dfc..8fb9d98 100644
--- a/gxml/DomElement.vala
+++ b/gxml/DomElement.vala
@@ -108,7 +108,7 @@ public interface GXml.DomElement : GLib.Object,
   /**
    * Parses an XML string, deserializing it over {@link GomElement}.
    */
-  public virtual void read_from_string (string str) throws GLib.Error {}
+  public virtual void read_from_string (string str, Cancellable? cancellable = null) throws GLib.Error {}
   /**
    * Parses an XML string, deserializing it over {@link GomElement}.
    */
@@ -117,7 +117,7 @@ public interface GXml.DomElement : GLib.Object,
   /**
    * Serialize {@link GomElement} to a string.
    */
-  public virtual string write_string () throws GLib.Error { return ""; }
+  public virtual string write_string (Cancellable? cancellable = null) throws GLib.Error { return ""; }
   /**
    * Serialize asinchronically {@link GomElement} to a string.
    */
@@ -125,8 +125,8 @@ public interface GXml.DomElement : GLib.Object,
   /**
    * Uses element's {@link GomDocument} to write an XML to a file, serializing it.
    */
-  public virtual void write_file (GLib.File f) throws GLib.Error {
-    owner_document.write_file (f);
+  public virtual void write_file (GLib.File f, Cancellable? cancellable = null) throws GLib.Error {
+    owner_document.write_file (f, cancellable);
   }
   /**
    * Uses element's {@link GomDocument} to write asynchronically an XML to a file, serializing it.
diff --git a/gxml/GXmlDocument.vala b/gxml/GXmlDocument.vala
index 19e3006..2944a57 100644
--- a/gxml/GXmlDocument.vala
+++ b/gxml/GXmlDocument.vala
@@ -1,7 +1,7 @@
 /* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
 /* GDocument.vala
  *
- * Copyright (C) 2016  Daniel Espinosa <esodan gmail com>
+ * Copyright (C) 2016-2019  Daniel Espinosa <esodan gmail com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -38,8 +38,9 @@ public class GXml.GDocument : GXml.GNode,
                               GXml.DomXMLDocument,
                               GXml.XPathContext
 {
-  protected Xml.Doc* doc;
+  internal Xml.Doc* doc;
   protected Xml.Buffer _buffer;
+  protected Parser _parser = null;
 
   public GDocument () {
     doc = new Xml.Doc ();
@@ -55,33 +56,31 @@ public class GXml.GDocument : GXml.GNode,
   public GDocument.from_file (GLib.File file, int options = 0, Cancellable? cancel = null) throws GLib.Error 
{
     if (!file.query_exists ())
       throw new DocumentError.INVALID_DOCUMENT_ERROR (_("File doesn't exist"));
-    var b = new MemoryOutputStream.resizable ();
-    b.splice (file.read (), 0);
-    this.from_string ((string) b.data, options);
+    var parser = new GParser (this);
+    parser.cancellable = cancel;
+    parser.read_stream (file.read ());
   }
 
   public GDocument.from_string (string str, int options = 0) throws GLib.Error {
-    Xml.reset_last_error ();
-    doc = Xml.Parser.parse_memory (str, (int) str.length);
-    var e = Xml.get_last_error ();
-    if (e != null) {
-      var errmsg = "Parser Error for string";
-      string s = libxml2_error_to_string (e);
-      if (s != null)
-        errmsg = ".  ";
-      throw new GXml.Error.PARSER (errmsg);
-    }
-    if (doc == null)
-      doc = new Xml.Doc ();
+    var parser = new GParser (this);
+    parser.read_string (str);
   }
   public GDocument.from_stream (GLib.InputStream istream) throws GLib.Error {
-    var b = new MemoryOutputStream.resizable ();
-    b.splice (istream, 0);
-    if (b.data == null)
-      throw new DocumentError.INVALID_DOCUMENT_ERROR (_("stream doesn't provide data"));
-    this.from_string ((string) b.data);
+    var parser = new GParser (this);
+    parser.read_stream (istream);
   }
   public GDocument.from_doc (Xml.Doc doc) { this.doc = doc; }
+
+  public Parser GXml.DomDocument.get_xml_parser () {
+    if (_parser != null) {
+      return _parser;
+    }
+    return new GParser (this);
+  }
+  public void set_xml_parser (Parser parser) {
+    _parser = parser;
+  }
+
   // GXml.Node
   public override bool set_namespace (string uri, string? prefix)
   {
diff --git a/gxml/GomDocument.vala b/gxml/GomDocument.vala
index fb46a57..9a75075 100644
--- a/gxml/GomDocument.vala
+++ b/gxml/GomDocument.vala
@@ -1,7 +1,7 @@
 /* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
 /*
  *
- * Copyright (C) 2016  Daniel Espinosa <esodan gmail com>
+ * Copyright (C) 2016-2019  Daniel Espinosa <esodan gmail com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -27,6 +27,9 @@ using GXml;
  *
  * This object avoids pre and post XML parsing, by using a one step parsing
  * to translate text XML tree to an GObject based tree.
+ *
+ * If you define a property in a derived class with a nick's name '::ROOT' it
+ * will be initialized and used as root node to parse documents.
  */
 public class GXml.GomDocument : GomNode,
                               DomParentNode,
@@ -42,6 +45,7 @@ public class GXml.GomDocument : GomNode,
   protected string _character_set;
   protected string _content_type;
   protected GXml.DomEvent _constructor;
+  protected Parser _parser;
   public DomImplementation implementation { get { return _implementation; } }
   public string url { get { return _url; } }
   public string document_uri { get { return _url; } }
@@ -73,6 +77,7 @@ public class GXml.GomDocument : GomNode,
     _compat_mode = "";
     _character_set = "utf-8";
     _content_type = "application/xml";
+    _parser = null;
   }
   public GomDocument () {}
   public GomDocument.from_path (string path) throws GLib.Error {
@@ -91,113 +96,69 @@ public class GXml.GomDocument : GomNode,
    * Creates a document parsing a file.
    */
   public GomDocument.from_file (GLib.File file) throws GLib.Error {
-    var parser = new XParser (this);
-    parser.read_file (file, null);
+    Parser parser = get_xml_parser ();
+    parser.read_file (file);
+  }
+
+  private GomElement get_root_gom_element () {
+    Object obj = null;
+    foreach (ParamSpec spec in this.get_class ().list_properties ()) {
+      if ("::" in spec.get_nick () && spec.name.down () == "root") {
+        if (spec.value_type.is_a (typeof (GomElement))) {
+          Value val = Value (Type.OBJECT);
+          get_property (spec.name, ref val);
+          var roote = val.get_object () as GomElement;
+          if (roote == null) {
+            obj = Object.new (spec.value_type,"owner-document", this.owner_document);
+            try { this.append_child (obj as GomElement); }
+            catch (GLib.Error e) {
+              warning (_("Error while attempting to instantiate root property object: %s").printf 
(e.message));
+              obj = null;
+            }
+            val.set_object (obj);
+            set_property (spec.name, val);
+          }
+        }
+      }
+    }
+    return obj as GomElement;
   }
 
   /**
    * Creates a document parsing a stream.
    */
   public GomDocument.from_stream (GLib.InputStream stream) throws GLib.Error {
-    var parser = new XParser (this);
-    parser.read_stream (stream, null);
+    Parser parser = get_xml_parser ();
+    parser.read_stream (stream);
   }
 
   /**
    * Creates a document parsing a string.
    */
   public GomDocument.from_string (string str) throws GLib.Error {
-    var parser = new XParser (this);
-    parser.read_string (str, null);
+    Parser parser = get_xml_parser ();
+    parser.read_string (str);
   }
 
-  /**
-   * Writes a dump XML representation of document to a file.
-   */
-  public void write_file (GLib.File file) throws GLib.Error {
-    var parser = new XParser (this);
-    parser.write_file (file, null);
-  }
-  /**
-   * Writes asynchronically a dump XML representation of document to a file.
-   */
-  public async void write_file_async (GLib.File file, Cancellable? cancellable = null) throws GLib.Error {
-    var parser = new XParser (this);
-    yield parser.write_file_async (file, null);
-  }
-  /**
-   * Writes a dump XML representation of document to a stream.
-   */
-  public void write_stream (GLib.OutputStream stream) throws GLib.Error {
-    var parser = new XParser (this);
-    parser.write_stream (stream, null);
-  }
-  /**
-   * Writes a dump XML representation of document to a stream.
-   */
-  public async void write_stream_async (GLib.OutputStream stream, Cancellable? cancellable = null) throws 
GLib.Error {
-    var parser = new XParser (this);
-    parser.write_stream (stream, null);
-  }
-  /**
-   * Creates an {@link GLib.InputStream} to write a string representation
-   * in XML of {@link GomDocument}
-   */
-  public InputStream create_stream () throws GLib.Error {
-    var parser = new XParser (this);
-    return parser.create_stream (null);
-  }
-  /**
-   * Creates an {@link GLib.InputStream} to write a string representation
-   * in XML of {@link GomDocument}
-   */
-  public async InputStream create_stream_async (Cancellable? cancellable = null) throws GLib.Error {
-    var parser = new XParser (this);
-    return yield parser.create_stream_async (null);
-  }
-  /**
-   * Serialize {@link GomDocument} to a string.
-   */
-  public string write_string () throws GLib.Error {
-    var parser = new XParser (this);
-    return parser.write_string ();
-  }
-  /**
-   * Serialize {@link GomDocument} to a string.
-   */
-  public async string write_string_async (Cancellable? cancellable = null) throws GLib.Error {
-    var parser = new XParser (this);
-    return yield parser.write_string_async ();
-  }
-  /**
-   * Reads a file contents and parse it to document.
-   */
-  public void read_from_file (GLib.File file) throws GLib.Error {
-    var parser = new XParser (this);
-    parser.read_file (file, null);
-  }
-  /**
-   * Reads a file contents and parse it to document.
-   */
-  public async void read_from_file_async (GLib.File file, Cancellable? cancellable = null) throws GLib.Error 
{
-    var parser = new XParser (this);
-    yield parser.read_file_async (file, null);
-  }
-  /**
-   * Reads a string and parse it to document.
-   */
-  public void read_from_string (string str) throws GLib.Error {
-    var parser = new XParser (this);
-    parser.read_string (str, null);
-  }
-  /**
-   * Reads a string and parse it to document.
-   */
-  public async void read_from_string_async (string str, Cancellable? cancellable = null) throws GLib.Error {
-    var parser = new XParser (this);
-    yield parser.read_string_async (str, null);
+  public Parser get_xml_parser () {
+    var roote = get_root_gom_element ();
+    Parser parser = null;
+    if (roote != null) {
+      parser = new XParser (roote);
+    } else {
+      parser = new XParser (this);
+    }
+    if (_parser != null) {
+      parser.backup = _parser.backup;
+      parser.indent = _parser.indent;
+      parser.cancellable = _parser.cancellable;
+    }
+    return parser;
   }
 
+  public void set_xml_parser (Parser parser) {
+    _parser = parser;
+  }
   public DomElement create_element (string local_name) throws GLib.Error {
     var e = new GomElement ();
     e.initialize_document (this, local_name);
diff --git a/gxml/GomElement.vala b/gxml/GomElement.vala
index f2f57a3..9d084c8 100644
--- a/gxml/GomElement.vala
+++ b/gxml/GomElement.vala
@@ -54,7 +54,8 @@ public class GXml.GomElement : GomNode,
   public void read_from_file (GLib.File f,
                       GLib.Cancellable? cancellable = null) throws GLib.Error {
     var parser = new XParser (this);
-    parser.read_file (f, cancellable);
+    parser.cancellable = cancellable;
+    parser.read_file (f);
   }
   /**
    * Parses asinchronically an XML file, deserializing it over {@link GomElement}.
@@ -62,7 +63,8 @@ public class GXml.GomElement : GomNode,
   public async void read_from_file_async (GLib.File f,
                       GLib.Cancellable? cancellable = null) throws GLib.Error {
     var parser = new XParser (this);
-    yield parser.read_file_async (f, cancellable);
+    parser.cancellable = cancellable;
+    yield parser.read_file_async (f);
   }
   /**
    * Parses an XML over a {@link GLib.InputStream}, deserializing it over {@link GomElement}.
@@ -70,7 +72,8 @@ public class GXml.GomElement : GomNode,
   public void read_from_stream (GLib.InputStream istream,
                       GLib.Cancellable? cancellable = null) throws GLib.Error {
     var parser = new XParser (this);
-    parser.read_stream (istream, cancellable);
+    parser.cancellable = cancellable;
+    parser.read_stream (istream);
   }
   /**
    * Parses asynchronically an XML over a {@link GLib.InputStream}, deserializing it over {@link GomElement}.
@@ -78,27 +81,31 @@ public class GXml.GomElement : GomNode,
   public async void read_from_stream_async (GLib.InputStream istream,
                       GLib.Cancellable? cancellable = null) throws GLib.Error {
     var parser = new XParser (this);
-    yield parser.read_stream_async (istream, cancellable);
+    parser.cancellable = cancellable;
+    yield parser.read_stream_async (istream);
   }
   /**
    * Parses an XML string, deserializing it over {@link GomElement}.
    */
-  public void read_from_string (string str) throws GLib.Error {
+  public void read_from_string (string str, Cancellable? cancellable = null) throws GLib.Error {
     var parser = new XParser (this);
-    parser.read_string (str, null);
+    parser.cancellable = cancellable;
+    parser.read_string (str);
   }
   /**
    * Parses an XML string, deserializing it over {@link GomElement}.
    */
   public async void read_from_string_async (string str, Cancellable? cancellable = null) throws GLib.Error {
     var parser = new XParser (this);
-    yield parser.read_string_async (str, null);
+    parser.cancellable = cancellable;
+    yield parser.read_string_async (str);
   }
   /**
    * Serialize {@link GomElement} to a string.
    */
-  public string write_string () throws GLib.Error {
+  public string write_string (Cancellable? cancellable = null) throws GLib.Error {
     var parser = new XParser (this);
+    parser.cancellable = cancellable;
     return parser.write_string ();
   }
   /**
@@ -106,12 +113,13 @@ public class GXml.GomElement : GomNode,
    */
   public async string write_string_async (Cancellable? cancellable = null) throws GLib.Error {
     var parser = new XParser (this);
+    parser.cancellable = cancellable;
     return yield parser.write_string_async ();
   }
   /**
    * Uses element's {@link GomDocument} to write an XML to a file, serializing it.
    */
-  public void write_file (GLib.File f) throws GLib.Error {
+  public void write_file (GLib.File f, Cancellable? cancellable = null) throws GLib.Error {
     (this.owner_document as GomDocument).write_file (f);
   }
   /**
@@ -308,7 +316,6 @@ public class GXml.GomElement : GomNode,
         if (p == null) {
           GomProperty prop = new GomStringRef (this, name);
           _attributes.add (name, prop);
-          message ("Set: %s", name);
         }
       }
     });
@@ -770,7 +777,7 @@ public class GXml.GomElement : GomNode,
   public void read_unparsed () throws GLib.Error {
     if (unparsed == null) return;
     var parser = new XParser (this);
-    parser.read_child_nodes_string (unparsed, null);
+    parser.read_child_nodes_string (unparsed);
     unparsed = null;
   }
 }
diff --git a/gxml/GomObject.vala b/gxml/GomObject.vala
index 4247e89..6974a64 100644
--- a/gxml/GomObject.vala
+++ b/gxml/GomObject.vala
@@ -1,7 +1,7 @@
 /* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
 /*
  *
- * Copyright (C) 2016  Daniel Espinosa <esodan gmail com>
+ * Copyright (C) 2016-2019  Daniel Espinosa <esodan gmail com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -51,15 +51,20 @@ public interface GXml.GomObject : GLib.Object,
     return l;
   }
   /**
-   * Returns property's {@link GLib.ParamSpec} based on given nick. This function is
-   * case insensitive.
+   * Returns property's {@link GLib.ParamSpec} based on given nick, without '::'
+   * This function is case insensitive.
+   *
+   * By default any property to be serialized, should set its nick with a prefix
+   * '::', while this method requires to avoid '::' for property's name to find.
+   * '::' will not be present on serialization output, so you can use any convention
+   * for your attribute's name, like using camel case.
    */
-  public virtual ParamSpec? find_property_name (string pname) {
+  public virtual ParamSpec? find_property_name (string nick) {
     foreach (ParamSpec spec in this.get_class ().list_properties ()) {
       string name = spec.get_nick ();
       if ("::" in name) {
         name = name.replace ("::","");
-        if (name.down () == pname.down ()) {
+        if (name.down () == nick.down ()) {
           return spec;
         }
       }
@@ -73,7 +78,7 @@ public interface GXml.GomObject : GLib.Object,
    *
    * This method will check if nick's name is equal than given name
    * in order to avoid use canonical names like "your-name" if your
-   * property is your_name; so you can se nick to "YourName" to find
+   * property is your_name; so you can use nick to "YourName" to find
    * and instantiate it.
    */
   public virtual ParamSpec? find_object_property_name (string pname) {
@@ -372,6 +377,8 @@ public interface GXml.GomObject : GLib.Object,
    * assert (nb.node != null);
    * }}}
    *
+   * Property's name can be canonical or its nick name, see {@link find_object_property_name}
+   *
    * Returns: true if property has been set and initialized, false otherwise.
    */
   public virtual bool set_instance_property (string name) {
diff --git a/gxml/Makefile.am b/gxml/Makefile.am
index 144c4a3..545ccca 100644
--- a/gxml/Makefile.am
+++ b/gxml/Makefile.am
@@ -68,6 +68,7 @@ sources = \
        GXmlElement.vala \
        GXmlNamespace.vala \
        GXmlNode.vala \
+       GXmlParser.vala \
        GXmlProcessingInstruction.vala \
        GXmlText.vala \
        GXmlHashMapAttr.vala \
diff --git a/gxml/Parser.vala b/gxml/Parser.vala
index e7b043b..bf75412 100644
--- a/gxml/Parser.vala
+++ b/gxml/Parser.vala
@@ -1,7 +1,7 @@
 /* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
 /* Parser.vala
  *
- * Copyright (C) 2016-2017  Daniel Espinosa <esodan gmail com>
+ * Copyright (C) 2016-2019  Daniel Espinosa <esodan gmail com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -43,6 +43,10 @@ public interface GXml.Parser : Object {
    * Controls if, when writing, identation should be used.
    */
   public abstract bool indent { get; set; }
+  /**
+   * Controls if, when writing, identation should be used.
+   */
+  public abstract Cancellable? cancellable { get; set; }
   /**
    * A {@link GXml.DomDocument} to read to or write from
    */
@@ -50,22 +54,18 @@ public interface GXml.Parser : Object {
   /**
    * Writes a {@link GXml.DomDocument} to a {@link GLib.File}
    */
-  public virtual void write_file (GLib.File file,
-                            GLib.Cancellable? cancellable)
-                            throws GLib.Error {
+  public virtual void write_file (GLib.File file) throws GLib.Error {
     var ostream = file.replace (null, backup,
                             GLib.FileCreateFlags.NONE, cancellable);
-    write_stream (ostream, cancellable);
+    write_stream (ostream);
   }
   /**
    * Writes a {@link GXml.DomDocument} to a {@link GLib.File}
    */
-  public virtual async void write_file_async (GLib.File file,
-                            GLib.Cancellable? cancellable)
-                            throws GLib.Error {
-    var ostream = file.replace (null, backup,
-                            GLib.FileCreateFlags.NONE, cancellable);
-    yield write_stream_async (ostream, cancellable);
+  public virtual async void write_file_async (GLib.File file) throws GLib.Error {
+    var ostream = yield file.replace_async (null, backup,
+                            GLib.FileCreateFlags.NONE, 0, cancellable);
+    yield write_stream_async (ostream);
   }
   /**
    * Writes a {@link node} to a string
@@ -78,68 +78,59 @@ public interface GXml.Parser : Object {
   /**
    * Writes a {@link GXml.DomDocument} to a {@link GLib.OutputStream}
    */
-  public abstract void write_stream (OutputStream stream,
-                                    GLib.Cancellable? cancellable) throws GLib.Error;
+  public abstract void write_stream (OutputStream stream) throws GLib.Error;
   /**
    * Writes asynchronically a {@link node} to a {@link GLib.OutputStream}
    */
-  public abstract async void write_stream_async (OutputStream stream,
-                            GLib.Cancellable? cancellable = null) throws GLib.Error;
+  public abstract async void write_stream_async (OutputStream stream) throws GLib.Error;
   /**
    * Reads a {@link node} from a {@link GLib.File}
    */
-  public virtual void read_file (GLib.File file,
-                                GLib.Cancellable? cancellable)
+  public virtual void read_file (GLib.File file)
                                 throws GLib.Error {
     if (!file.query_exists ())
       throw new GXml.ParserError.INVALID_FILE_ERROR (_("File doesn't exist"));
-    read_stream (file.read (), cancellable);
+    read_stream (file.read ());
   }
   /**
    * Reads a {@link GXml.DomDocument} from a {@link GLib.File}
    */
-  public async virtual void read_file_async (GLib.File file,
-                                    GLib.Cancellable? cancellable)
-                                    throws GLib.Error {
+  public async virtual void read_file_async (GLib.File file) throws GLib.Error {
     if (!file.query_exists ())
       throw new GXml.ParserError.INVALID_FILE_ERROR (_("File doesn't exist"));
     Idle.add (read_file_async.callback);
     yield;
-    yield read_stream_async (file.read (), cancellable);
+    yield read_stream_async (file.read ());
   }
 
   /**
    * Read a {@link GXml.DomDocument} from a {@link GLib.InputStream}
    */
-  public abstract void read_stream (InputStream stream,
-                                   GLib.Cancellable? cancellable) throws GLib.Error;
+  public abstract void read_stream (InputStream stream) throws GLib.Error;
 
   /**
    * Read a {@link GXml.DomDocument} from a {@link GLib.InputStream}
    */
-  public abstract async abstract void read_stream_async (InputStream stream,
-                                   GLib.Cancellable? cancellable) throws GLib.Error;
+  public abstract async abstract void read_stream_async (InputStream stream) throws GLib.Error;
   /**
    * Reads a {@link node} from a string
    */
-  public abstract void read_string (string str,
-                                   GLib.Cancellable? cancellable) throws GLib.Error;
+  public abstract void read_string (string str) throws GLib.Error;
 
   /**
    * Reads synchronically {@link node} a from a string
    */
-  public abstract async void read_string_async (string str, GLib.Cancellable? cancellable) throws GLib.Error;
+  public abstract async void read_string_async (string str) throws GLib.Error;
   /**
    * Creates an {@link GLib.InputStream} to write a string representation
    * in XML
    */
-  public abstract InputStream create_stream (GLib.Cancellable? cancellable = null) throws GLib.Error;
+  public abstract InputStream create_stream () throws GLib.Error;
   /**
    * Creates asyncronically an {@link GLib.InputStream} to write a string representation
    * in XML
    */
-  public abstract async InputStream
-  create_stream_async (GLib.Cancellable? cancellable = null) throws GLib.Error;
+  public abstract async InputStream create_stream_async () throws GLib.Error;
   /**
    * Iterates in all child nodes and append them to node.
    */
@@ -287,16 +278,15 @@ public interface GXml.Parser : Object {
   /**
    * Read all childs node feed by stream.
    */
-  public abstract void read_child_nodes_stream (GLib.InputStream istream,
-                          GLib.Cancellable? cancellable = null) throws GLib.Error;
+  public abstract void read_child_nodes_stream (GLib.InputStream istream) throws GLib.Error;
   /**
    * Read childs nodes from string
    */
-  public virtual void read_child_nodes_string (string str, GLib.Cancellable? cancellable) throws GLib.Error {
+  public virtual void read_child_nodes_string (string str) throws GLib.Error {
     if (str == "")
       throw new ParserError.INVALID_DATA_ERROR (_("Invalid document string, it is empty or is not allowed"));
     var stream = new GLib.MemoryInputStream.from_data (str.data);
-    read_child_nodes_stream (stream, cancellable);
+    read_child_nodes_stream (stream);
   }
   /**
    * Reads all child nodes as string
diff --git a/gxml/XParser.vala b/gxml/XParser.vala
index 8be8d32..08212af 100644
--- a/gxml/XParser.vala
+++ b/gxml/XParser.vala
@@ -1,7 +1,7 @@
 /* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
 /* XParser.vala
  *
- * Copyright (C) 2016-2017  Daniel Espinosa <esodan gmail com>
+ * Copyright (C) 2016-2019  Daniel Espinosa <esodan gmail com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -31,7 +31,6 @@ public class GXml.XParser : Object, GXml.Parser {
   private DomNode _node;
   private TextReader tr;
   private Xml.TextWriter tw;
-  private Cancellable cancellable;
   private DataInputStream tistream;
 
   public bool backup { get; set; }
@@ -39,6 +38,8 @@ public class GXml.XParser : Object, GXml.Parser {
 
   public DomNode node { get { return _node; } }
 
+  public Cancellable? cancellable { get; set; }
+
 
   public XParser (DomNode node) {
     _node = node;
@@ -55,20 +56,17 @@ public class GXml.XParser : Object, GXml.Parser {
     tistream = null;
   }
 
-  public void write_stream (OutputStream stream,
-                            GLib.Cancellable? cancellable = null) throws GLib.Error {
+  public void write_stream (OutputStream stream) throws GLib.Error {
     var s = dump ();
     var b = new GLib.MemoryInputStream.from_data (s.data, null);
-    stream.splice (b, GLib.OutputStreamSpliceFlags.NONE);
+    stream.splice (b, GLib.OutputStreamSpliceFlags.NONE, cancellable);
     stream.close ();
     tw = null;
   }
-  public async void write_stream_async (OutputStream stream,
-                            GLib.Cancellable? cancellable = null) throws GLib.Error {
+  public async void write_stream_async (OutputStream stream) throws GLib.Error {
     var s = yield dump_async ();
     var b = new GLib.MemoryInputStream.from_data (s.data, null);
-    stream.splice (b, GLib.OutputStreamSpliceFlags.NONE);
-    stream.close ();
+    yield stream.splice_async (b, GLib.OutputStreamSpliceFlags.NONE, 0, cancellable);
     tw = null;
   }
 
@@ -77,7 +75,7 @@ public class GXml.XParser : Object, GXml.Parser {
    * in XML
    */
   public InputStream
-  create_stream (GLib.Cancellable? cancellable = null) throws GLib.Error {
+  create_stream () throws GLib.Error {
     var s = dump ();
     tw = null;
     return new GLib.MemoryInputStream.from_data (s.data, null);
@@ -87,7 +85,7 @@ public class GXml.XParser : Object, GXml.Parser {
    * in XML
    */
   public async InputStream
-  create_stream_async (GLib.Cancellable? cancellable = null) throws GLib.Error {
+  create_stream_async () throws GLib.Error {
     var s = yield dump_async ();
     tw = null;
     return new GLib.MemoryInputStream.from_data (s.data, null);
@@ -99,19 +97,19 @@ public class GXml.XParser : Object, GXml.Parser {
   public async string write_string_async () throws GLib.Error  {
     return yield dump_async ();
   }
-  public void read_string (string str, GLib.Cancellable? cancellable) throws GLib.Error {
+  public void read_string (string str) throws GLib.Error {
     if (str == "")
       throw new ParserError.INVALID_DATA_ERROR (_("Invalid document string, it is empty or is not allowed"));
     var stream = new GLib.MemoryInputStream.from_data (str.data);
-    read_stream (stream, cancellable);
+    read_stream (stream);
   }
-  public async void read_string_async (string str, GLib.Cancellable? cancellable) throws GLib.Error {
+  public async void read_string_async (string str) throws GLib.Error {
     if (str == "")
       throw new ParserError.INVALID_DATA_ERROR (_("Invalid document string, it is empty or is not allowed"));
     var stream = new GLib.MemoryInputStream.from_data (str.data);
     Idle.add (read_string_async.callback);
     yield;
-    yield read_stream_async (stream, cancellable);
+    yield read_stream_async (stream);
   }
 
   static int read_callback (void* context, [CCode (array_length=false)] char[] buffer, int len) {
@@ -137,15 +135,8 @@ public class GXml.XParser : Object, GXml.Parser {
         dr += bdr;
       }
     } catch (GLib.Error e) {
-      try {
-        message (_("Error reading stream: %s"), e.message);
-        // parser->tistream.close (parser->cancellable);
-        // parser->tistream = null;
-        return -1;
-      } catch (GLib.Error e) {
-        warning (_("Error closing stream: %s"), e.message);
-        return -1;
-      }
+      message (_("Error reading stream: %s"), e.message);
+      return -1;
     }
     return dr;
   }
@@ -163,8 +154,7 @@ public class GXml.XParser : Object, GXml.Parser {
     return 0;
   }
 
-  public void read_stream (GLib.InputStream istream,
-                          GLib.Cancellable? cancellable = null) throws GLib.Error {
+  public void read_stream (GLib.InputStream istream) throws GLib.Error {
     this.cancellable = cancellable;
     tistream = new DataInputStream (istream);
     tr = new TextReader.for_io (read_callback,
@@ -178,8 +168,7 @@ public class GXml.XParser : Object, GXml.Parser {
     tr = null;
     tistream = null;
   }
-  public async void read_stream_async (GLib.InputStream istream,
-                          GLib.Cancellable? cancellable = null) throws GLib.Error {
+  public async void read_stream_async (GLib.InputStream istream) throws GLib.Error {
     this.cancellable = cancellable;
     tistream = new DataInputStream (istream);
     Idle.add (read_stream_async.callback);
@@ -233,16 +222,14 @@ public class GXml.XParser : Object, GXml.Parser {
       }
     }
   }
-  public void read_child_nodes_stream (GLib.InputStream istream,
-                          GLib.Cancellable? cancellable = null) throws GLib.Error {
+  public void read_child_nodes_stream (GLib.InputStream istream) throws GLib.Error {
     var b = new MemoryOutputStream.resizable ();
     b.splice (istream, 0);
     tr = new TextReader.for_memory ((char[]) b.data, (int) b.get_data_size (), "/gxml_memory");
     read_child_nodes (_node);
     tr = null;
   }
-  public async void read_child_nodes_stream_async (GLib.InputStream istream,
-                          GLib.Cancellable? cancellable = null) throws GLib.Error {
+  public async void read_child_nodes_stream_async (GLib.InputStream istream) throws GLib.Error {
     var b = new MemoryOutputStream.resizable ();
     b.splice (istream, 0);
     Idle.add (read_child_nodes_stream_async.callback);
diff --git a/gxml/meson.build b/gxml/meson.build
index 185bbc2..01633d8 100644
--- a/gxml/meson.build
+++ b/gxml/meson.build
@@ -87,6 +87,7 @@ valasources = files ([
        'GXmlListNamespaces.vala',
        'GXmlNamespace.vala',
        'GXmlNode.vala',
+       'GXmlParser.vala',
        'GXmlProcessingInstruction.vala',
        'GXmlText.vala',
        'GXPathObject.vala',
diff --git a/test/GElementTest.vala b/test/GElementTest.vala
index 0d83451..9cbd5a5 100644
--- a/test/GElementTest.vala
+++ b/test/GElementTest.vala
@@ -246,5 +246,18 @@ class GElementTest : GXmlTest  {
                    assert_not_reached ();
                  }
                });
+    Test.add_func ("/gxml/g-document/dom-write-read", () => {
+      try {
+        DomDocument d = new GDocument ();
+        File dir = File.new_for_path (GXmlTestConfig.TEST_DIR);
+        assert (dir.query_exists ());
+        File f = File.new_for_uri (dir.get_uri ()+"/test-large.xml");
+        assert (f.query_exists ());
+        d.read_from_file (f);
+      } catch (GLib.Error e) {
+        warning ("Error: %s", e.message);
+        assert_not_reached ();
+      }
+    });
        }
 }
diff --git a/test/GXmlDocumentPerformanceTest.vala b/test/GXmlDocumentPerformanceTest.vala
index 07e1039..b5b60e4 100644
--- a/test/GXmlDocumentPerformanceTest.vala
+++ b/test/GXmlDocumentPerformanceTest.vala
@@ -28,21 +28,21 @@ class GXmlTest.Suite : Object
     GLib.Intl.setlocale (GLib.LocaleCategory.ALL, "");
     Test.init (ref args);
     Test.add_func ("/gxml/g-document/performance", () => {
-    try {
-      DomDocument d = new GDocument ();
-      File dir = File.new_for_path (GXmlTestConfig.TEST_DIR);
-      assert (dir.query_exists ());
-      File f = File.new_for_uri (dir.get_uri ()+"/test-large.xml");
-      assert (f.query_exists ());
-      Test.timer_start ();
-      d.read_from_file (f);
-      var t = Test.timer_elapsed ();
-      message ("Elapsed time: %g", t);
-    } catch (GLib.Error e) {
-      warning ("Error: %s", e.message);
-      assert_not_reached ();
-    }
-  });
-  return Test.run ();
-}
+      try {
+        DomDocument d = new GDocument ();
+        File dir = File.new_for_path (GXmlTestConfig.TEST_DIR);
+        assert (dir.query_exists ());
+        File f = File.new_for_uri (dir.get_uri ()+"/test-large.xml");
+        assert (f.query_exists ());
+        Test.timer_start ();
+        d.read_from_file (f);
+        var t = Test.timer_elapsed ();
+        message ("Elapsed time: %g", t);
+      } catch (GLib.Error e) {
+        warning ("Error: %s", e.message);
+        assert_not_reached ();
+      }
+    });
+    return Test.run ();
+  }
 }
diff --git a/test/GXmlTest.vala b/test/GXmlTest.vala
index 9be4077..4e9e6b4 100644
--- a/test/GXmlTest.vala
+++ b/test/GXmlTest.vala
@@ -2,7 +2,7 @@
 /* GXmlTest.vala
  *
  * Copyright (C) 2011-2013  Richard Schwarting <aquarichy gmail com>
- * Copyright (C) 2011-2015  Daniel Espinosa <esodan gmail com>
+ * Copyright (C) 2011-2019  Daniel Espinosa <esodan gmail com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -69,8 +69,9 @@ class GXmlTest {
                GomSerializationTest.add_tests ();
                GomSchemaTest.add_tests ();
                CssSelectorTest.add_tests ();
+               NodeListTest.add_tests ();
 
-                               Test.run ();
+               Test.run ();
 
                return 0;
        }
diff --git a/test/GomDocumentTest.vala b/test/GomDocumentTest.vala
index d27ccdf..5a86f03 100644
--- a/test/GomDocumentTest.vala
+++ b/test/GomDocumentTest.vala
@@ -23,6 +23,33 @@
 using GXml;
 
 class GomDocumentTest : GXmlTest {
+       class ObjectDocument : GomDocument {
+               [Description (nick="::ROOT")]
+               public ObjectParent root { get; set; }
+               public class ObjectParent : GomElement {
+                       construct {
+                               try { initialize ("root"); }
+                               catch (GLib.Error e) { warning ("Error: "+e.message); }
+                       }
+                       [Description (nick="::text")]
+                       public string text { get; set; }
+                       [Description (nick="::prop")]
+                       public ObjectProperty prop { get; set; }
+                       public class ObjectProperty : Object, GomProperty {
+                               public string? value { owned get; set; }
+                               public bool validate_value (string? val) {
+                                       return true;
+                               }
+                       }
+                       public ObjectChild child { get; set; }
+                       public class ObjectChild : GomElement {
+                               construct {
+                                       try { initialize ("child"); }
+                                       catch (GLib.Error e) { warning ("Error: "+e.message); }
+                               }
+                       }
+               }
+       }
        public static void add_tests () {
                Test.add_func ("/gxml/gom-document/construct_api", () => {
                        try {
@@ -540,6 +567,7 @@ class GomDocumentTest : GXmlTest {
                                n.append_child (n2);
                                message (d.write_string ());
                                string str = d.write_string ();
+                               message ("Output document: %s", str);
                                assert ("<Node" in str);
                                assert ("<Node name=\"value\"><Node2/></Node>" in str);
                        } catch (GLib.Error e) {
@@ -723,5 +751,16 @@ class GomDocumentTest : GXmlTest {
                    assert_not_reached ();
                  } //<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";>
                });
+               Test.add_func ("/gxml/gom-document/parse-root-element", () => {
+                       try {
+                               var d = new ObjectDocument ();
+                               d.read_from_string ("""<root><child id="id1"/><child id="id2"/></root>""");
+                               message (d.write_string ());
+                               assert (d.root != null);
+                       } catch (GLib.Error e) {
+                   GLib.message ("Error: "+e.message);
+                   assert_not_reached ();
+                 } //<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";>
+               });
        }
 }
diff --git a/test/GomSerializationTest.vala b/test/GomSerializationTest.vala
index cdc6792..f768313 100644
--- a/test/GomSerializationTest.vala
+++ b/test/GomSerializationTest.vala
@@ -971,7 +971,7 @@ class GomSerializationTest : GXmlTest  {
     try {
       var b = new Book ();
       var parser = new XParser (b);
-      parser.read_string ("<book name=\"Loco\"/>", null);
+      parser.read_string ("<book name=\"Loco\"/>");
       string s = parser.write_string ();
       assert (s != null);
       GLib.message ("Doc:"+s);
@@ -1040,7 +1040,7 @@ class GomSerializationTest : GXmlTest  {
 #endif
       assert ("<Motor/>" in s);
       var parser = new XParser (m);
-      parser.read_string ("<Motor On=\"true\" Torque=\"3.1416\" Speed=\"3600.1011\" TensionType=\"dc\" 
Tension=\"125\"/>", null);
+      parser.read_string ("<Motor On=\"true\" Torque=\"3.1416\" Speed=\"3600.1011\" TensionType=\"dc\" 
Tension=\"125\"/>");
       s = m.to_string ();
 #if DEBUG
       GLib.message ("doc:"+s);
@@ -1076,7 +1076,7 @@ class GomSerializationTest : GXmlTest  {
 #endif
       assert ("<BookStand Classification=\"Science\"/>" in s);
       var parser = new XParser (bs);
-      parser.read_string ("<BookStand Classification=\"Science\"><BookRegister Year=\"2016\"/><BookRegister 
Year=\"2010\"/><Test/><BookRegister Year=\"2000\"/></BookStand>", null);
+      parser.read_string ("<BookStand Classification=\"Science\"><BookRegister Year=\"2016\"/><BookRegister 
Year=\"2010\"/><Test/><BookRegister Year=\"2000\"/></BookStand>");
       s = bs.to_string ();
 #if DEBUG
       GLib.message ("doc:"+s);



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