Extract AbstractMultiMap from HashMultiMap
authorDidier 'Ptitjes <ptitjes@free.fr>
Mon, 28 Sep 2009 11:07:44 +0000 (13:07 +0200)
committerDidier 'Ptitjes <ptitjes@free.fr>
Mon, 28 Sep 2009 14:28:52 +0000 (16:28 +0200)
gee/Makefile.am
gee/abstractmultimap.vala [new file with mode: 0644]
gee/hashmultimap.vala

index 74adec8..e6294f7 100644 (file)
@@ -17,6 +17,7 @@ libgee_la_VALASOURCES = \
        abstractcollection.vala \
        abstractlist.vala \
        abstractmap.vala \
+       abstractmultimap.vala \
        abstractmultiset.vala \
        abstractqueue.vala \
        abstractset.vala \
diff --git a/gee/abstractmultimap.vala b/gee/abstractmultimap.vala
new file mode 100644 (file)
index 0000000..4020f43
--- /dev/null
@@ -0,0 +1,129 @@
+/* abstractmultimap.vala
+ *
+ * Copyright (C) 2009  Ali Sabil
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Ali Sabil <ali.sabil@gmail.com>
+ *     Didier 'Ptitjes Villevalois <ptitjes@free.fr>
+ */
+
+/**
+ * Skeletal implementation of the {@link MultiMap} interface.
+ *
+ * @see HashMultiMap
+ * @see TreeMultiMap
+ */
+public abstract class Gee.AbstractMultiMap<K,V> : GLib.Object, MultiMap<K,V> {
+       public int size {
+               get { return _nitems; }
+       }
+
+       protected Map<K, Collection<V>> _storage_map;
+       private int _nitems = 0;
+       private Set<V> _empty_value_set;
+
+       public AbstractMultiMap (Map<K, Collection<V>> storage_map) {
+               this._storage_map = storage_map;
+               this._empty_value_set = Set.empty<V> ();
+       }
+
+       protected abstract Collection<V> create_value_storage ();
+
+       protected abstract MultiSet<K> create_multi_key_set ();
+
+       protected abstract EqualFunc get_value_equal_func ();
+
+       public Set<K> get_keys () {
+               return _storage_map.keys;
+       }
+
+       public MultiSet<K> get_all_keys () {
+               MultiSet<K> result = create_multi_key_set ();
+               foreach (var entry in _storage_map.entries) {
+                       for (int i = 0; i < entry.value.size; i++) {
+                               result.add (entry.key);
+                       }
+               }
+               return result;
+       }
+
+       public Collection<V> get_values () {
+               var result = new ArrayList<V> (get_value_equal_func ());
+               foreach (var entry in _storage_map.entries) {
+                       foreach (var value in entry.value) {
+                               result.add (value);
+                       }
+               }
+               return result;
+       }
+
+       public bool contains (K key) {
+               return _storage_map.contains (key);
+       }
+
+       public new Collection<V> get (K key) {
+               if (_storage_map.contains (key)) {
+                       return _storage_map.get (key).read_only_view;
+               } else {
+                       return _empty_value_set;
+               }
+       }
+
+       public new void set (K key, V value) {
+               if (_storage_map.contains (key)) {
+                       if (_storage_map.get (key).add (value)) {
+                               _nitems++;
+                       }
+               } else {
+                       var s = create_value_storage ();
+                       s.add (value);
+                       _storage_map.set (key, s);
+                       _nitems++;
+               }
+       }
+
+       public bool remove (K key, V value) {
+               if (_storage_map.contains (key)) {
+                       var values = _storage_map.get (key);
+                       if (values.contains (value)) {
+                               values.remove (value);
+                               _nitems--;
+                               if (values.size == 0) {
+                                       _storage_map.remove (key);
+                               }
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       public bool remove_all (K key) {
+               if (_storage_map.contains (key)) {
+                       int size = _storage_map.get (key).size;
+                       if (_storage_map.remove (key)) {
+                               _nitems -= size;
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       public void clear () {
+               _storage_map.clear ();
+               _nitems = 0;
+       }
+}
index 3e4258a..0961d19 100644 (file)
 /**
  * Hash table implementation of the {@link MultiMap} interface.
  */
-public class Gee.HashMultiMap<K,V> : GLib.Object, MultiMap<K,V> {
-       public int size {
-               get { return _nitems; }
+public class Gee.HashMultiMap<K,V> : AbstractMultiMap<K,V> {
+       public HashFunc key_hash_func {
+               get { return ((HashMap<K, Set<V>>) _storage_map).key_hash_func; }
        }
 
-       public HashFunc key_hash_func { private set; get; }
-
-       public EqualFunc key_equal_func { private set; get; }
+       public EqualFunc key_equal_func {
+               get { return ((HashMap<K, Set<V>>) _storage_map).key_equal_func; }
+       }
 
        public HashFunc value_hash_func { private set; get; }
 
        public EqualFunc value_equal_func { private set; get; }
 
-       private Map<K, Collection<V>> _items;
-       private int _nitems = 0;
-       private Set<V> _empty_value_set;
-
        public HashMultiMap (HashFunc? key_hash_func = null, EqualFunc? key_equal_func = null, HashFunc? value_hash_func = null, EqualFunc? value_equal_func = null) {
-               if (key_hash_func == null) {
-                       key_hash_func = Functions.get_hash_func_for (typeof (K));
-               }
-               if (key_equal_func == null) {
-                       key_equal_func = Functions.get_equal_func_for (typeof (K));
-               }
+               base (new HashMap<K, Set<V>> (key_hash_func, key_equal_func, direct_equal));
                if (value_hash_func == null) {
                        value_hash_func = Functions.get_hash_func_for (typeof (V));
                }
                if (value_equal_func == null) {
                        value_equal_func = Functions.get_equal_func_for (typeof (V));
                }
-               this.key_hash_func = key_hash_func;
-               this.key_equal_func = key_equal_func;
                this.value_hash_func = value_hash_func;
                this.value_equal_func = value_equal_func;
-               this._items = new HashMap<K, Set<V>> (key_hash_func, key_equal_func, direct_equal);
-               this._empty_value_set = new ReadOnlySet<V> (new HashSet<V> (_value_hash_func, _value_equal_func));
-       }
-
-       public Set<K> get_keys () {
-               return _items.keys;
-       }
-
-       public MultiSet<K> get_all_keys () {
-               MultiSet<K> result = new HashMultiSet<K> (_key_hash_func, _key_equal_func);
-               foreach (var entry in _items.entries) {
-                       for (int i = 0; i < entry.value.size; i++) {
-                               result.add (entry.key);
-                       }
-               }
-               return result;
        }
 
-       public Collection<V> get_values () {
-               var result = new ArrayList<V> (_value_equal_func);
-               foreach (var entry in _items.entries) {
-                       foreach (var value in entry.value) {
-                               result.add (value);
-                       }
-               }
-               return result;
+       protected override Collection<V> create_value_storage () {
+               return new HashSet<V> (_value_hash_func, _value_equal_func);
        }
 
-       public bool contains (K key) {
-               return _items.contains (key);
-       }
-
-       public new Collection<V> get (K key) {
-               if (_items.contains (key)) {
-                       return new ReadOnlyCollection<V> (_items.get (key));
-               } else {
-                       return _empty_value_set;
-               }
-       }
-
-       public new void set (K key, V value) {
-               if (_items.contains (key)) {
-                       if (_items.get (key).add (value)) {
-                               _nitems++;
-                       }
-               } else {
-                       var s = new HashSet<V> (_value_hash_func, _value_equal_func);
-                       s.add (value);
-                       _items.set (key, s);
-                       _nitems++;
-               }
-       }
-
-       public bool remove (K key, V value) {
-               if (_items.contains (key)) {
-                       var values = _items.get (key);
-                       if (values.contains (value)) {
-                               values.remove (value);
-                               _nitems--;
-                               if (values.size == 0) {
-                                       _items.remove (key);
-                               }
-                               return true;
-                       }
-               }
-               return false;
-       }
-
-       public bool remove_all (K key) {
-               if (_items.contains (key)) {
-                       int size = _items.get (key).size;
-                       if (_items.remove (key)) {
-                               _nitems -= size;
-                               return true;
-                       }
-               }
-               return false;
+       protected override MultiSet<K> create_multi_key_set () {
+               return new HashMultiSet<K> (key_hash_func, key_equal_func);
        }
 
-       public void clear () {
-               _items.clear ();
-               _nitems = 0;
+       protected override EqualFunc get_value_equal_func () {
+               return _value_equal_func;
        }
 }