[gxml/serialization] Added collection DualKeyMap and Unit Tests



commit e25c4831733fa8d28c0f2b540f4536fe77801311
Author: Daniel Espinosa <esodan gmail com>
Date:   Wed Nov 13 17:19:39 2013 -0600

    Added collection DualKeyMap and Unit Tests

 gxml/Makefile.am                        |    2 +
 gxml/SerializableGeeDualKeyMap.vala     |  222 +++++++++++++++++++++++++++++++
 gxml/SerializableMapDualId.vala         |   27 ++++
 test/GXmlTest.vala                      |    1 +
 test/Makefile.am                        |    1 +
 test/SerializableGeeDualKeyMapTest.vala |  210 +++++++++++++++++++++++++++++
 6 files changed, 463 insertions(+), 0 deletions(-)
---
diff --git a/gxml/Makefile.am b/gxml/Makefile.am
index 6de2735..a691a97 100644
--- a/gxml/Makefile.am
+++ b/gxml/Makefile.am
@@ -67,6 +67,8 @@ libgxml_la_SOURCES = \
        Serialization.vala \
        SerializableGeeTreeMap.vala \
        SerializableMapId.vala \
+       SerializableGeeDualKeyMap.vala \
+       SerializableMapDualId.vala \
        $(NULL)
 
 gxml.vala.stamp: $(libgxml_la_SOURCES)
