/*
* GNU LESSER GENERAL PUBLIC LICENSE Copyright (C) 2006 The Lobo Project
*
* This library 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 2.1 of
* the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Contact info: xamjadmin@users.sourceforge.net
*/
/*
* Created on Oct 8, 2005
*/
package org.cobra_grendel.util;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class WeakValueHashMap implements Map
{
private class LocalFilter implements ObjectFilter
{
/*
* (non-Javadoc)
*
* @see org.xamjwg.util.ObjectFilter#decode(java.lang.Object)
*/
@Override
public Object decode(final Object source)
{
WeakReference wf = (WeakReference) source;
return wf == null ? null : wf.get();
}
/*
* (non-Javadoc)
*
* @see org.xamjwg.util.ObjectFilter#encode(java.lang.Object)
*/
@Override
public Object encode(final Object source)
{
throw new java.lang.UnsupportedOperationException("Read-only collection.");
}
}
private static class LocalWeakReference extends WeakReference
{
private final Object key;
public LocalWeakReference(final Object key, final Object target, final ReferenceQueue queue)
{
super(target, queue);
this.key = key;
}
@Override
public boolean equals(final Object other)
{
Object target1 = this.get();
Object target2 = other instanceof LocalWeakReference ? ((LocalWeakReference) other).get() : null;
return Objects.equals(target1, target2);
}
public Object getKey()
{
return key;
}
@Override
public int hashCode()
{
Object target = this.get();
return target == null ? 0 : target.hashCode();
}
}
private final Map map = new HashMap();
private final ReferenceQueue queue = new ReferenceQueue();
public WeakValueHashMap()
{
super();
}
private final void checkQueue()
{
ReferenceQueue queue = this.queue;
LocalWeakReference ref;
while ((ref = (LocalWeakReference) queue.poll()) != null)
{
map.remove(ref.getKey());
}
}
@Override
public void clear()
{
checkQueue();
map.clear();
}
@Override
public boolean containsKey(final Object key)
{
WeakReference wf = (WeakReference) map.get(key);
return wf != null && wf.get() != null;
}
@Override
public boolean containsValue(final Object value)
{
throw new UnsupportedOperationException();
}
@Override
public Set entrySet()
{
throw new UnsupportedOperationException();
}
@Override
public Object get(final Object key)
{
checkQueue();
WeakReference wf = (WeakReference) map.get(key);
return wf == null ? null : wf.get();
}
@Override
public boolean isEmpty()
{
return map.isEmpty();
}
@Override
public Set keySet()
{
return map.keySet();
}
@Override
public Object put(final Object key, final Object value)
{
if (value == null)
{
throw new IllegalArgumentException("null values not accepted");
}
checkQueue();
Reference ref = new LocalWeakReference(key, value, queue);
WeakReference oldWf = (WeakReference) map.put(key, ref);
return oldWf == null ? null : oldWf.get();
}
@Override
public void putAll(final Map t)
{
checkQueue();
Iterator i = t.entrySet().iterator();
while (i.hasNext())
{
Map.Entry entry = (Map.Entry) i.next();
put(entry.getKey(), entry.getValue());
}
}
@Override
public Object remove(final Object key)
{
checkQueue();
WeakReference wf = (WeakReference) map.remove(key);
return wf == null ? null : wf.get();
}
@Override
public int size()
{
return map.size();
}
@Override
public Collection values()
{
return new FilteredCollection(map.values(), new LocalFilter());
}
}