[gxml] GomHashPairedMap: reimplemented using Gee



commit 952d65f48b67bf08384d6f521f5d34f19676e541
Author: Daniel Espinosa <esodan gmail com>
Date:   Fri Jun 9 15:25:54 2017 -0500

    GomHashPairedMap: reimplemented using Gee
    
    Seems there are an issue if you use a hashtable
    in a hashtable using Vala and GLib.HashTable.
    
    When replaced GLib.HashTable with Gee.HashMap
    now GomHashPairedMap works properly

 gxml/GomCollections.vala       |   33 +++++++++++------
 test/GomSerializationTest.vala |   79 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 12 deletions(-)
---
diff --git a/gxml/GomCollections.vala b/gxml/GomCollections.vala
index 8b60ee0..e8ef380 100644
--- a/gxml/GomCollections.vala
+++ b/gxml/GomCollections.vala
@@ -20,7 +20,7 @@
  *      Daniel Espinosa <esodan gmail com>
  */
 
-
+using Gee;
 /**
  * A DOM4 interface to keep references to {@link DomElement} in a {@link element}
  * child nodes. Only {@link GomObject} are supported.
@@ -30,7 +30,7 @@ public interface GXml.GomCollection : Object
   /**
    * A list of child {@link DomElement} objects of {@link element}
    */
-  public abstract Queue<int> nodes_index { get; }
+  public abstract GLib.Queue<int> nodes_index { get; }
   /**
    * A {@link GomElement} with all child elements in collection.
    */
