[gxml] Added GomHashPairedMap a two key collection map



commit b9a2b61feec126248a4a4102d90b237cfbedfa80
Author: Daniel Espinosa <esodan gmail com>
Date:   Tue Feb 21 11:00:16 2017 -0600

    Added GomHashPairedMap a two key collection map

 gxml/GomCollections.vala |  208 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 205 insertions(+), 3 deletions(-)
---
diff --git a/gxml/GomCollections.vala b/gxml/GomCollections.vala
index 5c213a5..899af4d 100644
--- a/gxml/GomCollections.vala
+++ b/gxml/GomCollections.vala
@@ -334,13 +334,14 @@ public class GXml.GomHashMap : GXml.BaseCollection, GXml.GomCollection {
    */
   protected HashTable<string,int> _hashtable = new HashTable<string,int> (str_hash,str_equal);
   /**
-   * Element used to refer of containier element. You should define it at construction time
+   * Element's attribute name used to refer of container's element.
+   * You should define it at construction time
    * our set it as a construction property.
    */
   protected string _attribute_key;
   /**
-   * An attribute's name in items to be added and used to retrieve a key to be
-   * used in collection.
+   * An attribute's name in items to be added and used to retrieve elements
+   * as key.
    */
   public string attribute_key {
     get { return _attribute_key; } construct set { _attribute_key = value; }
@@ -402,6 +403,9 @@ public class GXml.GomHashMap : GXml.BaseCollection, GXml.GomCollection {
    * Attribute should be a valid {@link DomElement} attribute or
    * a {@link GomObject} property identified using a nick with a '::' prefix.
    *
+   * If there are more elements with same key, they are keep as child nodes
+   * but the one in collection will be the last one to be found.
+   *
    * Return: false if element should not be added to collection.
    */
   public override bool validate_append (int index, DomElement element) throws GLib.Error {
@@ -430,3 +434,201 @@ public class GXml.GomHashMap : GXml.BaseCollection, GXml.GomCollection {
     return true;
   }
 }
+
+
+/**
+ * Inteface to be implemented by {@link GomElement} derived classes
+ * in order to provide a string to be used in {@link GomHasMap} as key.
+ *
+ * If {@link GomHashMap} has set its {@link GomHashMap.attribute_key}
+ * its value has precedence over this method.
+ */
+public interface GXml.MappeableElementPairKey : Object, DomElement {
+  public abstract string get_map_primary_key ();
+  public abstract string get_map_secondary_key ();
+}
+
+/**
+ * A class impementing {@link GomCollection} to store references to
+ * child {@link DomElement} of {@link element}, using two attributes in
+ * items as primary and secondary keys or {@link MappeableElementPairKey.map_primary_key}
+ * and {@link MappeableElementPairKey.map_secondary_key} methods if
+ * {@link MappeableElementPairKey} is implemented
+ * by items to be added. If one or both keys are not defined in node,
+ * it is not added; but keeps it as a child node of actual
+ * {@link GomCollection.element}.
+ *
+ * If {@link GomElement} to be added is of type {@link GomCollection.items_type}
+ * and implements {@link MappeableElementPairKey}, you should set
+ * {@link GomHashMap.attribute_primary_key} and {@link GomHashMap.attribute_secondary_key}
+ * to null in order to use returned value of {@link MappeableElementPairKey.map_primary_key}
+ * and {@link MappeableElementPairKey.map_secondary_key}
+ * as keys.
+ *
+ * {{{
+ *   public class YourObject : GomElement {
+ *    [Description (nick="::Name")]
+ *    public string name { get; set; }
+ *    public string code { get; set; }
+ *   }
+ *   public class YourList : GomHashPairedMap {
+ *    construct {
+ *      try { initialize_with_key (typeof (YourObject),"Name"); }
+ *      catch (GLib.Error e) {
+ *        warning ("Initialization error for collection type: %s : %s"
+ *             .printf (get_type ().name(), e.message));
+ *      }
+ *    }
+ *   }
+ * }}}
+ */
+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);
+  /**
+   * Element's attribute name used to refer of container's element as primery key.
+   * You should define it at construction time
+   * our set it as a construction property.
+   */
+  protected string _attribute_primary_key;
+  /**
+   * Element's attribute name used to refer of container's element as secondary key.
+   * You should define it at construction time
+   * our set it as a construction property.
+   */
+  protected string _attribute_secondary_key;
+  /**
+   * An attribute's name in items to be added and used to retrieve elements
+   * as primary key.
+   */
+  public string attribute_primary_key {
+    get { return _attribute_primary_key; } construct set { _attribute_primary_key = value; }
+  }
+  /**
+   * An attribute's name in items to be added and used to retrieve elements
+   * as secondary key.
+   */
+  public string attribute_secondary_key {
+    get { return _attribute_secondary_key; } construct set { _attribute_secondary_key = value; }
+  }
+  /**
+   * Convenient function to initialize a {@link GomHashMap} collection, using
+   * given element, items' type and name.
+   */
+  public void initialize_element_with_keys (GomElement element,
+                                  GLib.Type items_type,
+                                  string attribute_primary_key,
+                                  string attribute_secondary_key) throws GLib.Error
+  {
+    initialize (items_type);
+    initialize_element (element);
+    _attribute_primary_key = attribute_primary_key;
+    _attribute_secondary_key = attribute_secondary_key;
+    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_keys (GLib.Type items_type,
+                                  string attribute_primary_key,
+                                  string attribute_secondary_key) throws GLib.Error
+  {
+    initialize (items_type);
+    _attribute_primary_key = attribute_primary_key;
+    _attribute_secondary_key = attribute_secondary_key;
+  }
+  /**
+   * Returns an {@link DomElement} in the collection using given string keys.
+   */
+  public new DomElement? get (string primary_key, string secondary_key) {
+    if (!_hashtable.contains (primary_key)) return null;
+    var ht = _hashtable.get (primary_key);
+    if (ht == null) return null;
+    if (!ht.contains (secondary_key)) return null;
+    var i = ht.get (secondary_key);
+    return _element.child_nodes.get (i) as DomElement;
+  }
+  /**
+   * Returns true if @key is used in collection as primery key.
+   */
+  public bool has_primary_key (string key) {
+    if (_hashtable.contains (key)) return true;
+    return false;
+  }
+  /**
+   * Returns true if @key is used in collection as secondary key
+   * with @pkey as primary.
+   */
+  public bool has_secondary_key (string pkey, string key) {
+    if (!(_hashtable.contains (pkey))) return false;
+    var ht = _hashtable.get (pkey);
+    if (ht == null) return false;
+    if (ht.contains (key)) return true;
+    return false;
+  }
+  /**
+   * Returns list of primary keys used in collection.
+   */
+  public GLib.List<string> get_primary_keys () {
+    return _hashtable.get_keys ();
+  }
+  /**
+   * 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 ();
+  }
+  /**
+   * Validates if given element has a {@link GomHashMap.attribute_primary_key}
+   * and {@link GomHashMap.attribute_secondary_key} set,
+   * if so adds a new keys pointing to given index and returns true.
+   *
+   * Attribute should be a valid {@link DomElement} attribute or
+   * a {@link GomObject} property identified using a nick with a '::' prefix.
+   *
+   * If there are more elements with same keys, they are keep as child nodes
+   * but the one in collection will be the last one to be found.
+   *
+   * Return: false if element should not be added to collection.
+   */
+  public override bool validate_append (int index, DomElement element) throws GLib.Error {
+    if (!(element is GomElement)) return false;
+#if DEBUG
+    message ("Validating HashMap Element..."
+            +(element as GomElement).write_string ()
+            +" Attrs:"+(element as GomElement).attributes.length.to_string());
+#endif
+    string pkey = null;
+    string skey = null;
+    if (attribute_primary_key != null && attribute_secondary_key != null) {
+      pkey = (element as DomElement).get_attribute (attribute_primary_key);
+      skey = (element as DomElement).get_attribute (attribute_secondary_key);
+      if (pkey == null || skey == null) {
+        pkey = (element as DomElement).get_attribute (attribute_primary_key.down ());
+        skey = (element as DomElement).get_attribute (attribute_secondary_key.down ());
+      }
+    } else {
+      if (items_type.is_a (typeof(MappeableElementPairKey))) {
+        if (!(element is MappeableElementPairKey)) return false;
+        pkey = ((MappeableElementPairKey) element).get_map_primary_key ();
+        skey = ((MappeableElementPairKey) element).get_map_secondary_key ();
+      }
+    }
+    if (pkey == null || skey == null) return false;
+    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);
+    return true;
+  }
+}


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