/*
 * $Header: /home/cvspublic/jakarta-slide/src/share/org/apache/slide/util/HashMapObjectCache.java,v 1.12 2004/12/31 04:51:05 masonjm Exp $
 * $Revision: 1.12 $
 * $Date: 2004/12/31 04:51:05 $
 *
 * ====================================================================
 *
 * Copyright 1999-2002 The Apache Software Foundation 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */ 

package org.apache.slide.util;

/**
 * Object cache implementation using Keith Visco's HashMap structure.
 * 
 * @version $Revision: 1.12 $ $Date: 2004/12/31 04:51:05 $
 * @deprecated The cache may grow beyond max size or not cache at all.
 * see <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=13142">Bug 13142</a>
 */
public class HashMapObjectCache extends AbstractObjectCache {
    
    
    // ----------------------------------------------------------- Constructors
    
    
    /**
     * Constructor.
     * <p>
     * Warning (blinking) : That constructor is to be used really carefully
     * as the cache maximum size is not limited.
     */
    public HashMapObjectCache() {
        super();
        this.cache = new HashMap(this.initialSize);
    }
    
    
    /**
     * Constructor.
     * 
     * @param initialSize Initial size of the cache
     * @param maxSize Maximum size of the cache
     * @param desiredHitRatio Desired cache hit ratio
     */
    public HashMapObjectCache(int initialSize, int maxSize, 
                              double desiredHitRatio) {
        super(initialSize, maxSize, desiredHitRatio);
        this.cache = new HashMap(this.initialSize / 3);
    }
    
    
    // ----------------------------------------------------- Instance Variables
    
    
    /**
     * Cache structure.
     */
    protected HashMap cache;
    
    
    // ---------------------------------------------------- ObjectCache methods
    
    
    /**
     * Get the object associated with the key.
     * 
     * @param key Object's key
     * @return Object null if there is no object associated with that key in 
     * the cache, or the object value otherwise
     */
    public Object get(Object key) {
        synchronized (cache) {
            Object result = cache.get(key);
            this.cacheRequests += 1;
            
            if (result != null) {
                this.cacheHits += 1;
            } else {
                shouldResize();
            }
            return result;
        }
    }
    
    
    /**
     * Add an object to the cache, or overwrite its value.
     * 
     * @param key Object's key
     * @param value Object's value
     */
    public void put(Object key, Object value) {
        synchronized (cache) {
            cache.put(key, value);
        }
    }
    
    
    /**
     * Remove object associated with the given key. Doesn't do anything if the 
     * key wasn't associated with any object.
     * 
     * @param key Object's key
     */
    public void remove(Object key) {
        synchronized (cache) {
            cache.remove(key);
        }
    }
    
    
    /**
     * Clear object cache.
     */
    public void clear() {
        synchronized (cache) {
            cache.clear();
        }
    }
    
    
    // ------------------------------------------------------ Protected Methods
    
    
    /**
     * Removes some elements from the cache. The selection of the objects to
     * remove, along with the number are left to the implementation.
     */
    protected void removeSomeObjects() {
        clear();
    }
    
    
    /**
     * Get cache size.
     * 
     * @return int Current cache size
     */
    protected int getSize() {
        return cache.size();
    }
    
    
    /**
     * Resize cache.
     */
    protected void resize() {
        synchronized (cache) {
            if (getSize() < maxSize) {
                int size = getSize();
                cache.clear();
                cache = new HashMap(size / 3 * 2);
            }
        }
    }
    
    
}
