116 lines
3.0 KiB
Java
116 lines
3.0 KiB
Java
package tc.oc.commons.core.util;
|
|
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import com.google.common.base.Function;
|
|
import com.google.common.base.Predicate;
|
|
import com.google.common.collect.Collections2;
|
|
import com.google.common.collect.ForwardingMap;
|
|
import com.google.common.collect.Iterators;
|
|
import com.google.common.collect.Sets;
|
|
|
|
/**
|
|
* Map adapter that inherits entries from a parent map. This map's entries
|
|
* have priority over the parent's. Modifications affect this map only.
|
|
* Modification through views or iterators is not supported.
|
|
*/
|
|
public class InheritingMap<K, V> extends ForwardingMap<K, V> {
|
|
|
|
private final Map<K, V> map, parent;
|
|
|
|
public InheritingMap(Map<K, V> parent) {
|
|
this(new HashMap<K, V>(), parent);
|
|
}
|
|
|
|
public InheritingMap(Map<K, V> map, Map<K, V> parent) {
|
|
this.map = map;
|
|
this.parent = parent;
|
|
}
|
|
|
|
@SafeVarargs
|
|
public static <K, V> Map<K, V> chain(Map<K, V>... maps) {
|
|
return chain(Iterators.forArray(maps));
|
|
}
|
|
|
|
public static <K, V> Map<K, V> chain(Iterable<Map<K, V>> maps) {
|
|
return chain(maps.iterator());
|
|
}
|
|
|
|
public static <K, V> Map<K, V> chain(Iterator<Map<K, V>> maps) {
|
|
if(!maps.hasNext()) return Collections.emptyMap();
|
|
final Map<K, V> head = maps.next();
|
|
if(!maps.hasNext()) return head;
|
|
return new InheritingMap<>(head, chain(maps));
|
|
}
|
|
|
|
@Override
|
|
protected Map<K, V> delegate() {
|
|
return map;
|
|
}
|
|
|
|
@Override
|
|
public int size() {
|
|
return Sets.union(map.keySet(), parent.keySet()).size();
|
|
}
|
|
|
|
@Override
|
|
public boolean isEmpty() {
|
|
return map.isEmpty() && parent.isEmpty();
|
|
}
|
|
|
|
@Override
|
|
public boolean containsKey(Object key) {
|
|
return map.containsKey(key) || parent.containsKey(key);
|
|
}
|
|
|
|
@Override
|
|
public boolean containsValue(Object value) {
|
|
return map.containsValue(value) || parent.containsValue(value);
|
|
}
|
|
|
|
@Override
|
|
public V get(Object key) {
|
|
if(map.containsKey(key)) {
|
|
return map.get(key);
|
|
} else {
|
|
return parent.get(key);
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public Set<K> keySet() {
|
|
return Sets.union(map.keySet(), parent.keySet());
|
|
}
|
|
|
|
@Override
|
|
public Collection<V> values() {
|
|
return Collections2.transform(keySet(), new Function<K, V>() {
|
|
@Override public V apply(K key) {
|
|
return get(key);
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public Set<Entry<K, V>> entrySet() {
|
|
// Union of child's entrySet and paren't entrySet with child's keys filtered out
|
|
return Sets.union(
|
|
map.entrySet(),
|
|
Sets.filter(
|
|
parent.entrySet(),
|
|
new Predicate<Entry<K, V>>() {
|
|
@Override public boolean apply(Entry<K, V> entry) {
|
|
return !map.containsKey(entry.getKey());
|
|
}
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|