package rescuecore2.misc.collections;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Collection;
/**
A DelegatingMap is a HashMap that delegates to another map for keys that do not have a value.
@param <K> The key type.
@param <V> The value type.
*/
public abstract class DelegatingMap<K, V> extends HashMap<K, V> {
private Map<K, V> downstream;
/**
Construct a DelegatingMap that delegates to a given map.
@param downstream The delegate map.
*/
public DelegatingMap(Map<K, V> downstream) {
this.downstream = downstream;
}
@Override
public boolean containsKey(Object key) {
return super.containsKey(key) || downstream.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return super.containsValue(value) || downstream.containsValue(value);
}
@Override
public Set<Map.Entry<K, V>> entrySet() {
Set<Map.Entry<K, V>> result = new HashSet<Map.Entry<K, V>>();
result.addAll(super.entrySet());
for (Map.Entry<K, V> next : downstream.entrySet()) {
if (!super.containsKey(next.getKey())) {
result.add(next);
}
}
return result;
}
@Override
public boolean equals(Object o) {
if (o instanceof DelegatingMap) {
return super.equals(o) && this.downstream.equals(((DelegatingMap)o).downstream);
}
return false;
}
@Override
@SuppressWarnings("unchecked")
public V get(Object key) {
V result = super.get(key);
if (result == null) {
return downstream.get(key);
}
return result;
}
@Override
public int hashCode() {
return super.hashCode() ^ downstream.hashCode();
}
@Override
public boolean isEmpty() {
return super.isEmpty() && downstream.isEmpty();
}
@Override
public Set<K> keySet() {
Set<K> result = new HashSet<K>();
result.addAll(super.keySet());
result.addAll(downstream.keySet());
return result;
}
@Override
public int size() {
return keySet().size();
}
@Override
public Collection<V> values() {
Collection<V> result = new HashSet<V>();
result.addAll(super.values());
result.addAll(downstream.values());
return result;
}
}