package rescuecore2.misc.collections;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.Collection;
/**
A LazyMap is a Map that generates default values for keys that do not yet have a value. This class delegates to a real Map implementation for all methods with the exception of {@link #get(Object)}. If the downstream get returns a value then that value is returned to the caller. If the downstream get returns null then the {@link #createValue()} method will be called and the result of that is added to the downstream map and returned.
@param <K> The key type.
@param <V> The value type.
*/
public abstract class LazyMap<K, V> implements Map<K, V> {
private Map<K, V> downstream;
/**
Construct a LazyMap that delegates to a new HashMap.
*/
public LazyMap() {
this(new HashMap<K, V>());
}
/**
Construct a LazyMap that delegates to a given map.
@param downstream The delegate map.
*/
public LazyMap(Map<K, V> downstream) {
this.downstream = downstream;
}
/**
Construct a new value object for a key that does not yet have a value.
@return A new value object.
*/
public abstract V createValue();
@Override
public void clear() {
downstream.clear();
}
@Override
public boolean containsKey(Object key) {
return downstream.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return downstream.containsValue(value);
}
@Override
public Set<Map.Entry<K, V>> entrySet() {
return downstream.entrySet();
}
@Override
public boolean equals(Object o) {
return (o instanceof LazyMap) && (((LazyMap)o).downstream.equals(this.downstream));
}
@Override
@SuppressWarnings("unchecked")
public V get(Object key) {
V result = downstream.get(key);
if (result == null) {
try {
result = createValue();
downstream.put((K)key, result);
}
catch (ClassCastException e) {
result = null;
}
}
return result;
}
@Override
public int hashCode() {
return downstream.hashCode();
}
@Override
public boolean isEmpty() {
return downstream.isEmpty();
}
@Override
public Set<K> keySet() {
return downstream.keySet();
}
@Override
public V put(K key, V value) {
return downstream.put(key, value);
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
downstream.putAll(m);
}
@Override
public V remove(Object key) {
return downstream.remove(key);
}
@Override
public int size() {
return downstream.size();
}
@Override
public Collection<V> values() {
return downstream.values();
}
}