@@ -133,7 +133,7 @@ public abstract class GXml.BaseCollection : Object {
   /**
    * A collection of node's index refered. Don't modify it manually.
    */
-  protected Queue<int> _nodes_index = new Queue<int> ();
+  protected GLib.Queue<int> _nodes_index = new GLib.Queue<int> ();
   /**
    * Element used to refer of containier element. You should define it at construction time
    * our set it as a construction property.
@@ -169,7 +169,7 @@ public abstract class GXml.BaseCollection : Object {
   /**
    * {@inheritDoc}
    */
-  public Queue<int> nodes_index { get { return _nodes_index; } }
+  public GLib.Queue<int> nodes_index { get { return _nodes_index; } }
   /**
    * {@inheritDoc}
    */
@@ -482,7 +482,7 @@ public class GXml.GomHashPairedMap : GXml.BaseCollection, GXml.GomCollection {
   /**
    * A hashtable with all keys as string to node's index refered. Don't modify it manually.
    */
-  protected HashTable<string,HashTable<string,int>> _hashtable = new HashTable<string,HashTable<string,int>> 
(str_hash,str_equal);
+  protected Gee.HashMap<string,HashMap<string,int>> _hashtable = new HashMap<string,HashMap<string,int>> ();
   /**
    * Element's attribute name used to refer of container's element as primery key.
    * You should define it at construction time
@@ -571,17 +571,23 @@ public class GXml.GomHashPairedMap : GXml.BaseCollection, GXml.GomCollection {
    * Returns list of primary keys used in collection.
    */
   public GLib.List<string> get_primary_keys () {
-    return _hashtable.get_keys ();
+    var l = new GLib.List<string> ();
+    foreach (string k in _hashtable.keys) {
+      l.append (k);
+    }
+    return l;
   }
   /**
    * Returns list of secondary keys used in collection with @pkey as primary key.
    */
   public GLib.List<string> get_secondary_keys (string pkey) {
     var l = new GLib.List<string> ();
-    if (!_hashtable.contains (pkey)) return l;
     var ht = _hashtable.get (pkey);
     if (ht == null) return l;
-    return ht.get_keys ();
+    foreach (string k in ht.keys) {
+      l.append (k);
+    }
+    return l;
   }
   /**
    * Validates if given element has a {@link attribute_primary_key}
@@ -619,11 +625,14 @@ public class GXml.GomHashPairedMap : GXml.BaseCollection, GXml.GomCollection {
         skey = ((MappeableElementPairKey) element).get_map_secondary_key ();
       }
     }
-    if (pkey == null || skey == null) return false;
+    if (pkey == null || skey == null)
+      throw new DomError.NOT_FOUND_ERROR (_("No primary key and/or secondary key was found"));
     var ht = _hashtable.get (pkey);
-    if (ht == null) ht = new HashTable<string,int> (str_hash, str_equal);
-    ht.insert (skey, index);
-    if (!_hashtable.contains (pkey)) _hashtable.insert (pkey, ht);
+    if (ht == null) {
+      ht = new HashMap<string,int> ();
+      _hashtable.set (pkey, ht);
+    }
+    ht.set (skey, index);
     return true;
   }
 }
diff --git a/test/GomSerializationTest.vala b/test/GomSerializationTest.vala
index 1369601..f9b90fc 100644
--- a/test/GomSerializationTest.vala
+++ b/test/GomSerializationTest.vala
@@ -23,6 +23,38 @@
 using GXml;
 
 // GOM Collection Definitions
+class Operations : GomElement {
+  private Operation.Map _map;
+  public Operation.Map map {
+    get {
+      if (_map == null)
+        set_instance_property ("map");
+      return _map;
+    }
+    set {
+      if (_map != null)
+        try { clean_property_elements ("map"); }
+        catch (GLib.Error e) { warning ("Error: "+e.message); }
+      _map = value;
+    }
+  }
+  construct { try { initialize ("Operations"); } catch { assert_not_reached (); } }
+}
+class Operation : GomElement, MappeableElementPairKey {
+  [Description (nick="::ID")]
+  public string id { get; set; }
+  [Description (nick="::Code")]
+  public string code { get; set; }
+  construct { try { initialize ("Operation"); } catch { assert_not_reached (); } }
+  public string get_map_primary_key () { return id; }
+  public string get_map_secondary_key () { return code; }
+  public class Map : GomHashPairedMap {
+    construct {
+      try { initialize (typeof (Operation)); }
+      catch (GLib.Error e) { message ("Error: "+e.message); }
+    }
+  }
+}
 class GomName : GomElement
 {
   construct { try { initialize ("Name"); } catch { assert_not_reached (); } }
@@ -1131,5 +1163,52 @@ class GomSerializationTest : GXmlTest  {
         assert_not_reached ();
       }
     });
+    Test.add_func ("/gxml/gom-serialization/collections/hashpairedmap",
+    () => {
+      try {
+        var ops = new Operations ();
+        assert (ops.map != null);
+        assert (ops.map.length == 0);
+        var op1 = ops.map.create_item () as Operation;
+        assert (op1 is Operation);
+        op1.id = "a1";
+        op1.code = "b1";
+        ops.map.append (op1);
+        assert (ops.map.length == 1);
+        var top1 = ops.map.get ("a1", "b1") as Operation;
+        assert (top1 is Operation);
+        assert (top1.id == "a1");
+        assert (top1.code == "b1");
+        var pkeys1 = ops.map.get_primary_keys ();
+        assert (pkeys1.length () == 1);
+        var op2 = ops.map.create_item () as Operation;
+        assert (op2 is Operation);
+        op2.id = "a1";
+        op2.code = "b2";
+        ops.map.append (op2);
+        var op3 = ops.map.create_item () as Operation;
+        assert (op2 is Operation);
+        op3.id = "a2";
+        op3.code = "b1";
+        ops.map.append (op3);
+        assert (ops.map.length == 3);
+        var op4 = ops.map.create_item () as Operation;
+        assert (op4 is Operation);
+        op4.id = "a2";
+        op4.code = "b2";
+        ops.map.append (op4);
+        assert (ops.map.length == 4);
+        message (ops.write_string ());
+        var pkeys2 = ops.map.get_primary_keys ();
+        assert (pkeys2.length () == 2);
+        foreach (string pk in pkeys2) { message (pk); }
+        var skeys1 = ops.map.get_secondary_keys ("a1");
+        foreach (string pk in skeys1) { message (pk); }
+        assert (skeys1.length () == 2);
+      } catch (GLib.Error e) {
+        GLib.message ("ERROR: "+e.message);
+        assert_not_reached ();
+      }
+    });
   }
 }


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