package com.novoda.data;
import com.google.auto.value.AutoValue;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@AutoValue
public abstract class ImmutableMapWithCopy<K, V> {
public static <K, V> ImmutableMapWithCopy<K, V> empty() {
return from(ImmutableMap.<K, V>of());
}
public static <K, V> ImmutableMapWithCopy<K, V> from(Map<K, V> map) {
return new AutoValue_ImmutableMapWithCopy<>(ImmutableMap.copyOf(map));
}
ImmutableMapWithCopy() {
// AutoValue best practices https://github.com/google/auto/blob/master/value/userguide/practices.md
}
abstract ImmutableMap<K, V> internalMap();
public int size() {
return internalMap().size();
}
public boolean isEmpty() {
return internalMap().isEmpty();
}
public boolean containsKey(Object key) {
return internalMap().containsKey(key);
}
public boolean containsValue(Object value) {
return internalMap().containsValue(value);
}
public V get(Object key) {
return internalMap().get(key);
}
public ImmutableMapWithCopy<K, V> put(K key, V value) {
Map<K, V> mutableMap = extractMutableMap();
mutableMap.put(key, value);
return from(mutableMap);
}
public ImmutableMapWithCopy<K, V> remove(Object key) {
Map<K, V> mutableMap = extractMutableMap();
mutableMap.remove(key);
return from(mutableMap);
}
public ImmutableMapWithCopy<K, V> putAll(Map<? extends K, ? extends V> m) {
Map<K, V> mutableMap = extractMutableMap();
mutableMap.putAll(m);
return from(mutableMap);
}
public Set<K> keySet() {
return internalMap().keySet();
}
public Collection<V> values() {
return internalMap().values();
}
public Set<Map.Entry<K, V>> entrySet() {
return internalMap().entrySet();
}
public <K2, V2> ImmutableMapWithCopy<K2, V2> transformEntries(Function<Map.Entry<K, V>, Map.Entry<K2, V2>> transformer) {
ImmutableMap.Builder<K2, V2> builder = ImmutableMap.builder();
for (Map.Entry<K, V> entry : internalMap().entrySet()) {
builder.put(transformer.apply(entry));
}
return from(builder.build());
}
private Map<K, V> extractMutableMap() {
Map<K, V> mutableMap = new HashMap<>();
for (Map.Entry<K, V> entry : internalMap().entrySet()) {
mutableMap.put(entry.getKey(), entry.getValue());
}
return mutableMap;
}
public ImmutableMapWithCopy<K, V> filter(Predicate<Map.Entry<K, V>> predicate) {
return from(Maps.filterEntries(internalMap(), predicate));
}
}