[gxml] Improved GomCollection and GomProperty



commit ee1c6b262077b3dd36249b95059da042be9d8bd5
Author: Daniel Espinosa <esodan gmail com>
Date:   Mon Jan 16 19:30:59 2017 -0600

    Improved GomCollection and GomProperty
    
    * Improved documentation
    * GomCollection implementations now provide convenient
      methods to make easy to derive classes
    * GomProperty implemenatations now provide convenient
      methods to make easy to derive classes
    * GomProperty add regular expression validation for
      values
    * Added new GomString implementation for GomProperty
    * Updated tests cases to test new API in GomCollection
      and GomProperty implementations

 gxml/GomCollections.vala       |  179 ++++++++++++++++++++++++----------------
 gxml/GomDocument.vala          |    8 ++-
 gxml/GomElement.vala           |   20 ++++-
 gxml/GomProperty.vala          |  177 +++++++++++++++++++++++++++++++++------
 test/GomSerializationTest.vala |  175 +++++++++++++--------------------------
 test/gxml-performance.vala     |   39 +++++++++
 6 files changed, 376 insertions(+), 222 deletions(-)
---
diff --git a/gxml/GomCollections.vala b/gxml/GomCollections.vala
index 08f7bc8..a198322 100644
--- a/gxml/GomCollections.vala
+++ b/gxml/GomCollections.vala
@@ -87,13 +87,35 @@ public interface GXml.GomCollection : Object
    * Number of items referenced in {@link nodes_index}
    */
   public virtual int length { get { return (int) nodes_index.get_length (); } }
+  /**
+   * Initialize collection to use a given {@link GomElement} derived type.
+   * Internally, this method create an instance of given type to initialize
+   * {@link items_type} and {@link items_name}.
+   *
+   * This method can be used at construction time of classes implementing
+   * {@link GomCollection} to initialize object type to refer in collection.
+   */
+  public abstract void initialize (GLib.Type t) throws GLib.Error;
+  /**
+   * Creates a new instance of {@link items_type}, with same
+   * {@link DomNode.owner_document} than {@link element}
+   *
+   * Returns: a new instance object or null if type is not a {@link GomElement} or no parent has been set
+   */
+  public virtual GomElement? create_item () {
+    if (items_type.is_a (GLib.Type.INVALID)) return null;
+    if (!items_type.is_a (typeof (GomElement))) return null;
+    if (element == null) return null;
+    return Object.new (items_type,
+                      "owner_document", element.owner_document) as GomElement;
+  }
 }
 
 /**
- * A class impementing {@link GomCollection} to store references to
- * child {@link DomElement} of {@link element}, using an index.
+ * Base class for collections implemeting {@link GomCollection}, priving basic
+ * infrastructure.
  */
