/*
* Copyright 2003-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.util;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Bidirectional map from pair (K1, K2) <-> V
*/
public class PairMap<K1, K2, V> {
private Map<K1, Map<K2, V>> myMap = new HashMap<K1, Map<K2, V>>();
private Map<V, K1> myValueToK1Map = new HashMap<V, K1>();
private Map<V, K2> myValueToK2Map = new HashMap<V, K2>();
public void put(K1 k1, K2 k2, V v) {
Map<K2, V> map = myMap.get(k1);
if (map == null) {
map = new HashMap<K2, V>();
myMap.put(k1, map);
}
V oldV = map.put(k2, v);
if (oldV != null) {
myValueToK1Map.remove(oldV);
myValueToK2Map.remove(oldV);
}
myValueToK1Map.put(v, k1);
myValueToK2Map.put(v, k2);
}
public V get(K1 k1, K2 k2) {
Map<K2, V> map = myMap.get(k1);
if (map == null) return null;
return map.get(k2);
}
public boolean contains(K1 k1, K2 k2) {
return get(k1, k2) != null;
}
public void remove(K1 k1, K2 k2) {
Map<K2, V> map = myMap.get(k1);
if (map == null) return;
V oldV = map.remove(k2);
if (map.isEmpty()) {
myMap.remove(k1);
}
if (oldV != null) {
myValueToK1Map.remove(oldV);
myValueToK2Map.remove(oldV);
}
}
public void remove(V v) {
K1 k1 = myValueToK1Map.remove(v);
K2 k2 = myValueToK2Map.remove(v);
Map<K2, V> map = myMap.get(k1);
if (map == null) return;
V oldV = map.remove(k2);
if (map.isEmpty()) {
myMap.remove(k1);
}
}
public void clear(K1 k1) {
Map<K2, V> removed = myMap.remove(k1);
if (removed != null) {
for (V removedV : removed.values()) {
myValueToK1Map.remove(removedV);
myValueToK2Map.remove(removedV);
}
}
}
public Set<V> values(){
return myValueToK1Map.keySet();
}
public void clear() {
myMap.clear();
myValueToK1Map.clear();
myValueToK2Map.clear();
}
}