package bjc.esodata; import java.util.*; import bjc.data.Pair; /** * Represents a map keyed by pairs, where you can look up all the items that * have a particular left or right key value. * * NOTE: Using the keySet/values/entrySet views to modify the map will break the * tracking invariants. * * @author bjcul * * @param * @param * @param */ public class PairMap implements Map, Value> { private Map, Value> backing; private Multimap> leftTracker; private Multimap> rightTracker; /** * Create a new pair map. */ public PairMap() { this.backing = new HashMap<>(); this.leftTracker = new Multimap<>(); this.rightTracker = new Multimap<>(); } /** * Get all of the key-pairs which contain the given left value. * * @param val The value to search for. * * @return All of the key-pairs containing the given value. */ public Set> getLeft(Left val) { return leftTracker.get(val); } /** * Get all of the key-pairs which contain the given right value. * * @param val The value to search for. * * @return All of the key-pairs containing the given value. */ public Set> getRight(Right val) { return rightTracker.get(val); } /** * Get a value without having to construct a pair callee-side * * @param lft The left value * @param rght The right value. * * @return The value corresponding to the given key-pair, if one exists */ public Value biget(Left lft, Right rght) { return backing.get(Pair.pair(lft, rght)); } @Override public int size() { return backing.size(); } @Override public boolean isEmpty() { return backing.isEmpty(); } @Override public boolean containsKey(Object key) { return backing.containsKey(key); } @Override public boolean containsValue(Object value) { return backing.containsKey(value); } @Override public Value get(Object key) { return backing.get(key); } @Override public Value put(Pair key, Value value) { Value ret = backing.put(key, value); leftTracker.add(key.getLeft(), key); rightTracker.add(key.getRight(), key); return ret; } @Override public Value remove(Object key) { @SuppressWarnings("unchecked") Pair actKey = (Pair) key; leftTracker.remove(actKey.getLeft(), actKey); rightTracker.remove(actKey.getRight(), actKey); return backing.remove(key); } @Override public void putAll(Map, ? extends Value> m) { for (Entry, ? extends Value> entry : m.entrySet()) { put(entry.getKey(), entry.getValue()); } } @Override public void clear() { backing.clear(); leftTracker = new Multimap<>(); rightTracker = new Multimap<>(); } // TODO: Update these to not break the tracking invariants @Override public Set> keySet() { return backing.keySet(); } @Override public Collection values() { return backing.values(); } @Override public Set, Value>> entrySet() { return backing.entrySet(); } }