/*
 * $Header: /home/cvspublic/jakarta-slide/src/share/org/apache/slide/util/AbstractObjectCache.java,v 1.10 2004/07/28 09:34:29 ib Exp $
 * $Revision: 1.10 $
 * $Date: 2004/07/28 09:34:29 $
 *
 * ====================================================================
 *
 * 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 abstract implementation.
 * 
 * @version $Revision: 1.10 $ $Date: 2004/07/28 09:34:29 $
 */
public abstract class AbstractObjectCache implements ObjectCache {
    
    
    // -------------------------------------------------------------- Constants
    
    
    /**
     * Default cache size.
     */
    protected static final int DEFAULT_SIZE = 1000;
    
    
    /**
     * Default desired hit ratio.
     */
    protected static final double DEFAULT_HIT_RATIO = 0.8;
    
    
    // ----------------------------------------------------------- Constructors
    
    
    /**
     * Constructor.
     * <p>
     * Warning (blinking) : That constructor is to be used really carefully
     * as the cache maximum size is not limited.
     */
    public AbstractObjectCache() {
        this(DEFAULT_SIZE, Integer.MAX_VALUE, DEFAULT_HIT_RATIO);
    }
    
    
    /**
     * Constructor.
     * 
     * @param initialSize Initial size of the cache
     * @param maxSize Maximum size of the cache
     * @param desiredHitRatio Desired cache hit ratio
     */
    public AbstractObjectCache(int initialSize, int maxSize, 
                               double desiredHitRatio) {
        this.initialSize = initialSize;
        this.maxSize = maxSize;
        this.desiredHitRatio = desiredHitRatio;
    }
    
    
    // ----------------------------------------------------- Instance Variables
    
    
    /**
     * Initial cache size.
     */
    protected int initialSize;
    
    
    /**
     * Desired hit ratio.
     */
    protected double desiredHitRatio;
    
    
    /**
     * Maximum cache size.
     */
    protected int maxSize;
    
    
    // Cache statistics
    
    /**
     * Number of cache requests.
     */
    protected double cacheRequests;
    
    
    /**
     * Number of cache hits.
     */
    protected double cacheHits;
    
    
    /**
     * Current cache hit ratio. Equals to cacheHits / cacheRequests, if, and
     * only if cacheRequests >= cache.size(). Otherwise, it's value is not 
     * used. If the cache hit ratio, is inferior to the desired hit ratio, 
     * the cache grows (unless its maximum size is already reached).
     */
    protected double currentHitRatio;
    
    
    // ---------------------------------------------------- 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 abstract Object get(Object key);
    
    
    /**
     * Add an object to the cache, or overwrite its value.
     * 
     * @param key Object's key
     * @param value Object's value
     */
    public abstract void put(Object key, Object 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 abstract void remove(Object key);
    
    
    /**
     * Clear object cache.
     */
    public abstract void 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 abstract void removeSomeObjects();
    
    
    /**
     * Get cache size.
     * 
     * @return int Current cache size
     */
    protected abstract int getSize();
    
    
    /**
     * Resize cache.
     */
    protected abstract void resize();
    
    
    /**
     * Is the cache size too small ?
     */
    protected void shouldResize() {
        if (cacheRequests > getSize()) {
            currentHitRatio = cacheHits / cacheRequests;
            if (currentHitRatio > desiredHitRatio) {
                resize();
            }
        }
    }
    
    
}
