<commit_before>/* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
 * HashThreeMap.vala
 *
 * Copyright (C) 2016  <NAME> <<EMAIL>>
 *
 * 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:
 *      <NAME> <<EMAIL>>
 */

using Gee;

/**
 * A class impementing {@link Collection} to store references to
 * child {@link DomElement} of {@link Collection.element}, using three attributes in
 * items as primary, secondary tertiary keys or {@link MappeableElementThreeKey.get_map_pkey},
 * {@link MappeableElementThreeKey.get_map_skey}
 * and {@link MappeableElementThreeKey.get_map_tkey}
 * methods if {@link MappeableElementThreeKey} are implemented
 * by items to be added. All keys should be defined in node, otherwise
 * it is not added; but keeps it as a child node of actual
 * {@link Collection.element}.
 *
 * If {@link GXml.Element} to be added is of type {@link Collection.items_type}
 * and implements {@link MappeableElementThreeKey}, you should set
 * {@link attribute_primary_key}, {@link attribute_secondary_key}
 * and  {@link attribute_third_key}
 * to null in order to use returned value of {@link MappeableElementThreeKey.get_map_pkey},
 * {@link MappeableElementThreeKey.get_map_skey}
 * and {@link MappeableElementThreeKey.get_map_tkey}
 * as keys.
 *
 * {{{
 *   public class YourObject : GXml.Element, MappeableElementThreeKey {
 *    [Description (nick="::Name")]
 *    public string name { get; set; }
 *    public string code { get; set; }
 *    public string category { get; set; }
 *    public string get_map_primary_key () { return code; }
 *    public string get_map_secondary_key () { return name; }
 *    public string get_map_third_key () { return category; }
 *   }
 *   public class YourList : HashThreeMap {
 *    construct {
 *      try { initialize_with (typeof (YourObject)); }
 *      catch (GLib.Error e) {
 *        warning ("Initialization error for collection type: %s : %s"
 *             .printf (get_type ().name(), e.message));
 *      }
 *    }
 *   }
 * }}}
 */
public class GXml.HashThreeMap : GXml.BaseCollection, ThreeMap {
  /**
   * A hashtable with all keys as string to node's index refered. Don't modify it manually.
   */
  protected Gee.HashMap<string,Gee.HashMap<string,Gee.HashMap<string,int>>> _hashtable = new Gee.HashMap<string,Gee.HashMap<string,Gee.HashMap<string,int>>> ();
  /**
   * 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;
  /**
   * Element's attribute name used to refer of container's element as third key.
   * You should define it at construction time
   * our set it as a construction property.
   */
  protected string _attribute_third_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; }
  }
  /**
   * An attribute's name in items to be added and used to retrieve elements
   * as third key.
   */
  public string attribute_third_key {
    get { return _attribute_third_key; } construct set { _attribute_third_key = value; }
  }
  /**
   * Convenient function to initialize a {@link GXml.HashMap} collection, using
   * given element, items' type and name.
   */
  public void initialize_element_with_keys (GXml.Element element,
                                  GLib.Type items_type,
                                  string attribute_primary_key,
                                  string attribute_secondary_key,
                                  string attribute_third_key) throws GLib.Error
  {
    initialize (items_type);
    initialize_element (element);
    _attribute_primary_key = attribute_primary_key;
    _attribute_secondary_key = attribute_secondary_key;
    _attribute_third_key = attribute_third_key;
  }

  /**
   * Convenient function to initialize a {@link GXml.HashMap} 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,
                                  string attribute_third_key) throws GLib.Error
  {
    initialize (items_type);
    _attribute_primary_key = attribute_primary_key;
    _attribute_secondary_key = attribute_secondary_key;
    _attribute_third_key = attribute_third_key;
  }
  /**
   * Returns an {@link DomElement} in the collection using given string keys.
   */
  public new DomElement? get (string primary_key, string secondary_key, string third_key) {
    if (!_hashtable.has_key (primary_key)) return null;
    var ht = _hashtable.get (primary_key);
    if (ht == null) return null;
    if (!ht.has_key (secondary_key)) return null;
    var hte = ht.get (secondary_key);
    if (hte == null) return null;
    if (!hte.has_key (third_key)) return null;
    var i = hte.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.has_key (key)) return true;<commit_msg>HashThreeMap: Fix get() implementation<commit_after>/* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
/*
 * HashThreeMap.vala
 *
 * Copyright (C) 2016  <NAME> <<EMAIL>>
 *
 * 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:
 *      <NAME> <<EMAIL>>
 */

