001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2006.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.sail.memory.model;
007:
008: import java.lang.ref.WeakReference;
009: import java.util.AbstractSet;
010: import java.util.Collection;
011: import java.util.Iterator;
012: import java.util.Map;
013: import java.util.WeakHashMap;
014:
015: /**
016: * An object registry that uses weak references to keep track of the stored
017: * objects. The registry can be used to retrieve stored objects using another,
018: * equivalent object. As such, it can be used to prevent the use of duplicates
019: * in another data structure, reducing memory usage. The objects that are being
020: * stored should properly implement the {@link Object#equals} and
021: * {@link Object#hashCode} methods.
022: */
023: public class WeakObjectRegistry<E> extends AbstractSet<E> {
024:
025: /*-----------*
026: * Variables *
027: *-----------*/
028:
029: /**
030: * The hash map that is used to store the objects.
031: */
032: private final Map<E, WeakReference<E>> objectMap = new WeakHashMap<E, WeakReference<E>>();
033:
034: /*--------------*
035: * Constructors *
036: *--------------*/
037:
038: /**
039: * Constructs a new, empty object registry.
040: */
041: public WeakObjectRegistry() {
042: super ();
043: }
044:
045: /**
046: * Constructs a new WeakObjectRegistry containing the elements in the
047: * specified collection.
048: *
049: * @param c
050: * The collection whose elements are to be placed into this object
051: * registry.
052: * @throws NullPointerException
053: * If the specified collection is null.
054: */
055: public WeakObjectRegistry(Collection<? extends E> c) {
056: this ();
057: addAll(c);
058: }
059:
060: /*---------*
061: * Methods *
062: *---------*/
063:
064: /**
065: * Retrieves the stored object that is equal to the supplied <tt>key</tt>
066: * object.
067: *
068: * @param key
069: * The object that should be used as the search key for the operation.
070: * @return A stored object that is equal to the supplied key, or
071: * <tt>null</tt> if no such object was found.
072: */
073: public E get(Object key) {
074: WeakReference<E> weakRef = objectMap.get(key);
075:
076: if (weakRef != null) {
077: return weakRef.get();
078: }
079:
080: return null;
081: }
082:
083: @Override
084: public Iterator<E> iterator() {
085: return objectMap.keySet().iterator();
086: }
087:
088: @Override
089: public int size() {
090: return objectMap.size();
091: }
092:
093: @Override
094: public boolean contains(Object o) {
095: return get(o) != null;
096: }
097:
098: @Override
099: public boolean add(E object) {
100: WeakReference<E> ref = new WeakReference<E>(object);
101:
102: ref = objectMap.put(object, ref);
103:
104: if (ref != null && ref.get() != null) {
105: // A duplicate was added which replaced the existing object. Undo this
106: // operation.
107: objectMap.put(ref.get(), ref);
108: return false;
109: }
110:
111: return true;
112: }
113:
114: @Override
115: public boolean remove(Object o) {
116: WeakReference<E> ref = objectMap.remove(o);
117: return ref != null && ref.get() != null;
118: }
119:
120: @Override
121: public void clear() {
122: objectMap.clear();
123: }
124: }
|