TransactionMap.java
package eu.javaexperience.collection.map;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import eu.javaexperience.interfaces.simple.SimpleGet;
import eu.javaexperience.interfaces.simple.SimpleGetFactory;
public class TransactionMap<K, V> extends AbstractMap<K, V>
{
protected Map<K, V> modifiable;
protected Map<K, V> diff;
protected Map<K, Boolean> contains;
protected Map<K, V> access;
protected Map<K, V> origin;
public TransactionMap(Map<K, V> origin)
{
this(origin, (SimpleGet) SimpleGetFactory.getSmallMapFactory());
}
public TransactionMap(Map<K, V> origin, SimpleGet<Map> mapCreator)
{
this.origin = origin;
this.diff = mapCreator.get();
this.access = mapCreator.get();
this.contains = mapCreator.get();
this.modifiable = new ChainedMap<>(diff, access, origin);
}
public Map<K, V> getOriginalMap()
{
return origin;
}
public Map<K, V> getAccessMap()
{
return access;
}
public Map<K, V> getDiffMap()
{
return diff;
}
public Map<K, V> getModifiableMap()
{
return modifiable;
}
public static final Object NULL_VALUE = new Object();
protected V touchValue(K key)
{
{
Object in = access.get(key);
if(null != in)
{
in = modifiable.get(key);
if(NULL_VALUE == in)
{
return null;
}
else
{
return (V) in;
}
}
}
V re = origin.get(key);
if(null == re)
{
access.put(key, (V)NULL_VALUE);
return null;
}
else
{
access.put(key, re);
return (V) re;
}
}
protected Set<Entry<K, V>> touchValues(Set<Entry<K, V>> kvs)
{
Set<Entry<K, V>> ret = new HashSet<>();
for(Entry<K, V> kv:kvs)
{
K key = kv.getKey();
Object in = kv.getValue();
if(null != in)
{
in = modifiable.get(key);
if(NULL_VALUE == in)
{
access.remove(key);
//ret.add(new KeyVal(key, null));
continue;
}
else
{
access.put(key, (V)in);
ret.add(new KeyVal(key, in));
continue;
}
}
}
return ret;
}
@Override
public boolean containsKey(Object key)
{
return null != touchValue((K) key);
}
@Override
public V get(Object key)
{
return touchValue((K) key);
}
@Override
public V put(K key, V value)
{
V o = touchValue(key);
modifiable.put(key, value);
return o;
}
@Override
public V remove(Object key)
{
V o = touchValue((K) key);
modifiable.put((K) key, (V) NULL_VALUE);
return o;
}
@Override
public void clear()
{
for(K k:keySet())
{
remove(k);
}
}
@Override
public Set<K> keySet()
{
Set<K> ret = modifiable.keySet();
for(K k:ret)
{
touchValue(k);
}
return ret;
}
public V getAccessTimeValue(K key)
{
V in = access.get(key);
if(NULL_VALUE == in)
{
return null;
}
return in;
}
@Override
public int size()
{
int ret = 0;
for(V v:values())
{
if(null != v)
{
++ret;
}
}
return ret;
}
@Override
public Set<Entry<K, V>> entrySet()
{
Set<Entry<K, V>> ents = modifiable.entrySet();
return touchValues(ents);
}
}