package de.invesdwin.util.collections;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import javax.annotation.concurrent.ThreadSafe;
/**
* A thread-safe version of {@link Map} in which all operations that change the Map are implemented by making a new copy
* of the underlying Map.
*
* While the creation of a new Map can be expensive, this class is designed for cases in which the primary function is
* to read data from the Map, not to modify the Map. Therefore the operations that do not cause a change to this class
* happen quickly and concurrently.
*
*/
@ThreadSafe
public abstract class ACopyOnWriteDelegateMap<K, V> implements Map<K, V>, Cloneable {
private volatile Map<K, V> delegate;
/**
* Creates a new instance of ACopyOnWriteDelegateMap.
*
*/
public ACopyOnWriteDelegateMap() {
delegate = newDelegate(Collections.<K, V> emptyMap());
}
protected abstract Map<K, V> newDelegate(final Map<K, V> data);
/**
* Adds the provided key and value to this map.
*
* @see java.util.Map#put(java.lang.Object, java.lang.Object)
*/
@Override
public V put(final K key, final V value) {
synchronized (this) {
final Map<K, V> newMap = newDelegate(delegate);
final V val = newMap.put(key, value);
delegate = newMap;
return val;
}
}
/**
* Removed the value and key from this map based on the provided key.
*
* @see java.util.Map#remove(java.lang.Object)
*/
@Override
public V remove(final Object key) {
synchronized (this) {
final Map<K, V> newMap = newDelegate(delegate);
final V val = newMap.remove(key);
delegate = newMap;
return val;
}
}
/**
* Inserts all the keys and values contained in the provided map to this map.
*
* @see java.util.Map#putAll(java.util.Map)
*/
@Override
public void putAll(final Map<? extends K, ? extends V> newData) {
synchronized (this) {
final Map<K, V> newMap = newDelegate(delegate);
newMap.putAll(newData);
delegate = newMap;
}
}
/**
* Removes all entries in this map.
*
* @see java.util.Map#clear()
*/
@Override
public void clear() {
synchronized (this) {
delegate = newDelegate(Collections.<K, V> emptyMap());
}
}
// ==============================================
// ==== Below are methods that do not modify ====
// ==== the internal Maps ====
// ==============================================
/**
* @return the number of key/value pairs in this map.
*
* @see java.util.Map#size()
*/
@Override
public int size() {
return delegate.size();
}
/**
* @return true if this map is empty, otherwise false.
*
* @see java.util.Map#isEmpty()
*/
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
/**
* @return true if this map contains the provided key, otherwise this method return false.
*
* @see java.util.Map#containsKey(java.lang.Object)
*/
@Override
public boolean containsKey(final Object key) {
return delegate.containsKey(key);
}
/**
* @return true if this map contains the provided value, otherwise this method returns false.
*
* @see java.util.Map#containsValue(java.lang.Object)
*/
@Override
public boolean containsValue(final Object value) {
return delegate.containsValue(value);
}
/**
* @return the value associated with the provided key from this map.
*
* @see java.util.Map#get(java.lang.Object)
*/
@Override
public V get(final Object key) {
return delegate.get(key);
}
/**
* This method will return a read-only {@link Set}.
*/
@Override
public Set<K> keySet() {
return delegate.keySet();
}
/**
* This method will return a read-only {@link Collection}.
*/
@Override
public Collection<V> values() {
return delegate.values();
}
/**
* This method will return a read-only {@link Set}.
*/
@Override
public Set<Entry<K, V>> entrySet() {
return delegate.entrySet();
}
@Override
public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
throw new InternalError();
}
}
}