package com.google.maps.android;

import java.util.Collection;
import java.util.HashMap;

/**
 * Extension of HashMap that provides two main features. Firstly it allows reverse lookup
 * for a key given a value, by storing a second HashMap internally which maps values to keys.
 * Secondly, it supports Collection values, in which case, each item in the collection is
 * used as a key in the internal reverse HashMap. It's therefore up to the caller to ensure
 * the overall set of values, and collection values, are unique.
 *
 * Used by GeoJsonRenderer to store GeoJsonFeature instances mapped to corresponding Marker,
 * Polyline, and Polygon map objects. We want to look these up in reverse to provide access
 * to GeoJsonFeature instances when map objects are clicked.
 */
public class BiMultiMap<K> extends HashMap<K, Object> {

    private final HashMap<Object, K> mValuesToKeys = new HashMap<>();

    public void putAll(HashMap<K, Object> map) {
        // put() manages the reverse map, so call it on each entry.
        for (Entry<K, Object> entry : map.entrySet()) {
            put(entry.getKey(), entry.getValue());
        }
    }

    @Override
    public Object put(K key, Object value) {
        // Store value/key in the reverse map, and store each item in the value
        // if the value is a collection.
        if (value instanceof Collection) {
            for (Object valueItem: (Collection) value) {
                mValuesToKeys.put(valueItem, key);
            }
        } else {
            mValuesToKeys.put(value, key);
        }
        return super.put(key, value);
    }

    public Object remove(Object key) {
        // Also remove the value/key from the reverse map.
        mValuesToKeys.remove(get(key));
        return super.remove(key);
    }

    /**
     * Reverse lookup of key by value.
     *
     * @param value Object value to lookup
     * @return K the key for the given value
     */
    public K getKey(Object value) {
        return mValuesToKeys.get(value);
    }

}

@@ -81,16 +81,38 @@
 HashMap;
+%0Aimport java.util.Map;
 %0A%0A/**%0A *
@@ -868,20 +868,16 @@
 e final 
-Hash
 Map%3CObje
@@ -917,16 +917,30 @@
 p%3C%3E();%0A%0A
+    @Override%0A
     publ
@@ -954,33 +954,34 @@
  putAll(
-HashMap%3CK, Object
+Map%3C? extends K, ?
 %3E map) %7B
@@ -1068,25 +1068,30 @@
  (Entry%3C
-K, Object
+? extends K, ?
 %3E entry 
@@ -1286,82 +1286,488 @@
  map
-, and store each item in the value%0A        // if the value is a collection
+.%0A        mValuesToKeys.put(value, key);%0A        return super.put(key, value);%0A    %7D%0A%0A    public Object put(K key, Collection values) %7B%0A        // Store values/key in the reverse map.%0A        for (Object value : values) %7B%0A            mValuesToKeys.put(value, key);%0A        %7D%0A        return super.put(key, values);%0A    %7D%0A%0A    @Override%0A    public Object remove(Object key) %7B%0A        Object value = super.remove(key);%0A        // Also remove the value(s) and key from the reverse map
 .%0A  
@@ -1840,16 +1840,17 @@
 alueItem
+ 
 : (Colle
@@ -1891,27 +1891,30 @@
 aluesToKeys.
-put
+remove
 (valueItem, 
@@ -1911,21 +1911,16 @@
 alueItem
-, key
 );%0A     
@@ -1967,38 +1967,36 @@
 aluesToKeys.
-put
+remove
 (value
-, key
 );%0A        %7D
@@ -2010,38 +2010,22 @@
   return
- super.put(key,
  value
-)
 ;%0A    %7D%0A
@@ -2033,138 +2033,291 @@
     
-public Object remove(Object key) %7B%0A        // Also remove the value/key from the reverse map.%0A        mValuesToKeys.remove(get(key
+@Override%0A    public void clear() %7B%0A        super.clear();%0A        mValuesToKeys.clear();%0A    %7D%0A%0A    @SuppressWarnings(%22unchecked%22)%0A    @Override%0A    public BiMultiMap%3CK%3E clone() %7B%0A        BiMultiMap%3CK%3E cloned = new BiMultiMap%3C%3E();%0A        cloned.putAll((Map%3CK, Object%3E) super.clone(
 ));%0A
@@ -2331,33 +2331,22 @@
  return 
-super.remove(key)
+cloned
 ;%0A    %7D%0A
@@ -2420,24 +2420,17 @@
 m value 
-Object v
+V
 alue to 
@@ -2456,14 +2456,8 @@
 rn K
- the k
 ey f

Fix BiMultiMap.remove() and implement missing methods (clear, clone).