diff --git a/gxml/SerializableGeeDualKeyMap.vala b/gxml/SerializableGeeDualKeyMap.vala
new file mode 100644
index 0000000..6936744
--- /dev/null
+++ b/gxml/SerializableGeeDualKeyMap.vala
@@ -0,0 +1,222 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* SerializableGeeTreeModel.vala
+ *
+ * Copyright (C) 2013  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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Daniel Espinosa <esodan gmail com>
+ */
+using GXml;
+using Gee;
+
+public class GXml.SerializableDualKeyMap<P,S,V> : Object, Serializable
+{
+  private Gee.HashMultiMap<P,HashMap<S,V>> storage;
+
+  public Type value_type
+  {
+    get {
+      init ();
+      return typeof (V);
+    }
+  }
+  public Type primary_key_type
+  {
+    get {
+      init ();
+      return typeof (P);
+    }
+  }
+  public Type secondary_key_type
+  {
+    get {
+      init ();
+      return typeof (S);
+    }
+  }
+  public Gee.Collection<P> primary_keys
+  {
+    owned get {
+      init ();
+      return storage.get_keys ();
+    }
+  }
+  public Gee.Collection<S> secondary_keys (P key)
+  {
+    init ();
+    var hs = storage.get (key);
+    var s = new HashSet<S> ();
+    foreach (HashMap<S,V> hm in hs) {
+      s.add_all (hm.keys);
+    }
+    return s;
+  }
+  public Gee.Collection<V> values_for_key (P primary_key)
+  {
+    init ();
+    var hs = storage.get (primary_key);
+    var s = new HashSet<V> ();
+    foreach (HashMap<S,V> hm in hs) {
+      s.add_all (hm.values);
+    }
+    return s;
+  }
+  public Gee.Collection<V> values ()
+  {
+    init ();
+    var s = new Gee.HashSet<V> ();
+    foreach (HashMap<S,V> h in storage.get_values ()) {
+      s.add_all (h.values);
+    }
+    return s;
+  }
+  public new void @set (P primary_key, S secundary_key, V val)
+  {
+    init ();
+    var h = new HashMap<S,V> ();
+    h  set (secundary_key, val);
+    storage  set (primary_key, h);
+  }
+  public new V? @get (P primary_key, S secondary_key)
+  {
+    init ();
+    var hs = storage  get (primary_key);
+    foreach (HashMap<S,V> h in hs) {
+      if (h.has_key (secondary_key))
+        return h  get (secondary_key);
+    }
+    return null;
+  }
+  public int size { get { return storage.size; } }
+  private void init ()
+  {
+    if (storage == null)
+      storage = new Gee.HashMultiMap<P,HashMap<S,V>> ();
+  }
+  // Serializable Interface
+  protected ParamSpec[] properties { get; set; }
+  public GLib.HashTable<string,GLib.ParamSpec> ignored_serializable_properties { get; protected set; }
+  public string? serialized_xml_node_value { get; protected set; default=null; }
+  public GLib.HashTable<string,GXml.Node> unknown_serializable_property { get; protected set; }
+
+  public virtual bool property_use_nick () { return false; }
+
+  public virtual string node_name ()
+  {
+    return "";
+  }
+  public string default_node_name ()
+  {
+    return get_type().name().down();
+  }
+
+  public virtual GLib.ParamSpec? find_property_spec (string property_name)
+  {
+    return default_find_property_spec (property_name);
+  }
+
+  public virtual void init_properties ()
+  {
+    default_init_properties ();
+  }
+
+  public virtual GLib.ParamSpec[] list_serializable_properties ()
+  {
+    return default_list_serializable_properties ();
+  }
+
+  public virtual void get_property_value (GLib.ParamSpec spec, ref Value val)
+  {
+    default_get_property_value (spec, ref val);
+  }
+
+  public virtual void set_property_value (GLib.ParamSpec spec, GLib.Value val)
+  {
+    default_set_property_value (spec, val);
+  }
+
+  public virtual bool transform_from_string (string str, ref GLib.Value dest)
+  {
+    return false;
+  }
+
+  public virtual bool transform_to_string (GLib.Value val, ref string str)
+  {
+    return false;
+  }
+
+  public virtual GXml.Node? serialize (GXml.Node node)
+                              throws GLib.Error
+                              requires (node is Element)
+  {
+    return default_serialize (node);
+  }
+  public GXml.Node? default_serialize (GXml.Node node)
+                              throws GLib.Error
+                              requires (node is Element)
+  {
+    foreach (HashMap<S,V> h in storage.get_values ()) {
+      foreach (V v in h.values) {
+        if (v is Serializable)
+          ((GXml.Serializable) v).serialize (node);;
+      }
+    }
+    return node;
+  }
+  public virtual GXml.Node? serialize_property (GXml.Element element,
+                                        GLib.ParamSpec prop)
+                                        throws GLib.Error
+  {
+    return default_serialize_property (element, prop);
+  }
+  public GXml.Node? default_serialize_property (GXml.Element element,
+                                        GLib.ParamSpec prop)
+                                        throws GLib.Error
+  {
+    return element;
+  }
+  public virtual GXml.Node? deserialize (GXml.Node node)
+                                    throws GLib.Error
+                                    requires (node_name () != null)
+  {
+    return default_deserialize (node);
+  }
+  public GXml.Node? default_deserialize (GXml.Node node)
+                    throws GLib.Error
+                    requires (value_type.is_a (typeof (GXml.Serializable)))
+                    requires (value_type.is_a (typeof (SerializableMapDualId)))
+  {
+    if (node is Element) {
+      foreach (GXml.Node n in node.child_nodes) {
+        var obj = (SerializableMapDualId<P,S>) Object.new (value_type);
+        ((Serializable) obj).deserialize (n);
+        @set (obj.primary_id (), obj.secondary_id (), obj);
+      }
+    }
+    return node;
+  }
+  public virtual bool deserialize_property (GXml.Node property_node)
+                                            throws GLib.Error
+  {
+    return default_deserialize_property (property_node);
+  }
+  public bool default_deserialize_property (GXml.Node property_node)
+                                            throws GLib.Error
+  {
+    return true;
+  }
+}
+
diff --git a/gxml/SerializableMapDualId.vala b/gxml/SerializableMapDualId.vala
new file mode 100644
index 0000000..2a80004
--- /dev/null
+++ b/gxml/SerializableMapDualId.vala
@@ -0,0 +1,27 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* SerializableGeeTreeModel.vala
+ *
+ * Copyright (C) 2013  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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Daniel Espinosa <esodan gmail com>
+ */
+using GXml;
+public interface SerializableMapDualId<P,S> : Object
+{
+  public abstract P primary_id  ();
+  public abstract S secondary_id ();
+}
diff --git a/test/GXmlTest.vala b/test/GXmlTest.vala
index 51fccc9..8811ca5 100644
--- a/test/GXmlTest.vala
+++ b/test/GXmlTest.vala
@@ -39,6 +39,7 @@ class GXmlTest {
                SerializableTest.add_tests ();
                SerializableObjectModelTest.add_tests ();
                SerializableGeeTreeMapTest.add_tests ();
+               SerializableGeeDualKeyMapTest.add_tests ();
 
                Test.run ();
 
diff --git a/test/Makefile.am b/test/Makefile.am
index 4ce0b0f..4296024 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -39,6 +39,7 @@ gxml_test_SOURCES = \
        SerializationTest.vala \
        SerializableObjectModelTest.vala \
        SerializableGeeTreeMapTest.vala \
+       SerializableGeeDualKeyMapTest.vala \
        $(NULL)
 
 gxml_test.vala.stamp: $(gxml_test_SOURCES)
diff --git a/test/SerializableGeeDualKeyMapTest.vala b/test/SerializableGeeDualKeyMapTest.vala
new file mode 100644
index 0000000..3a28c53
--- /dev/null
+++ b/test/SerializableGeeDualKeyMapTest.vala
@@ -0,0 +1,210 @@
+using GXml;
+using Gee;
+
+class Spaces : SerializableObjectModel, SerializableMapDualId<string,string>
+{
+  public string primary_id  () { return owner; }
+  public string secondary_id () { return name; }
+  public string name { get; set; }
+  public string owner { get; set; }
+  public Spaces.full ( string owner, string name)
+  {
+    this.name = name;
+    this.owner = owner;
+  }
+  public override void init_properties ()
+  {
+    default_init_properties ();
+  }
+  public override string to_string () { return name; }
+}
+
+class SerializableGeeDualKeyMapTest : GXmlTest
+{
+  public static void add_tests ()
+  {
+    Test.add_func ("/gxml/serializable/serializable_dual_key_map/api",
+    () => {
+      try {
+        var c = new SerializableDualKeyMap<string,string,Spaces> ();
+        var o1 = new Spaces.full ("Floor", "Big");
+        var o2 = new Spaces.full ("Wall", "Small");
+        var o3 = new Spaces.full ("Floor", "Bigger");
+        var o4 = new Spaces.full ("Wall","Smallest");
+        c.set (o1.owner, o1.name, o1);
+        c.set (o2.owner, o2.name, o2);
+        c.set (o3.owner, o3.name, o3);
+        c.set (o4.owner, o4.name, o4);
+        if (c.size != 4) {
+          stdout.printf (@"SIZE: $(c.size)\n");
+          assert_not_reached ();
+        }
+        bool found1 = false;
+        bool found2 = false;
+        bool found3 = false;
+        bool found4 = false;
+        foreach (Spaces s in c.values ()) {
+          if (s.owner == "Floor" && s.name == "Big")
+            found1 = true;
+          if (s.owner == "Wall" && s.name == "Small")
+            found2 = true;
+          if (s.owner == "Floor" && s.name == "Bigger")
+            found3 = true;
+          if (s.owner == "Wall" && s.name == "Smallest")
+            found4 = true;
+        }
+        if (!found1) {
+          stdout.printf (@"Not found 'Floor' & 'Big':\n");
+          assert_not_reached ();
+        }
+        if (!found2) {
+          stdout.printf (@"Not found 'Wall' & 'Small':\n");
+          assert_not_reached ();
+        }
+        if (!found3) {
+          stdout.printf (@"Not found 'Floor' & 'Bigger':\n");
+          assert_not_reached ();
+        }
+        if (!found4) {
+          stdout.printf (@"Not found 'Wall' & 'Smallest':\n");
+          assert_not_reached ();
+        }
+        found1 = found3 = false;
+        foreach (Spaces s in c.values_for_key ("Floor")) {
+          if (s.owner == "Floor" && s.name == "Big")
+            found1 = true;
+          if (s.owner == "Floor" && s.name == "Bigger")
+            found3 = true;
+        }
+        if (!found1) {
+          stdout.printf (@"Not found 'Floor' & 'Big':\n");
+          assert_not_reached ();
+        }
+        if (!found3) {
+          stdout.printf (@"Not found 'Floor' & 'Bigger':\n");
+          assert_not_reached ();
+        }
+        found2 = found4 = true;
+        foreach (string k2 in c.secondary_keys ("Wall")) {
+          var s = c.get ("Wall", k2);
+          if (s.owner == "Wall" && s.name == "Small")
+            found2 = true;
+          if (s.owner == "Wall" && s.name == "Smallest")
+            found4 = true;
+        }
+        if (!found2) {
+          stdout.printf (@"Not found 'Wall' & 'Small':\n");
+          assert_not_reached ();
+        }
+        if (!found4) {
+          stdout.printf (@"Not found 'Wall' & 'Smallest':\n");
+          assert_not_reached ();
+        }
+      }
+      catch (GLib.Error e) {
+        stdout.printf (@"ERROR: $(e.message)");
+      }
+    });
+    Test.add_func ("/gxml/serializable/serializable_dual_key_map/serialize",
+    () => {
+      try {
+        var c = new SerializableDualKeyMap<string,string,Spaces> ();
+        var o1 = new Spaces.full ("Floor", "Big");
+        var o2 = new Spaces.full ("Wall", "Small");
+        var o3 = new Spaces.full ("Floor", "Bigger");
+        var o4 = new Spaces.full ("Wall","Smallest");
+        c.set (o1.owner, o1.name, o1);
+        c.set (o2.owner, o2.name, o2);
+        c.set (o3.owner, o3.name, o3);
+        c.set (o4.owner, o4.name, o4);
+        var doc = new Document ();
+        var root = doc.create_element ("root");
+        doc.append_child (root);
+        c.serialize (root);
+        if (!root.has_child_nodes ()) {
+          stdout.printf (@"ERROR: root node have no childs $(doc)\n");
+          assert_not_reached ();
+        }
+        bool found1 = false;
+        bool found2 = false;
+        bool found3 = false;
+        bool found4 = false;
+        foreach (GXml.Node n in root.child_nodes) {
+          if (n is Element && n.node_name == "spaces") {
+            var name = ((Element) n).get_attribute_node ("name");
+            var owner = ((Element) n).get_attribute_node ("owner");
+            if (name != null && owner != null) {
+              if (name.node_value == "Big" && owner.node_value == "Floor") found1 = true;
+              if (name.node_value == "Small" && owner.node_value == "Wall") found2 = true;
+              if (name.node_value == "Bigger" && owner.node_value == "Floor") found3 = true;
+              if (name.node_value == "Smallest" && owner.node_value == "Wall") found4 = true;
+            }
+          }
+        }
+        if (!found1) {
+          stdout.printf (@"ERROR: 'Big' / 'Floor' not found\n$(doc)");
+          assert_not_reached ();
+        }
+        if (!found2) {
+          stdout.printf (@"ERROR: 'Small' / 'Wall' not found\n$(doc)");
+          assert_not_reached ();
+        }
+        if (!found3) {
+          stdout.printf (@"ERROR: 'Bigger' / 'Floor' not found\n$(doc)");
+          assert_not_reached ();
+        }
+        if (!found4) {
+          stdout.printf (@"ERROR: 'Smallest' / 'Wall' not found\n$(doc)");
+          assert_not_reached ();
+        }
+      }
+      catch (GLib.Error e) {
+        stdout.printf (@"ERROR: $(e.message)");
+        assert_not_reached ();
+      }
+    });
+    Test.add_func ("/gxml/serializable/serializable_dual_key_map/deserialize",
+    () => {
+      try {
+        var doc = new Document.from_string ("""<?xml version="1.0"?>
+<root><spaces name="Small" owner="Wall"/><spaces name="Smallest" owner="Wall"/><spaces name="Big" 
owner="Floor"/><spaces name="Bigger" owner="Floor"/></root>""");
+        var c = new SerializableDualKeyMap<string,string,Spaces> ();
+        c.deserialize (doc.document_element);
+        if (c.size != 4) {
+          stdout.printf (@"ERROR: incorrect size must be 4 got: $(c.size)\n");
+          assert_not_reached ();
+        }
+        bool found1 = false;
+        bool found2 = false;
+        bool found3 = false;
+        bool found4 = false;
+        foreach (Spaces s in c.values ()) {
+          if (s.owner == "Floor" && s.name == "Big") found1 = true;
+          if (s.owner == "Wall" && s.name == "Small") found2 = true;
+          if (s.owner == "Floor" && s.name == "Bigger") found3 = true;
+          if (s.owner == "Wall" && s.name == "Smallest") found4 = true;
+        }
+        if (!found1) {
+          stdout.printf (@"ERROR: 'Big' / 'Floor' not found\n$(doc)");
+          assert_not_reached ();
+        }
+        if (!found2) {
+          stdout.printf (@"ERROR: 'Small' / 'Wall' not found\n$(doc)");
+          assert_not_reached ();
+        }
+        if (!found3) {
+          stdout.printf (@"ERROR: 'Bigger' / 'Floor' not found\n$(doc)");
+          assert_not_reached ();
+        }
+        if (!found4) {
+          stdout.printf (@"ERROR: 'Smallest' / 'Wall' not found\n$(doc)");
+          assert_not_reached ();
+        }
+      }
+      catch (GLib.Error e) {
+        stdout.printf (@"ERROR: $(e.message)");
+        assert_not_reached ();
+      }
+    });
+  }
+}


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