/*
* HA-JDBC: High-Availability JDBC
* Copyright (C) 2012 Paul Ferraro
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.hajdbc.util.ref;
import java.lang.ref.Reference;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* A map that stores its values using a reference.
* @author Paul Ferraro
*/
public class ReferenceMap<K, V> implements Map<K, V>
{
private final Map<K, Reference<V>> map;
final ReferenceFactory referenceFactory;
public ReferenceMap(Map<K, Reference<V>> map, ReferenceFactory referenceFactory)
{
this.map = map;
this.referenceFactory = referenceFactory;
}
@Override
public void clear()
{
this.map.clear();
}
@Override
public boolean containsKey(Object key)
{
return this.map.containsKey(key);
}
@Override
public boolean containsValue(Object object)
{
for (Reference<V> reference: this.map.values())
{
V value = reference.get();
if ((value != null) && value.equals(object))
{
return true;
}
}
return false;
}
@Override
public Set<Map.Entry<K, V>> entrySet()
{
final Set<Map.Entry<K, Reference<V>>> entrySet = this.map.entrySet();
return new Set<Map.Entry<K, V>>()
{
@Override
public boolean add(Map.Entry<K, V> entry)
{
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection<? extends Map.Entry<K, V>> entries)
{
throw new UnsupportedOperationException();
}
@Override
public void clear()
{
entrySet.clear();
}
@Override
public boolean contains(Object object)
{
return false;
}
@Override
public boolean containsAll(Collection<?> collection)
{
return false;
}
@Override
public boolean isEmpty()
{
return entrySet.isEmpty();
}
@Override
public Iterator<Map.Entry<K, V>> iterator()
{
final Iterator<Map.Entry<K, Reference<V>>> entries = entrySet.iterator();
return new Iterator<Map.Entry<K, V>>()
{
@Override
public boolean hasNext()
{
return entries.hasNext();
}
@Override
public java.util.Map.Entry<K, V> next()
{
final Map.Entry<K, Reference<V>> entry = entries.next();
return new Map.Entry<K, V>()
{
@Override
public K getKey()
{
return entry.getKey();
}
@Override
public V getValue()
{
return entry.getValue().get();
}
@Override
public V setValue(V value)
{
Reference<V> reference = entry.setValue(ReferenceMap.this.referenceFactory.createReference(value));
return (reference != null) ? reference.get() : null;
}
};
}
@Override
public void remove()
{
entries.remove();
}
};
}
@Override
public boolean remove(Object object)
{
return false;
}
@Override
public boolean removeAll(Collection<?> collection)
{
return false;
}
@Override
public boolean retainAll(Collection<?> collection)
{
return false;
}
@Override
public int size()
{
return entrySet.size();
}
@Override
public Object[] toArray()
{
return null;
}
@Override
public <T> T[] toArray(T[] arg0)
{
return null;
}
};
}
@Override
public V get(Object key)
{
Reference<V> reference = this.map.get(key);
return (reference != null) ? reference.get() : null;
}
@Override
public boolean isEmpty()
{
return this.map.isEmpty();
}
@Override
public Set<K> keySet()
{
return this.map.keySet();
}
@Override
public V put(K key, V value)
{
Reference<V> reference = this.map.put(key, this.referenceFactory.createReference(value));
return (reference != null) ? reference.get() : null;
}
@Override
public void putAll(Map<? extends K, ? extends V> map)
{
for (Map.Entry<? extends K, ? extends V> entry: map.entrySet())
{
this.put(entry.getKey(), entry.getValue());
}
}
@Override
public V remove(Object key)
{
Reference<V> reference = this.map.remove(key);
return (reference != null) ? reference.get() : null;
}
@Override
public int size()
{
return this.map.size();
}
@Override
public Collection<V> values()
{
final Collection<Reference<V>> references = this.map.values();
return new Collection<V>()
{
@Override
public boolean add(V arg0)
{
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection<? extends V> arg0)
{
throw new UnsupportedOperationException();
}
@Override
public void clear()
{
references.clear();
}
@Override
public boolean contains(Object object)
{
for (Reference<V> reference: references)
{
V value = reference.get();
if ((value != null) && value.equals(object))
{
return true;
}
}
return false;
}
@Override
public boolean containsAll(Collection<?> objects)
{
return false;
}
@Override
public boolean isEmpty()
{
return references.isEmpty();
}
@Override
public Iterator<V> iterator()
{
final Iterator<Reference<V>> refs = references.iterator();
return new Iterator<V>()
{
@Override
public boolean hasNext()
{
return refs.hasNext();
}
@Override
public V next()
{
Reference<V> reference = refs.next();
return (reference != null) ? reference.get() : null;
}
@Override
public void remove()
{
refs.remove();
}
};
}
@Override
public boolean remove(Object value)
{
return false;
}
@Override
public boolean removeAll(Collection<?> values)
{
return false;
}
@Override
public boolean retainAll(Collection<?> values)
{
return false;
}
@Override
public int size()
{
return references.size();
}
@Override
public Object[] toArray()
{
return null;
}
@Override
public <T> T[] toArray(T[] arg0)
{
return null;
}
};
}
}