-public class GXml.GomArrayList : Object, GomCollection {
+public abstract class GXml.BaseCollection : Object {
   /**
    * A collection of node's index refered. Don't modify it manually.
    */
@@ -120,7 +142,23 @@ public class GXml.GomArrayList : Object, GomCollection {
    * at runtime.
    */
   protected GLib.Type _items_type = GLib.Type.INVALID;
+  /**
+   * {@inheritDoc}
+   */
+  public string items_name { get { return _items_name; } }
+  /**
+   * {@inheritDoc}
+   */
+  public Type items_type {
+    get { return _items_type; } construct set { _items_type = value; }
+  }
+  /**
+   * {@inheritDoc}
+   */
   public Queue<int> nodes_index { get { return _nodes_index; } }
+  /**
+   * {@inheritDoc}
+   */
   public DomElement element {
     get { return _element; }
     construct set {
@@ -133,35 +171,54 @@ public class GXml.GomArrayList : Object, GomCollection {
     }
   }
   /**
-   * {@link DomElement.local_name} used to identify nodes at runtime on readding
-   * XML documents. You can set it at construction time see {@link GomCollection.items_name}
+   * {@inheritDoc}
    */
-  public string items_name { get { return _items_name; } }
-  public Type items_type {
-    get { return _items_type; } construct set { _items_type = value; }
+  public void initialize (GLib.Type items_type) throws GLib.Error {
+    if (!items_type.is_a (typeof (GomElement))) {
+      throw new DomError.INVALID_NODE_TYPE_ERROR
+                (_("Invalid atempt to initialize a collection using an unsupported type. Only GXmlGomElement 
is supported"));
+    }
+    var o = Object.new (items_type) as GomElement;
+    _items_name = o.local_name;
+    _items_type = items_type;
   }
-
   /**
-   * Initialize an {@link GomArrayList} to use an element as child parent
-   * and items of given type. Derived classes are encourage to provide its
-   * own definition, chaining up, to correctly initialize a collection.
+   * Initialize an {@link GomArrayList} to use an element as children's parent.
+   * Searchs for all nodes, calling {@link GomCollection.search}
+   * with {@link GomCollection.items_type}, using its
+   * {@link DomElement.local_name} to find it.
+   *
+   * Implemenation classes, should initialize collection to hold a {@link GomElement}
+   * derived type using {@link GomCollection.initialize}.
    */
-  public GomArrayList.initialize (GomElement element, GLib.Type items_type) {
+  public void initialize_element (GomElement element) throws GLib.Error {
     _element = element;
-    _items_name = "";
-    if (!(items_type.is_a (typeof (GomObject)))) {
-      warning (_("Invalid object item type to initialize ArrayList"));
-    } else {
-      var tmp = Object.new (items_type) as GomElement;
-      _items_name = tmp.local_name;
-      search ();
-    }
+    search ();
   }
   /**
    * Adds an {@link DomElement} of type {@link GomObject} as a child of
    * {@link element}
    */
-  public void append (DomElement node) throws GLib.Error {
+  public abstract void append (DomElement node) throws GLib.Error;
+  /**
+   * Search for all child nodes in {@link element} of type {@link GomElement}
+   * with a {@link GomElement.local_name} equal to {@link GomCollection.items_name},
+   * to add it to collection.
+   *
+   * Implementations could add additional restrictions to add element to collection.
+   */
+  public abstract void search () throws GLib.Error;
+}
+
+/**
+ * A class impementing {@link GomCollection} to store references to
+ * child {@link DomElement} of {@link element}, using an index.
+ */
+public class GXml.GomArrayList : GXml.BaseCollection, GomCollection {
+  /**
+   * {@inheritDoc}
+   */
+  public override void append (DomElement node) throws GLib.Error {
     if (!(node is GomElement))
       throw new DomError.INVALID_NODE_TYPE_ERROR
                 (_("Invalid atempt to add unsupported type. Only GXmlGomElement is supported"));
@@ -179,7 +236,7 @@ public class GXml.GomArrayList : Object, GomCollection {
    * with a {@link GomElement.local_name} equal to {@link GomCollection.items_name},รง
    * to add it to collection.
    */
-  public void search () throws GLib.Error {
+  public override void search () throws GLib.Error {
     for (int i = 0; i < _element.child_nodes.size; i++) {
       var n = _element.child_nodes.get (i);
       if (n is GomObject) {
@@ -197,11 +254,7 @@ public class GXml.GomArrayList : Object, GomCollection {
  * child {@link DomElement} of {@link element}, using an attribute in
  * items as key.
  */
-public class GXml.GomHashMap : Object, GomCollection {
-  /**
-   * A collection of node's index refered. Don't modify it manually.
-   */
-  protected Queue<int> _nodes_index = new Queue<int> ();
+public class GXml.GomHashMap : GXml.BaseCollection, GXml.GomCollection {
   /**
    * A hashtable with all keys as string to node's index refered. Don't modify it manually.
    */
@@ -210,37 +263,7 @@ public class GXml.GomHashMap : Object, GomCollection {
    * Element used to refer of containier element. You should define it at construction time
    * our set it as a construction property.
    */
-  protected GomElement _element;
-  /**
-   * {@link DomElement.local_name} used to identify nodes at runtime on readding
-   * XML documents. You can set it at construction time see {@link GomCollection.items_name}
-   */
-  protected string _items_name = "";
-  /**
-   * Objects' type to be referenced by this collection and to deserialize objects.
-   * Derived classes, can initilize this value at constructor or as construct property.
-   *
-   * Used when reading and at initialization time, to know {@link GomElement.local_name}
-   * at runtime.
-   */
-  protected GLib.Type _items_type = GLib.Type.INVALID;
   protected string _attribute_key;
-  public Queue<int> nodes_index { get { return _nodes_index; } }
-  public DomElement element {
-    get { return _element; }
-    construct set {
-      if (value != null) {
-        if (value is GomElement)
-          _element = value as GomElement;
-        else
-          GLib.warning (_("Invalid element type only GXmlGomElement is supported"));
-      }
-    }
-  }
-  public string items_name { get { return _items_name; } }
-  public GLib.Type items_type {
-    get { return _items_type; } construct set { _items_type = value; }
-  }
   /**
    * An attribute's name in items to be added and used to retrieve a key to
    * used in collection.
@@ -248,27 +271,39 @@ public class GXml.GomHashMap : Object, GomCollection {
   public string attribute_key {
     get { return _attribute_key; } construct set { _attribute_key = value; }
   }
-
-  public GomHashMap.initialize (GomElement element,
+  /**
+   * Convenient function to initialize a {@link GomHashMap} collection, using
+   * given element, items' type and name.
+   */
+  public void initialize_element_with_key (GomElement element,
                                   GLib.Type items_type,
-                                  string attribute_key) {
-    _element = element;
-    _items_name = "";
+                                  string attribute_key) throws GLib.Error
+  {
+    initialize (items_type);
+    initialize_element (element);
     _attribute_key = attribute_key;
-    if (!(items_type.is_a (typeof (GomObject)))) {
-      warning (_("Invalid object item type to initialize HashMap"));
-    } else {
-      var tmp = Object.new (items_type) as GomElement;
-      _items_name = tmp.local_name;
-      search ();
-    }
+    search ();
+  }
+
+  /**
+   * Convenient function to initialize a {@link GomHashMap} collection, using
+   * given element, items' type and name.
+   *
+   * Using this method at construction time of derived classes.
+   */
+  public void initialize_with_key (GLib.Type items_type,
+                                  string attribute_key) throws GLib.Error
+  {
+    initialize (items_type);
+    _attribute_key = attribute_key;
+    search ();
   }
   /**
    * Sets an {@link DomElement} of type {@link GomObject} as a child of
    * {@link element}, requires new item to have defined an string attribute
    * to be used as key. Attribute should have the name: {@link attribute_key}
    */
-  public void append (DomElement node) throws GLib.Error {
+  public override void append (DomElement node) throws GLib.Error {
     if (!(node is GomElement))
       throw new DomError.INVALID_NODE_TYPE_ERROR
                 (_("Invalid atempt to set unsupported type. Only GXmlGomElement is supported"));
@@ -301,7 +336,7 @@ public class GXml.GomHashMap : Object, GomCollection {
    * Search for all child nodes in {@link element} of type {@link GomElement}
    * with an attribute {@link attribute_name} set, to add it to collection.
    */
-  public void search () throws GLib.Error {
+  public override void search () throws GLib.Error {
     for (int i = 0; i < _element.child_nodes.size; i++) {
       var n = _element.child_nodes.get (i);
       if (n is GomObject) {
diff --git a/gxml/GomDocument.vala b/gxml/GomDocument.vala
index 562679f..3f58634 100644
--- a/gxml/GomDocument.vala
+++ b/gxml/GomDocument.vala
@@ -135,7 +135,9 @@ public class GXml.GomDocument : GomNode,
   }
 
   public DomElement create_element (string local_name) throws GLib.Error {
-    return new GomElement.initialize (this, local_name);
+    var e = new GomElement ();
+    e.initialize_document (this, local_name);
+    return e;
   }
   public DomElement create_element_ns (string? namespace_uri, string qualified_name) throws GLib.Error
   {
@@ -161,7 +163,9 @@ public class GXml.GomDocument : GomNode,
         && namespace_uri == "http://www.w3.org/2000/xmlns/";)
       throw new DomError.NAMESPACE_ERROR
         (_("Only xmlns prefixs can be used with http://www.w3.org/2000/xmlns/";));
-    return new GomElement.namespace (this, namespace_uri, nsp, n);
+    var e = new GomElement ();
+    e.initialize_with_namespace (this, namespace_uri, nsp, n);
+    return e;
   }
 
   public DomHTMLCollection get_elements_by_tag_name (string local_name) {
diff --git a/gxml/GomElement.vala b/gxml/GomElement.vala
index 1219b71..96cf77d 100644
--- a/gxml/GomElement.vala
+++ b/gxml/GomElement.vala
@@ -213,12 +213,26 @@ public class GXml.GomElement : GomNode,
     _attributes = new Attributes (this);
     _local_name = "";
   }
-
-  public GomElement.initialize (DomDocument doc, string local_name) {
+  /**
+   * Convenient function to initialize, at construction time, a {@link GomElement}
+   * using given local name.
+   */
+  public void initialize (string local_name) {
+    _local_name = local_name;
+  }
+  /**
+   * Convenient function to initialize, at construction time, a {@link GomElement}
+   * using given local name and document.
+   */
+  public void initialize_document (DomDocument doc, string local_name) {
     _document = doc;
     _local_name = local_name;
   }
-  public GomElement.namespace (DomDocument doc, string? namespace_uri,
+  /**
+   * Convenient function to initialize, at construction time, a {@link GomElement}
+   * using given local name, document and namespace.
+   */
+  public void initialize_with_namespace (DomDocument doc, string? namespace_uri,
                               string? prefix, string local_name) {
     _document = doc;
     _local_name = local_name;
diff --git a/gxml/GomProperty.vala b/gxml/GomProperty.vala
index f95820f..c7b8934 100644
--- a/gxml/GomProperty.vala
+++ b/gxml/GomProperty.vala
@@ -23,7 +23,8 @@
 
 /**
  * An interface for {@link GomObject}'s properties translated to
- * {@link DomElement} attributes.
+ * {@link DomElement} attributes. If object is instantiated it is
+ * written, if not is just ingnored.
  */
 public interface GXml.GomProperty : Object
 {
@@ -32,19 +33,89 @@ public interface GXml.GomProperty : Object
    */
   public abstract string attribute_name { get; construct set; }
   /**
-   * Attribute's value in the parent {@link DomElement}.
+   * Validation rule.
+   *
+   * Is a regular expression, used to validate if values are valid.
+   */
+  public abstract string validation_rule { get; construct set; }
+  /**
+   * Attribute's value in the parent {@link DomElement} using a string.
+   *
+   * Implementation should take care to validate value before to set or
+   * parse from XML document.
    */
   public abstract string value { owned get; set; }
+  /**
+   * Convenient function to initialize property's name.
+   */
+  public abstract void initialize (string attribute_name);
+  /**
+   * Takes a string and check if it can be validated using
+   */
+  public abstract bool validate_value (string val);
 }
 
-public class GXml.GomDouble : Object, GomProperty {
-  protected double _value = 0.0;
+/**
+ * Base class for properties implementing {@link GomProperty} interface.
+ */
+public abstract class GXml.GomBaseProperty : Object, GXml.GomProperty {
   protected string _attribute_name;
+  protected string _validation_rule = "";
+  /**
+   * {@inheritDoc}
+   */
   public string attribute_name {
     get { return _attribute_name; }
     construct set { _attribute_name = value;}
   }
-  public string value {
+  /**
+   * {@inheritDoc}
+   */
+  public string validation_rule {
+    get { return _validation_rule; }
+    construct set { _validation_rule = value; } // TODO: Validate RegEx
+  }
+  /**
+   * {@inheritDoc}
+   */
+  public abstract string value { owned get; set; }
+  /**
+   * {@inheritDoc}
+   */
+  public void initialize (string attribute_name) { _attribute_name =  attribute_name; }
+  /**
+   * Takes a string and check if it can be validated using
+   * {@link validation_rule}.
+   */
+  public bool validate_value (string val) { return true; } // FIXME: Validate value
+}
+
+/**
+ * Convenient class to handle {@link GomElement}'s attributes
+ * using validated string using Regular Expressions.
+ */
+public class GXml.GomString : GomBaseProperty {
+  protected string _value = "";
+  public override string value {
+    owned get {
+      return _value;
+    }
+    set {
+      if (validate_value (value))
+        _value = value;
+    }
+  }
+}
+
+/**
+ * Convenient class to handle {@link GomElement}'s attributes
+ * using double pressition floats as sources of values.
+ *
+ * Property is represented as a string.
+ */
+public class GXml.GomDouble : GomBaseProperty {
+  protected double _value = 0.0;
+  public override string value {
     owned get {
       string s = "%."+decimals.to_string ()+"f";
       return s.printf (_value);
@@ -53,25 +124,48 @@ public class GXml.GomDouble : Object, GomProperty {
       _value = double.parse (value);
     }
   }
+  /**
+   * Set number of decimals to write out as {@link GomElement}'s property.
+   * Default is 4.
+   */
   public uint decimals { get; set; default = 4; }
+  /**
+   * Retrive current value.
+   */
   public double get_double () { return _value; }
+  /**
+   * Sets current value.
+   */
   public void set_double (double value) { _value = value; }
 }
 
+/**
+ * Convenient class to handle {@link GomElement}'s attributes
+ * using floats as sources of values.
+ *
+ * Property is represented as a string.
+ */
 public class GXml.GomFloat : GomDouble {
+  /**
+   * Retrive current value.
+   */
   public float get_float () { return (float) _value; }
+  /**
+   * Sets current value.
+   */
   public void set_float (float value) { _value = value; }
 }
 
 
-public class GXml.GomInt : Object, GomProperty {
+/**
+ * Convenient class to handle {@link GomElement}'s attributes
+ * using a integers as sources of values.
+ *
+ * Property is represented as a string.
+ */
+public class GXml.GomInt : GomBaseProperty {
   protected int _value = 0;
-  protected string _attribute_name;
-  public string attribute_name {
-    get { return _attribute_name; }
-    construct set { _attribute_name = value;}
-  }
-  public string value {
+  public override string value {
     owned get {
       return _value.to_string ();
     }
@@ -79,18 +173,25 @@ public class GXml.GomInt : Object, GomProperty {
       _value = (int) double.parse (value);
     }
   }
+  /**
+   * Retrive current value.
+   */
   public int get_integer () { return _value; }
+  /**
+   * Sets current value.
+   */
   public void set_integer (int value) { _value = value; }
 }
 
-public class GXml.GomBoolean : Object, GomProperty {
+/**
+ * Convenient class to handle {@link GomElement}'s attributes
+ * using a boolean ('true' and 'false') as sources of values.
+ *
+ * Property is represented as a string, using 'true' or 'false'.
+ */
+public class GXml.GomBoolean : GomBaseProperty {
   protected bool _value = false;
-  protected string _attribute_name;
-  public string attribute_name {
-    get { return _attribute_name; }
-    construct set { _attribute_name = value;}
-  }
-  public string value {
+  public override string value {
     owned get {
       return _value.to_string ();
     }
@@ -98,19 +199,27 @@ public class GXml.GomBoolean : Object, GomProperty {
       _value = bool.parse (value);
     }
   }
+  /**
+   * Retrive current value.
+   */
   public bool get_boolean () { return _value; }
+  /**
+   * Sets current value.
+   */
   public void set_boolean (bool value) { _value = value; }
 }
 
-public class GXml.GomEnum : Object, GomProperty {
+/**
+ * Convenient class to handle {@link GomElement}'s attributes
+ * using a {@link GLib.Type.ENUM} as a source of values.
+ *
+ * Enumeration is represented as a string, using its name, independent of
+ * value possition in enumeration.
+ */
+public class GXml.GomEnum : GomBaseProperty, GomProperty {
   protected int _value = 0;
-  protected string _attribute_name;
   protected Type _enum_type;
-  public string attribute_name {
-    get { return _attribute_name; }
-    construct set { _attribute_name = value;}
-  }
-  public string value {
+  public override string value {
     owned get {
       string s = "";
       try {
@@ -128,10 +237,26 @@ public class GXml.GomEnum : Object, GomProperty {
       }
     }
   }
+  /**
+   * Enum type used by property.
+   */
   public Type enum_type {
     get { return _enum_type; }
     construct set { _enum_type = value; }
   }
+  /**
+   * Convenient method to initialize internal enum type.
+   */
+  public void initialize_enum (string attribute_name, GLib.Type enum_type) {
+    initialize (attribute_name);
+    _enum_type = enum_type;
+  }
+  /**
+   * Retrive current value.
+   */
   public int get_enum () { return (int) _value; }
+  /**
+   * Sets current value.
+   */
   public void set_enum (int value) { _value = value; }
 }
diff --git a/test/GomSerializationTest.vala b/test/GomSerializationTest.vala
index 3a1d44d..980e6bc 100644
--- a/test/GomSerializationTest.vala
+++ b/test/GomSerializationTest.vala
@@ -25,125 +25,95 @@ using GXml;
 // GOM Collection Definitions
 class GomName : GomElement
 {
-  construct {
-    _local_name = "Name";
-  }
+  construct { initialize ("Name");}
   public string get_name () { return this.text_content; }
   public void   set_name (string name) { this.text_content = name; }
 }
 
 class GomEmail : GomElement
 {
-  construct {
-    _local_name = "Email";
-  }
+  construct {  initialize ("Email"); }
   public string get_mail () { return this.text_content; }
   public void   set_mail (string email) { text_content = email; }
 }
 
 class GomAuthor : GomElement
 {
-  construct {
-    _local_name = "Author";
-  }
   public Name name { get; set; }
   public Email email { get; set; }
+  construct { initialize ("Author");}
   public class Array : GomArrayList {
-    construct {
-      var t = new GomAuthor ();
-      _items_type = typeof (GomAuthor);
-      _items_name = t.local_name;
-    }
+    construct { initialize (typeof (GomAuthor)); }
   }
 }
 
 class GomAuthors : GomElement
 {
-  construct {
-    _local_name = "Authors";
-  }
   public string number { get; set; }
+  construct { initialize ("Authors"); }
   public Author.Array array { get; set; default = new Author.Array (); }
 }
 
 class GomInventory : GomElement
 {
-  [Description (nick="##Number")]
+  [Description (nick="::Number")]
   public int number { get; set; }
-  [Description (nick="##Row")]
+  [Description (nick="::Row")]
   public int row { get; set; }
+  [Description (nick="::Inventory")]
   public string inventory { get; set; }
+  construct { initialize ("Inventory"); }
   // FIXME: Add DualKeyMap implementation to GOM
   public class DualKeyMap : GomHashMap {
-    construct {
-      var t = new GomInventory ();
-      _items_type = typeof (GomInventory);
-      _items_name = t.local_name;
-      _attribute_key = "number";
-    }
+    construct { initialize_with_key (typeof (GomInventory), "number"); }
   }
 }
 
 class GomCategory : GomElement
 {
+  [Description (nick="::Name")]
   public string name { get; set; }
+  construct { initialize ("Category"); }
   public class Map : GomHashMap {
-    construct {
-      var t = new GomCategory ();
-      _items_type = typeof (GomCategory);
-      _items_name = t.local_name;
-      _attribute_key = "number";
-    }
+    construct { initialize_with_key (typeof (GomInventory), "name"); }
   }
 }
 
 
 class GomResume : GomElement
 {
-  [Description (nick="##Chapter")]
+  [Description (nick="::Chapter")]
   public string chapter { get; set; }
-  [Description (nick="##Text")]
+  [Description (nick="::Text")]
   public string text { get; set; }
+  construct { initialize ("Resume"); }
   public class Map : GomHashMap {
-    construct {
-      var t = new GomResume ();
-      _items_type = typeof (GomResume);
-      _items_name = t.local_name;
-      _attribute_key = "chapter";
-    }
+    construct { initialize_with_key (typeof (GomInventory), "chapter"); }
   }
 }
 
 class GomBook : GomElement
 {
-  construct {
-    _local_name = "Book";
-  }
-  [Description(nick="##Year")]
+  [Description(nick="::Year")]
   public string year { get; set; }
-  [Description(isbn="##ISBN")]
+  [Description(isbn="::ISBN")]
   public string isbn { get; set; }
   public GomName   name { get; set; }
   public GomAuthors authors { get; set; }
   public GomInventory.DualKeyMap inventory_registers { get; set; default = new GomInventory.DualKeyMap (); }
   public GomCategory.Map categories { get; set; default = new GomCategory.Map (); }
   public GomResume.Map resumes { get; set; default = new GomResume.Map (); }
+  construct { initialize ("Book"); }
   public class Array : GomArrayList {
-    construct {
-      var t = new GomBook ();
-      _items_type = typeof (GomBook);
-      _items_name = t.local_name;
-    }
+    construct { initialize (typeof (GomBook)); }
   }
 }
 
 class GomBookStore : GomElement
 {
-  construct {
-    _local_name = "BookStore";
-  }
-  [Description (nick="##name")]
+  [Description (nick="::name")]
   public string name { get; set; }
+  construct { initialize ("BookStore"); }
   public GomBook.Array books { get; set; default = new GomBook.Array (); }
 }
 
@@ -151,9 +121,7 @@ class GomSerializationTest : GXmlTest  {
   public class Book : GomElement {
     [Description (nick="::Name")]
     public string name { get; set; }
-    construct {
-      _local_name = "Book";
-    }
+    construct { initialize ("Book"); }
     public Book.document (DomDocument doc) {
       _document = doc;
     }
@@ -173,9 +141,7 @@ class GomSerializationTest : GXmlTest  {
     [Description (nick="::Model")]
     public string model { get; set; }
     public string ignore { get; set; } // ignored property
-    construct {
-      _local_name = "Computer";
-    }
+    construct { initialize ("Computer"); }
     public string to_string () {
       var parser = new XParser (this);
       string s = "";
@@ -195,9 +161,7 @@ class GomSerializationTest : GXmlTest  {
     public bool tax_free { get; set; }
     [Description (nick="::Month")]
     public Month month { get; set; }
-    construct {
-      _local_name = "Taxes";
-    }
+    construct { initialize ("Taxes"); }
     public string to_string () {
       var parser = new XParser (this);
       string s = "";
@@ -218,9 +182,7 @@ class GomSerializationTest : GXmlTest  {
     [Description (nick="::Year")]
     public int year { get; set; }
     public Book book { get; set; }
-    construct {
-      _local_name = "BookRegister";
-    }
+    construct { initialize ("BookRegister"); }
     public BookRegister.document (DomDocument doc) {
       _document = doc;
     }
@@ -242,7 +204,8 @@ class GomSerializationTest : GXmlTest  {
     public Registers registers { get; set; }
     public Books books { get; set; }
     construct {
-      _local_name = "BookStand";
+      initialize ("BookStand");
+      registers = Object.new (typeof(Registers), "element", this) as Registers;
     }
     public string to_string () {
       var parser = new XParser (this);
@@ -255,32 +218,19 @@ class GomSerializationTest : GXmlTest  {
       }
       return s;
     }
-    public class Registers : GomArrayList {
-      public Registers.initialize (BookStand stand) {
-        _element = stand;
-      }
-      construct {
-        var t = new BookRegister ();
-        _items_type = typeof (BookRegister);
-        _items_name = t.local_name;
-      }
-    }
-    public class Books : GomHashMap {
-      public Books.initialize (BookStand stand) {
-        _element = stand;
-      }
-      construct {
-        var t = new Book ();
-        _items_type = typeof (Book);
-        _items_name = t.local_name;
-        _attribute_key = "name";
-      }
-    }
+  }
+
+  public class Registers : GomArrayList {
+    construct { initialize (typeof (BookRegister)); }
+  }
+  public class Books : GomHashMap {
+    construct { initialize_with_key (typeof (Book), "name"); }
   }
   public class BookStore : GomElement {
-    public GomHashMap books { get; set; }
+    public Books books { get; set; }
     construct {
-      _local_name = "BookStore";
+      initialize ("BookStore");
+      books = Object.new (typeof (Books), "element", this) as Books;
     }
     public string to_string () {
       var parser = new XParser (this);
@@ -300,9 +250,7 @@ class GomSerializationTest : GXmlTest  {
     public Speed speed { get; set; }
     public TensionType tension_type { get; set; }
     public Tension tension { get; set; }
-    construct {
-      _local_name = "Motor";
-    }
+    construct { initialize ("Motor"); }
     public string to_string () {
       var parser = new XParser (this);
       string s = "";
@@ -319,30 +267,21 @@ class GomSerializationTest : GXmlTest  {
       DC
     }
     public class On : GomBoolean {
-      construct {
-        _attribute_name = "On";
-      }
+      construct { initialize ("On"); }
     }
     public class Torque : GomDouble {
-      construct {
-        _attribute_name = "Torque";
-      }
+      construct { initialize ("Torque"); }
     }
     public class Speed : GomFloat {
-      construct {
-        _attribute_name = "Speed";
-      }
+      construct { initialize ("Speed"); }
     }
     public class TensionType : GomEnum {
       construct {
-        _enum_type = typeof (TensionTypeEnum);
-        _attribute_name = "TensionType";
+        initialize_enum ("Tension", typeof (TensionTypeEnum));
       }
     }
     public class Tension : GomInt {
-      construct {
-        _attribute_name = "Tension";
-      }
+      construct { initialize ("Tension"); }
     }
   }
   public static void add_tests () {
@@ -413,31 +352,30 @@ class GomSerializationTest : GXmlTest  {
       assert (s != null);
       GLib.message ("DOC:"+s);
       assert ("<BookStand Classification=\"Science\"/>" in s);
-      assert (bs.registers == null);
-      var br = new BookRegister ();
-      bs.registers = new BookStand.Registers.initialize (bs);
+      assert (bs.registers != null);
       s = bs.to_string ();
       assert (s != null);
       GLib.message ("DOC:"+s);
       assert ("<BookStand Classification=\"Science\"/>" in s);
       try {
+        var br = bs.registers.create_item () as BookRegister;
         bs.registers.append (br);
         assert_not_reached ();
       } catch {}
-      br = new BookRegister.document (bs.owner_document);
-      br.year = 2016;
-      bs.registers.append (br);
+      var br2 = bs.registers.create_item () as BookRegister;
+      br2.year = 2016;
+      bs.registers.append (br2);
       s = bs.to_string ();
       assert (s != null);
       GLib.message ("DOC:"+s);
       assert ("<BookStand Classification=\"Science\"><BookRegister Year=\"2016\"/></BookStand>" in s);
-      var br2 = new BookRegister.document (bs.owner_document);
-      bs.registers.append (br2);
-      br2.year = 2010;
-      bs.append_child (bs.owner_document.create_element ("Test"));
-      var br3 = new BookRegister.document (bs.owner_document);
+      var br3 = bs.registers.create_item () as BookRegister;
       bs.registers.append (br3);
-      br3.year = 2000;
+      br3.year = 2010;
+      bs.append_child (bs.owner_document.create_element ("Test"));
+      var br4 = bs.registers.create_item () as BookRegister;
+      bs.registers.append (br4);
+      br4.year = 2000;
       s = bs.to_string ();
       assert (s != null);
       GLib.message ("DOC:"+s);
@@ -459,7 +397,6 @@ class GomSerializationTest : GXmlTest  {
       assert ("<BookStore/>" in s);
       assert (bs.books == null);
       var b = new Book ();
-      bs.books = new GomHashMap.initialize (bs,typeof (Book),"name");
       s = bs.to_string ();
       assert (s != null);
       GLib.message ("DOC:"+s);
diff --git a/test/gxml-performance.vala b/test/gxml-performance.vala
index 30d7b2d..00447fb 100644
--- a/test/gxml-performance.vala
+++ b/test/gxml-performance.vala
@@ -237,6 +237,45 @@ public class Performance
   }
   public static void add_tests ()
   {
+    Test.add_func ("/gxml/performance/check/document",
+    () => {
+      try {
+        double time;
+        GomDocument doc;
+        var f = GLib.File.new_for_path (GXmlTestConfig.TEST_DIR + "/test-large.xml");
+        assert (f.query_exists ());
+        Test.timer_start ();
+        var bs = new GomBookStore ();
+        bs.read_from_file (f);
+        assert (bs.local_name == "BookStore");
+        assert (bs.name == "The Great Book");
+        time = Test.timer_elapsed ();
+        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 ();
+        bs.write_file (of);
+        time = Test.timer_elapsed ();
+        Test.minimized_result (time, "Serialize/performance: %g seconds", time);
+        assert (of.query_exists ());
+        try { of.delete (); } catch { assert_not_reached (); }
+        // Check read structure
+        GLib.message ("Document Root: "+bs.owner_document.document_element.node_name);
+        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");
+        assert (ns.length > 0);
+        GLib.message ("Books: "+bs.books.length.to_string ());
+        /*assert (bs.books.length > 0);
+        var b = bs.books.get_item (0) as GomBook;
+        assert (b != null);
+        assert (b.year == "2015");*/
+      } catch (GLib.Error e) {
+#if DEBUG
+        GLib.message ("ERROR: "+e.message);
+#endif
+        assert_not_reached ();
+      }
+    });
 #if ENABLE_PERFORMANCE_TESTS
     Test.add_func ("/gxml/performance/read/gomdocument",
     () => {


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