/* * 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: lobochief@users.sourceforge.net */ /* * Created on Oct 8, 2005 */ package com.nvarghese.beowulf.common.cobra.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 final Map map = new HashMap(); private final ReferenceQueue queue = new ReferenceQueue(); public WeakValueHashMap() { super(); } public int size() { return this.map.size(); } public boolean isEmpty() { return this.map.isEmpty(); } public boolean containsKey(final Object key) { WeakReference wf = (WeakReference) this.map.get(key); return wf != null && wf.get() != null; } public boolean containsValue(final Object value) { throw new UnsupportedOperationException(); } public Object get(Object key) { this.checkQueue(); WeakReference wf = (WeakReference) this.map.get(key); return wf == null ? null : wf.get(); } public Object put(final Object key, final Object value) { this.checkQueue(); return this.putImpl(key, value); } private final Object putImpl(final Object key, final Object value) { if (value == null) { throw new IllegalArgumentException("null values not accepted"); } Reference ref = new LocalWeakReference(key, value, this.queue); WeakReference oldWf = (WeakReference) this.map.put(key, ref); return oldWf == null ? null : oldWf.get(); } public Object remove(final Object key) { this.checkQueue(); WeakReference wf = (WeakReference) this.map.remove(key); return wf == null ? null : wf.get(); } public void putAll(Map t) { this.checkQueue(); Iterator i = t.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); this.putImpl(entry.getKey(), entry.getValue()); } } public void clear() { this.checkQueue(); this.map.clear(); } public Set keySet() { return this.map.keySet(); } private final void checkQueue() { ReferenceQueue queue = this.queue; LocalWeakReference ref; while ((ref = (LocalWeakReference) queue.poll()) != null) { this.map.remove(ref.getKey()); } } public Collection values() { return new FilteredCollection(this.map.values(), new LocalFilter()); } public Set entrySet() { throw new UnsupportedOperationException(); } private class LocalFilter implements ObjectFilter { /* * (non-Javadoc) * * @see org.xamjwg.util.ObjectFilter#decode(java.lang.Object) */ 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) */ 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; } public Object getKey() { return key; } 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 int hashCode() { Object target = this.get(); return target == null ? 0 : target.hashCode(); } } }