package net.acomputerdog.core.storage;

import java.util.HashMap;
import java.util.Map;

/**
 * Similar to a HashMap, but with a category->key->value mapping.
 *
 * @param <C> The category (1st) identifier type
 * @param <K> The key (2nd) identifier type
 * @param <V> The value type
 */
public class MultiBind<C, K, V> {
    private final Map<C, Map<K, V>> bindData = new HashMap<C, Map<K, V>>();

    public void put(C category, K key, V value) {
        getOrCreateCategory(category).put(key, value);
    }

    public V getValue(C category, K key) {
        Map<K, V> cat = getCategory(category);
        if (cat == null) {
            return null;
        }
        return cat.get(key);
    }

    public Map<K, V> getCategory(C category) {
        return bindData.get(category);
    }

    public boolean categoryExists(C category) {
        return bindData.containsKey(category);
    }

    public boolean keyExists(C category, K key) {
        Map<K, V> cat = getCategory(category);
        return cat != null && cat.containsKey(key);
    }

    private Map<K, V> getOrCreateCategory(C category) {
        Map<K, V> cat = getCategory(category);
        if (cat == null) {
            bindData.put(category, cat = new HashMap<K, V>());
        }
        return cat;
    }
}

@@ -33,16 +33,46 @@
 orage;%0A%0A
+import java.util.Collections;%0A
 import j
@@ -353,192 +353,676 @@
     
-private final Map%3CC, Map%3CK, V%3E%3E bindData = new HashMap%3CC, Map%3CK, V%3E%3E();%0A%0A    public void put(C category, K key, V value) %7B%0A        getOrCreateCategory(category).put(key, value);%0A    %7D%0A
+/**%0A     * The map that holds the actual data for this MultiBind%0A     */%0A    private final Map%3CC, Map%3CK, V%3E%3E bindData = new HashMap%3CC, Map%3CK, V%3E%3E();%0A%0A    /**%0A     * Creates a new MultiBind%0A     */%0A    public MultiBind() %7B%0A        super();%0A    %7D%0A%0A    /**%0A     * Adds a value to this MultiBind%0A     *%0A     * @param category The category%0A     * @param key      The key%0A     * @param value    The value%0A     */%0A    public void put(C category, K key, V value) %7B%0A        getOrCreateCategory(category).put(key, value);%0A    %7D%0A%0A    /**%0A     * Gets a value from this MultiBind%0A     * @param category The category%0A     * @param key The key%0A     * @return Return the value%0A     */
 %0A   
@@ -1198,32 +1198,203 @@
 et(key);%0A    %7D%0A%0A
+    /**%0A     * Gets all the mappings from a specified category%0A     * @param category The category to get%0A     * @return Return all the mappings from the category%0A     */%0A
     public Map%3CK
@@ -1431,32 +1431,60 @@
 %0A        return 
+Collections.unmodifiableMap(
 bindData.get(cat
@@ -1481,32 +1481,33 @@
 ta.get(category)
+)
 ;%0A    %7D%0A%0A    pub
@@ -1507,261 +1507,793 @@
     
-public boolean categoryExists(C category) %7B%0A        return bindData.containsKey(category);%0A    %7D%0A%0A    public boolean keyExists(C category, K key) %7B%0A        Map%3CK, V%3E cat = getCategory(category);%0A        return cat != null && cat.containsKey(key);%0A    %7D%0A
+/**%0A     * Check if a category exists.%0A     * @param category The category to check%0A     * @return Return true if the category exists, false otherwise%0A     */%0A    public boolean categoryExists(C category) %7B%0A        return bindData.containsKey(category) && bindData.get(category).size() %3E 0;%0A    %7D%0A%0A    /**%0A     * Check if a key exists%0A     * @param category The category to check%0A     * @param key The key to check%0A     * @return Return true if the key has a value%0A     */%0A    public boolean keyExists(C category, K key) %7B%0A        Map%3CK, V%3E cat = getCategory(category);%0A        return cat != null && cat.containsKey(key);%0A    %7D%0A%0A    /**%0A     * Get or create a map of values for a category%0A     * @param category The category%0A     * @return Return a map of values for a category%0A     */
 %0A   

Add comments and update code of MultiBind