using Gee;

/**
 * A class impementing {@link Collection} to store references to
 * child {@link DomElement} of {@link Collection.element}, using three attributes in
 * items as primary, secondary tertiary keys or {@link MappeableElementThreeKey.get_map_pkey},
 * {@link MappeableElementThreeKey.get_map_skey}
 * and {@link MappeableElementThreeKey.get_map_tkey}
 * methods if {@link MappeableElementThreeKey} are implemented
 * by items to be added. All keys should be defined in node, otherwise
 * it is not added; but keeps it as a child node of actual
 * {@link Collection.element}.
 *
 * If {@link GXml.Element} to be added is of type {@link Collection.items_type}
 * and implements {@link MappeableElementThreeKey}, you should set
 * {@link attribute_primary_key}, {@link attribute_secondary_key}
 * and  {@link attribute_third_key}
 * to null in order to use returned value of {@link MappeableElementThreeKey.get_map_pkey},
 * {@link MappeableElementThreeKey.get_map_skey}
 * and {@link MappeableElementThreeKey.get_map_tkey}
 * as keys.
 *
 * {{{
 *   public class YourObject : GXml.Element, MappeableElementThreeKey {
 *    [Description (nick="::Name")]
 *    public string name { get; set; }
 *    public string code { get; set; }
 *    public string category { get; set; }
 *    public string get_map_primary_key () { return code; }
 *    public string get_map_secondary_key () { return name; }
 *    public string get_map_third_key () { return category; }
 *   }
 *   public class YourList : HashThreeMap {
 *    construct {
 *      try { initialize_with (typeof (YourObject)); }
 *      catch (GLib.Error e) {
 *        warning ("Initialization error for collection type: %s : %s"
 *             .printf (get_type ().name(), e.message));
 *      }
 *    }
 *   }
 * }}}
 */
public class GXml.HashThreeMap : GXml.BaseCollection, ThreeMap {
  /**
   * A hashtable with all keys as string to node's index refered. Don't modify it manually.
   */
  protected Gee.HashMap<string,Gee.HashMap<string,Gee.HashMap<string,int>>> _hashtable = new Gee.HashMap<string,Gee.HashMap<string,Gee.HashMap<string,int>>> ();
  /**
   * 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;
  /**
   * Element's attribute name used to refer of container's element as third key.
   * You should define it at construction time
   * our set it as a construction property.
   */
  protected string _attribute_third_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; }
  }
  /**
   * An attribute's name in items to be added and used to retrieve elements
   * as third key.
   */
  public string attribute_third_key {
    get { return _attribute_third_key; } construct set { _attribute_third_key = value; }
  }
  /**
   * Convenient function to initialize a {@link GXml.HashMap} collection, using
   * given element, items' type and name.
   */
  public void initialize_element_with_keys (GXml.Element element,
                                  GLib.Type items_type,
                                  string attribute_primary_key,
                                  string attribute_secondary_key,
                                  string attribute_third_key) throws GLib.Error
  {
    initialize (items_type);
    initialize_element (element);
    _attribute_primary_key = attribute_primary_key;
    _attribute_secondary_key = attribute_secondary_key;
    _attribute_third_key = attribute_third_key;
  }

  /**
   * Convenient function to initialize a {@link GXml.HashMap} 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,
                                  string attribute_third_key) throws GLib.Error
  {
    initialize (items_type);
    _attribute_primary_key = attribute_primary_key;
    _attribute_secondary_key = attribute_secondary_key;
    _attribute_third_key = attribute_third_key;
  }
  /**
   * Returns an {@link DomElement} in the collection using given string keys.
   */
  public new DomElement? get (string primary_key, string secondary_key, string third_key) {
    if (!_hashtable.has_key (primary_key)) return null;
    var ht = _hashtable.get (primary_key);
    if (ht == null) return null;
    if (!ht.has_key (secondary_key)) return null;
    var hte = ht.get (secondary_key);
    if (hte == null) return null;
    if (!hte.has_key (third_key)) return null;
    var i = hte.get (third_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.has_key (key)) return true;
{'fraction_non_alphanumeric': 0.08914521426934535, 'fraction_numerical': 0.0012222137346268429, 'mean_word_length': 3.156190476190476, 'pattern_counts': {'":': 2, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5249217', 'n_tokens_mistral': 3734, 'n_tokens_neox': 3680, 'n_words': 1306}