package org.holoeverywhere.util;
import java.lang.ref.WeakReference;
import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
public class WeaklyMap<K, V> extends AbstractMap<K, V> {
private static final class WeaklyEntry<K, V> implements Entry<K, V> {
private final Entry<K, WeaklyReference<V>> mEntry;
public WeaklyEntry(Entry<K, WeaklyReference<V>> entry) {
mEntry = entry;
}
@Override
public K getKey() {
return mEntry.getKey();
}
@Override
public V getValue() {
final WeaklyReference<V> ref = mEntry.getValue();
return ref == null ? null : ref.get();
}
@Override
public V setValue(V object) {
final WeaklyReference<V> ref = mEntry.setValue(new WeaklyReference<V>(object));
return ref == null ? null : ref.get();
}
}
private static final class WeaklyReference<T> extends WeakReference<T> {
public WeaklyReference(T r) {
super(r);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof WeaklyReference)) {
return false;
}
final Object o1 = ((WeaklyReference<?>) o).get();
final Object o2 = get();
return o1 != null && o2 != null && o1 == o2;
}
}
private final WeakHashMap<K, WeaklyReference<V>> mMap;
public WeaklyMap() {
mMap = new WeakHashMap<K, WeaklyReference<V>>();
}
@Override
public void clear() {
mMap.clear();
}
@Override
public boolean containsKey(Object key) {
return mMap.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return mMap.containsValue(new WeaklyReference<Object>(value));
}
@Override
public Set<Entry<K, V>> entrySet() {
final Set<Entry<K, WeaklyReference<V>>> entrySet = mMap.entrySet();
return new AbstractSet<Entry<K, V>>() {
@Override
public Iterator<Entry<K, V>> iterator() {
final Iterator<Entry<K, WeaklyReference<V>>> iterator = entrySet.iterator();
return new Iterator<Entry<K, V>>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Entry<K, V> next() {
return new WeaklyEntry<K, V>(iterator.next());
}
@Override
public void remove() {
iterator.remove();
}
};
}
@Override
public int size() {
return entrySet.size();
}
};
}
@Override
public V get(Object key) {
WeaklyReference<V> ref = mMap.get(key);
return ref == null ? null : ref.get();
}
@Override
public boolean isEmpty() {
return mMap.isEmpty();
}
@Override
public Set<K> keySet() {
return mMap.keySet();
}
@Override
public V put(K key, V value) {
WeaklyReference<V> ref = mMap.put(key, new WeaklyReference<V>(value));
return ref == null ? null : ref.get();
}
@Override
public void putAll(Map<? extends K, ? extends V> map) {
for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
mMap.put(entry.getKey(), new WeaklyReference<V>(entry.getValue()));
}
}
@Override
public V remove(Object key) {
WeaklyReference<V> ref = mMap.remove(key);
return ref == null ? null : ref.get();
}
@Override
public int size() {
return mMap.size();
}
@Override
public Collection<V> values() {
final Collection<WeaklyReference<V>> values = mMap.values();
return new AbstractCollection<V>() {
@Override
public Iterator<V> iterator() {
final Iterator<WeaklyReference<V>> iterator = values.iterator();
return new Iterator<V>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public V next() {
WeaklyReference<V> ref = iterator.next();
return ref == null ? null : ref.get();
}
@Override
public void remove() {
iterator.remove();
}
};
}
@Override
public int size() {
return values.size();
}
};
}
}