FileDocCategorySizeDatePackage
Cache.javaAPI DocExample6662Sun Jun 23 17:40:22 BST 2002org.dasein.util

Cache.java

package org.dasein.util;

// Java imports
import java.io.Serializable;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

/**
 * <p class="text">
 * Provides a cache of objects that will expire its contents as those
 * contents fail to be used. This cache uses
 * <span class="code">java.lang.ref.SoftReference</span> to guarantee
 * that cached items will be removed when they have not been
 * referenced for a long time. 
 * </p>
 * <p class="text">
 * This class is not synchronized and therefore should be synchronized
 * by the application for multi-threaded use.
 * </p>
 * @modified $Date$
 * @version $Revision$
 * @author George Reese/george.reese@jwt.com
 */
public class Cache implements Collection, Serializable {
    /**
     * A hash map indexing references by unique keys.
     */
    private HashMap cache = new HashMap();

    /*
     * Constructs a new empty cache.
     */
    public Cache() {
        super();
    }

    /**
     * Unsupported.
     * @param ob ignored
     * @return never returns
     * @throws java.lang.UnsupportedOperationException always
     */
    public boolean add(Object ob) {
        throw new UnsupportedOperationException();
    }
    
    /**
     * Unsupported.
     * @param coll ignored
     * @return never returns
     * @throws java.lang.UnsupportedOperationException always
     */
    public boolean addAll(Collection coll) {
        throw new UnsupportedOperationException();
    }
    
    /**
     * Caches the specified object identified by the specified key.
     * @param key a unique key for this object
     * @param val the object to be cached
     */
    public void cache(Object key, Object val) {
        cache.put(key, new SoftReference(val));
    }

    /**
     * Clears the entire cache.
     */
    public void clear() {
        cache.clear();
    }
    
    /**
     * Checks the specified object against the cache and verifies that it
     * is in the cache. This method will return
     * <span class="keyword">false</span> if the object was once in the cache
     * but has expired due to inactivity.
     * @param ob the object to check for in the cache
     * @return true if the object is in the cache
     */
    public boolean contains(Object ob) {
        Iterator it = cache.values().iterator();

        while( it.hasNext() ) {
            SoftReference ref = (SoftReference)it.next();
            Object item = ref.get();

            if( item != null && ob.equals(item) ) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * Checks the passed in collection and determines if all elements
     * of that collection are contained within this cache. Care should
     * be taken in reading too much into a failure. If one of the elements
     * was once in this cache but has expired due to inactivity, this
     * method will return false.
     * @param coll the collection to test
     * @return true if all elements of the tested collection are in the cache
     */
    public boolean containsAll(Collection coll) {
        Iterator it = coll.iterator();

        while( it.hasNext() ) {
            if( !contains(it.next()) ) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * Checks if an object with the specified key is in the cache.
     * @param key the object's identifier
     * @return true if the object is in the cache
     */
    public boolean containsKey(Object key) {
        if( !cache.containsKey(key) ) {
            return false;
        }
        else {
            SoftReference ref = (SoftReference)cache.get(key);

            if( ref.get() == null ) {
                release(key);
                return false;
            }
            return true;
        }
    }

    /**
     * Provides the cached object identified by the specified key. This
     * method will return <span class="code">null</span> if the
     * specified object is not in the cache.
     * @param key the unique identifier of the desired object
     * @return the cached object or null
     */
    public Object get(Object key) {
        SoftReference ref = (SoftReference)cache.get(key);
        Object ob;

        if( ref == null ) {
            return null;
        }
        ob = ref.get();
        if( ob == null ) {
            release(key);
        }
        return ob;
    }

    /**
     * @return true if the cache is empty
     */
    public boolean isEmpty() {
        return cache.isEmpty();
    }

    /**
     * Provides all of the valid objects in the cache.
     * This method will not be the snappiest method in the world.
     * @return all valid objects in the cache
     */
    public Iterator iterator() {
        return toList().iterator();
    }
    
    /**
     * Releases the specified object from the cache.
     * @param key the unique identified for the item to release
     */
    public void release(Object key) {
        cache.remove(key);
    }

    /**
     * Unsupported.
     * @param ob ignored
     * @return never returns
     * @throws java.lang.UnsupportedOperationException always
     */
    public boolean remove(Object ob) {
        throw new UnsupportedOperationException();
    }

    /**
     * Unsupported.
     * @param coll ignored
     * @return never returns
     * @throws java.lang.UnsupportedOperationException always
     */
    public boolean removeAll(Collection coll) {
        throw new UnsupportedOperationException();
    }

    /**
     * Unsupported.
     * @param coll ignored
     * @return never returns
     * @throws java.lang.UnsupportedOperationException always
     */
    public boolean retainAll(Collection coll) {
        throw new UnsupportedOperationException();
    }

    /**
     * @return the number of elements in the cache
     */
    public int size() {
        return toList().size();
    }

    /**
     * @return the cache as an array
     */
    public Object[] toArray() {
        return toList().toArray();
    }

    /**
     * @return the cache as an array
     */
    public Object[] toArray(Object[] arr) {
        return toList().toArray(arr);
    }

    /**
     * @return the cache as an array
     */
    private ArrayList toList() {
        Iterator it = cache.values().iterator();
        ArrayList tmp = new ArrayList();

        while( it.hasNext() ) {
            SoftReference ref = (SoftReference)it.next();
            Object ob = ref.get();
            
            if( ob != null ) {
                tmp.add(ob);
            }
        }
        return tmp;
    }
}