package org.metaborg.runtime.task;

import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multiset;

public class ManyToManyMap<K, V> implements Multimap<K, V> {
	private final Multimap<K, V> keyToValue = LinkedHashMultimap.create();
	private final Multimap<V, K> valueToKey = LinkedHashMultimap.create();

	public static <K, V> ManyToManyMap<K, V> create() {
		return new ManyToManyMap<K, V>();
	}

	@Override
	public void clear() {
		keyToValue.clear();
		valueToKey.clear();
	}

	@Override
	public boolean containsKey(Object key) {
		return keyToValue.containsKey(key);
	}

	@Override
	public boolean containsValue(Object value) {
		return keyToValue.containsValue(value);
	}

	@Override
	public Map<K, Collection<V>> asMap() {
		return keyToValue.asMap();
	}

	public Map<V, Collection<K>> asInverseMap() {
		return valueToKey.asMap();
	}

	@Override
	public boolean containsEntry(Object key, Object value) {
		return keyToValue.containsEntry(key, value);
	}

	@Override
	public Collection<Entry<K, V>> entries() {
		return keyToValue.entries();
	}

	@Override
	public Collection<V> get(K key) {
		return keyToValue.get(key);
	}

	public Collection<K> getInverse(V value) {
		return valueToKey.get(value);
	}

	@Override
	public boolean isEmpty() {
		return keyToValue.isEmpty();
	}

	@Override
	public Set<K> keySet() {
		return keyToValue.keySet();
	}

	@Override
	public Multiset<K> keys() {
		return keyToValue.keys();
	}

	@Override
	public boolean put(K key, V value) {
		return keyToValue.put(key, value) & valueToKey.put(value, key);
	}

	@Override
	public boolean putAll(Multimap<? extends K, ? extends V> multimap) {

		boolean result = keyToValue.putAll(multimap);

		for (Entry<? extends K, ? extends V> entry : multimap.entries())
			result &= valueToKey.put(entry.getValue(), entry.getKey());

		return result;
	}

	@Override
	public boolean putAll(K key, Iterable<? extends V> values) {

		boolean result = keyToValue.putAll(key, values);

		for (V value : values)
			result &= valueToKey.put(value, key);

		return result;
	}

	@Override
	public boolean remove(Object key, Object value) {
		return keyToValue.remove(key, value) & valueToKey.remove(value, key);
	}

	@Override
	public Collection<V> removeAll(Object key) {

		Collection<V> removed = keyToValue.removeAll(key);
		for (V r : removed)
			valueToKey.remove(r, key);

		return removed;
	}

	public Collection<K> removeAllInverse(Object value) {

		Collection<K> removed = valueToKey.removeAll(value);
		for (K r : removed)
			keyToValue.remove(r, value);

		return removed;
	}

	@Override
	public Collection<V> replaceValues(K key, Iterable<? extends V> values) {

		Collection<V> replaced = keyToValue.replaceValues(key, values);

		for (V r : replaced)
			valueToKey.remove(r, key);
		for (V value : values)
			valueToKey.put(value, key);

		return replaced;
	}

	@Override
	public int size() {
		return keyToValue.size();
	}

	@Override
	public Collection<V> values() {
		return keyToValue.values();
	}
}
@@ -566,35 +566,24 @@
 , V%3E();%0A%09%7D%0A%0A
-%09@Override%0A
 %09public void
@@ -593,16 +593,16 @@
 ear() %7B%0A
+
 %09%09keyToV
@@ -637,35 +637,24 @@
 lear();%0A%09%7D%0A%0A
-%09@Override%0A
 %09public bool
@@ -721,35 +721,24 @@
 y(key);%0A%09%7D%0A%0A
-%09@Override%0A
 %09public bool
@@ -813,35 +813,24 @@
 value);%0A%09%7D%0A%0A
-%09@Override%0A
 %09public Map%3C
@@ -966,35 +966,24 @@
 sMap();%0A%09%7D%0A%0A
-%09@Override%0A
 %09public bool
@@ -1075,35 +1075,24 @@
 value);%0A%09%7D%0A%0A
-%09@Override%0A
 %09public Coll
@@ -1154,35 +1154,24 @@
 ries();%0A%09%7D%0A%0A
-%09@Override%0A
 %09public Coll
@@ -1303,35 +1303,24 @@
 value);%0A%09%7D%0A%0A
-%09@Override%0A
 %09public bool
@@ -1366,35 +1366,24 @@
 mpty();%0A%09%7D%0A%0A
-%09@Override%0A
 %09public Set%3C
@@ -1426,35 +1426,24 @@
 ySet();%0A%09%7D%0A%0A
-%09@Override%0A
 %09public Mult
@@ -1487,35 +1487,24 @@
 keys();%0A%09%7D%0A%0A
-%09@Override%0A
 %09public bool
@@ -1595,35 +1595,24 @@
 , key);%0A%09%7D%0A%0A
-%09@Override%0A
 %09public bool
@@ -1867,35 +1867,24 @@
 result;%0A%09%7D%0A%0A
-%09@Override%0A
 %09public bool
@@ -2070,35 +2070,24 @@
 result;%0A%09%7D%0A%0A
-%09@Override%0A
 %09public bool
@@ -2197,35 +2197,24 @@
 , key);%0A%09%7D%0A%0A
-%09@Override%0A
 %09public Coll
@@ -2560,35 +2560,24 @@
 emoved;%0A%09%7D%0A%0A
-%09@Override%0A
 %09public Coll
@@ -2836,35 +2836,24 @@
 placed;%0A%09%7D%0A%0A
-%09@Override%0A
 %09public int 
@@ -2897,19 +2897,8 @@
 %09%7D%0A%0A
-%09@Override%0A
 %09pub

Remove Override annotations because Java 1.5 does not allow Override annotations when implementing _interface_ methods.