/*
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.appserv.util.cache;

import com.sun.enterprise.util.CULoggerInfo;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;

/**
 * BaseCache
 * Generic in-memory, abstract cache
 */
public class BaseCache implements Cache {

    /**
     * The resource bundle containing the localized message strings.
     */
    static final int MAX_ENTRIES = 1 << 30;
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    // maximum number of entries this cache may ever hold
    protected int maxEntries;

    // the number of cache entries in this cache
    protected int   entryCount;
    private Object  entryCountLk = new Object();

    /** threshold for the cache; once the threshold is reached
     *  entries are removed to accomodate newer inserts
     */
    protected int threshold = 0;

    // the number of cache hits
    protected int     hitCount;
    private Object  hitCountLk = new Object();

    // the number of cache misses
    protected int     missCount;
    private Object  missCountLk = new Object();

    // the number of cache item removals
    protected int    removalCount;
    private Object removalCountLk = new Object();

    // the number of cache item refreshes
    private int     refreshCount;
    private Object  refreshCountLk = new Object();

    // the number of times an item was added to cache
    private int     addCount;
    private Object  addCountLk = new Object();

    // the number of times the cache overflowed
    private int     overflowCount;
    private Object  overflowCountLk = new Object();

    // table size
        protected int maxBuckets;

    // cache entries hash table
        protected CacheItem[] buckets;
    // bucket-wide locks
        protected Object[]    bucketLocks;

    // boolean status and locks for item thread-safe refreshes
        protected boolean[]   refreshFlags;

    protected ArrayList listeners = new ArrayList();

    /**
     * default constructor for the basic cache
     */
    public BaseCache() { }

    /**
     * initialize the cache
     * @param maxEntries maximum number of entries expected in the cache
     * @param props opaque list of properties for a given cache implementation
     * @throws a generic Exception if the initialization failed
     */
    public void init(int maxEntries, Properties props) throws Exception {
        init(maxEntries, DEFAULT_LOAD_FACTOR, props);
    }

    /**
     * initialize the cache
     * @param maxEntries maximum number of entries expected in the cache
     * @param loadFactor the load factor
     * @param props opaque list of properties for a given cache implementation
     * @throws a generic Exception if the initialization failed
     */
    public void init(int maxEntries, float loadFactor, Properties props) {

        if (maxEntries <= 0) {
            String msg = CULoggerInfo.getString(CULoggerInfo.illegalMaxEntries);

            Integer obj = Integer.valueOf(maxEntries);
            Object[] params = { obj };
            msg = MessageFormat.format(msg, params);

            throw new IllegalArgumentException(msg);
        }

        if (maxEntries > MAX_ENTRIES)
             maxEntries = MAX_ENTRIES;

        this.maxEntries = maxEntries;

        // find a power of 2 >= maxEntries
        maxBuckets = 1;
        while (maxBuckets < maxEntries)
            maxBuckets <<= 1;

        //Cannot have the loadfactor as a negative value
        if( loadFactor < 0 )
            loadFactor = 0;

        /** initialize the threshold; a zero value for maxEntries
         *  implies no caching.
         */
        if (maxEntries != 0) {
            threshold = (int)(maxEntries * loadFactor) + 1;
        }

        // create the cache and the bucket locks
        entryCount = 0;
               buckets = new CacheItem[maxBuckets];
               bucketLocks = new Object[maxBuckets];
        refreshFlags = new boolean[maxBuckets];

        for (int i=0; i<maxBuckets; i++) {
                       buckets[i] = null;
                        bucketLocks[i] = new Object();
            refreshFlags[i] = false;
        }
    }

    /**
     * add the cache module listener
     * @param listener <code>CacheListener</code> implementation
     */
    public void addCacheListener(CacheListener listener) {
        listeners.add(listener);
    }

    /**
     * Returns a hash code for non-null Object x.
     * @See also <code>HashMap</code>
     */
    protected int hash(Object x) {
        int h = x.hashCode();
        return h - (h << 7);  // i.e., -127 * h
    }

    /**
     * Check for equality of non-null reference x and possibly-null y.
     */
    protected boolean eq(Object x, Object y) {
        return x == y || x.equals(y);
    }

    /**
     * increase the threshold
     */
    protected void handleOverflow() {
        // just double the threshold; this may degenerate the cache.
        threshold = (threshold * 2);
        incrementOverflowCount();
    }

    /**
     * this item is just added to the cache
     * @param item <code>CacheItem</code> that was created
     * @return a overflow item; may be null
     * Cache bucket is already synchronized by the caller
     *
     * Here, if cache is overflowing (i.e. reached threshold); this class
     * simply makes the cache unbounded by raising the threshold. Subclasses
     * are expected to provide a robust cache replacement algorithm.
     *
     * Subclasses should enhance this implemntation.
     */
    protected CacheItem itemAdded(CacheItem item) {
        if (isThresholdReached()) {
            handleOverflow();
        }
        return null;
    }

    /**
     * this item is accessed
     * @param item <code>CacheItem</code> accessed
     *
     * Cache bucket is already synchronized by the caller
     */
    protected void itemAccessed(CacheItem item) { }

    /**
     * item value has been refreshed
     * @param item <code>CacheItem</code> that was refreshed
     * @param oldSize size of the previous value that was refreshed
     * Cache bucket is already synchronized by the caller
     */
    protected void itemRefreshed(CacheItem item, int oldSize) { }

    /**
     * item value has been removed from the cache
     * @param item <code>CacheItem</code> that was just removed
     *
     * Cache bucket is already synchronized by the caller
     */
    protected void itemRemoved(CacheItem item) { }

    /**
     * Cannot find an item with the given key and hashCode
     * @param key <code>Object</code> that is not found
     * @param hashCode <code>int</code> its hashCode
     *
     * @returns the Object value associated with the item
     * Cache bucket is already synchronized by the caller
     */
    protected Object loadValue(Object key, int hashCode) {
        return null;
    }

    /**
     * create new item
     * @param hashCode for the entry
     * @param key <code>Object</code> key
     * @param value <code>Object</code> value
     * @param size size in bytes of the item
     * subclasses may override to provide their own CacheItem extensions
     * e.g. one that permits persistence.
     */
    protected CacheItem createItem(int hashCode, Object key,
                                        Object value, int size) {
        return new CacheItem(hashCode, key, value, size);
    }

    /**
     * has cache reached its threshold
     * @return true when the cache reached its threshold
     */
    protected boolean isThresholdReached() {
        return (entryCount > threshold);
    }

    /**
     * get the index of the item in the cache
     * @param hashCode of the entry
     * @return the index to be used in the cache
     */
    protected final int getIndex(int hashCode) {
        return (hashCode & (maxBuckets - 1));
    }

    /**
     * get the index of the item given a key
     * @param key of the entry
     * @return the index to be used in the cache
     */
    public final int getIndex(Object key) {
        return getIndex(hash(key));
    }

    /**
     * get the item stored at the key.
     * @param key lookup key
     * @returns the item stored at the key; null if not found.
     */
    public Object get(Object key) {
        int hashCode = hash(key);

        return get(hashCode, key);
    }

    /**
     * get the item stored at the given pre-computed hash code and the key.
     * @param key lookup key
     * @returns the item stored at the key; null if not found.
     */
    public Object get(int hashCode, Object key) {

                int index = getIndex(hashCode);
        Object value;
        CacheItem item = null;

                synchronized (bucketLocks[index]) {
                    item = buckets[index];

                        for (; item != null; item = item.next) {
                                if ( (hashCode == item.hashCode) && eq(key, item.key) ) {
                                        break;
                                }
                        }

            // update the stats in line
            if (item != null) {
                value = item.getValue();
                itemAccessed(item);
            }
            else
                value = loadValue(key, hashCode);
                }

        if (item != null)
            incrementHitCount();
        else
            incrementMissCount();

        return value;
    }

    /**
     * check if the cache contains the item at the key
     * @param key lookup key
     * @returns true if there is an item stored at the key; false if not.
     */
    public boolean contains(Object key) {
            return (get(key) != null);
    }

    /**
     * get all the items stored at the key.
     * @param key lookup key
     * @returns an Iterator over the items with the given key.
     */
    public Iterator getAll(Object key) {
        int hashCode = hash(key);
                int index = getIndex(hashCode);

        ArrayList valueList = new ArrayList(entryCount);
                synchronized (bucketLocks[index]) {
                    CacheItem item = buckets[index];

                        for (; item != null; item = item.next) {
                                if ( (hashCode == item.hashCode) && eq(key, item.key) ) {
                    incrementHitCount();
                    valueList.add(item.getValue());
                                }
                        }

                }

        return valueList.iterator();
    }

    /**
     * get an Iterator for the keys stored in the cache
     * @returns an Iterator
     */
    public Iterator keys() {
        ArrayList keyList = new ArrayList(entryCount);

        for (int index=0; index < maxBuckets; index++) {
            synchronized (bucketLocks[index]) {
                for (CacheItem item = buckets[index]; item != null;
                                item = item.next) {
                    keyList.add(item.key);
                }
            }
        }

        return keyList.iterator();
    }

    /**
     * get an Enumeration for the keys stored in the cache
     * @returns an Enumeration
     * XXX: should use Iterator which is based on Collections
     */
    public Enumeration elements() {
        Vector keyList = new Vector();

        for (int index=0; index < maxBuckets; index++) {
            synchronized (bucketLocks[index]) {
                for (CacheItem item = buckets[index]; item != null;
                                item = item.next) {
                    keyList.addElement(item.key);
                }
            }
        }

        return keyList.elements();
    }

    /**
     * get an Iterator for the values stored in the cache
     * @returns an Iterator
     */
    public Iterator values() {
        ArrayList valueList = new ArrayList(entryCount);

        for (int index=0; index < maxBuckets; index++) {
            synchronized (bucketLocks[index]) {
                for (CacheItem item = buckets[index]; item != null;
                                item = item.next) {
                    valueList.add(item.value);
                }
            }
        }

        return valueList.iterator();
    }

    /**
    /**
     * cache the given value at the specified key and return previous value
     * @param key lookup key
     * @param object item value to be stored
     * @returns the previous item stored at the key; null if not found.
     */
    public Object put(Object key, Object value) {
        int hashCode = hash(key);

        return _put(hashCode, key, value, -1, false);
    }

    /**
     * cache the given value at the specified key and return previous value
     * @param key lookup key
     * @param object item value to be stored
     * @param size in bytes of the value being cached
     * @returns the previous item stored at the key; null if not found.
     */
    public Object put(Object key, Object value, int size) {
        int hashCode = hash(key);

        return _put(hashCode, key, value, size, false);
    }

    /**
     * add the given value to the cache at the specified key
     * @param key lookup key
     * @param object item value to be stored
     */
    public void add(Object key, Object value) {
        int hashCode = hash(key);

        _put(hashCode, key, value, -1, true);
    }

    /**
     * add the given value with specified size to the cache at specified key
     * @param key lookup key
     * @param object item value to be stored
     * @param size in bytes of the value being added
     *
     * This function is suitable for multi-valued keys.
     */
    public void add(Object key, Object value, int size) {
        int hashCode = hash(key);

        _put(hashCode, key, value, size, true);
    }

    /**
     * cache the given value at the specified key and return previous value
     * @param hashCode previously computed hashCode for the key
     * @param key lookup key
     * @param object item value to be stored
     * @param size in bytes of the value being cached
     * @param addValue treate this operation to add (default is to replace)
     * @returns the previous item stored at the key; null if not found.
     *
     * Note: This can be used just to refresh the cached item as well, altho
     * it may call trimCache() if the cache reached its threshold -- which is
     * is probably not very intuitive.
     */
    protected Object _put(int hashCode, Object key,
                            Object value, int size, boolean addValue) {
                int index = getIndex(hashCode);

                CacheItem item, newItem = null, oldItem = null, overflow = null;
        Object oldValue;
        int oldSize = 0;

        // lookup the item
                synchronized (bucketLocks[index]) {
                        for (item = buckets[index]; item != null; item = item.next) {
                                if ((hashCode == item.hashCode) && eq(key, item.key)) {

                    oldItem = item;
                                        break;
                                }
                        }

            // if there was no item in the cache, insert the given item
                        if (addValue || oldItem == null) {
                newItem = createItem(hashCode, key, value, size);

                // add the item at the head of the bucket list
                            newItem.next = buckets[index];
                            buckets[index] = newItem;

                oldValue = null;
                overflow = itemAdded(newItem);
                        }
            else {
                oldSize = oldItem.getSize();
                oldValue = oldItem.refreshValue(value, size);
                itemRefreshed(oldItem, oldSize);
            }
                }

        if (newItem != null) {
            incrementEntryCount();
            incrementAddCount();

            // make sure we are are not crossing the threshold
            if (overflow != null)
                trimItem(overflow);
        }
        else
            incrementRefreshCount();

        return oldValue;
    }

    /**
     * remove the item stored at the key.
     * @param key lookup key
     * @returns the item stored at the key; null if not found.
     */
    public Object remove(Object key) {
        int hashCode = hash(key);

        Object retVal  = null;
        CacheItem removed = _remove( hashCode, key, null);

        if (removed != null)
            retVal = removed.getValue();
        return retVal;
    }

    /**
     * remove the item stored at the key.
     * @param hashCode a precomputed hashCode
     * @param key lookup key
     * @returns the item stored at the key; null if not found.
     */
    public Object remove(int hashCode, Object key) {
        Object retVal  = null;
        CacheItem removed = _remove( hashCode, key, null);

        if (removed != null)
            retVal = removed.getValue();
        return retVal;
    }

    /**
     * remove the given value stored at the key; value-specific removals.
     * @param key lookup key
     * @param value to match (for a multi-valued keys)
     * @returns the item stored at the key; null if not found.
     */
    public Object remove(Object key, Object value) {
        int hashCode = hash(key);

        Object retVal  = null;
        CacheItem removed = _remove( hashCode, key, value);

        if (removed != null)
            retVal = removed.getValue();
        return retVal;
    }

    /**
     * remove the item stored at the key.
     * @param hashCode a precomputed hashCode
     * @param key lookup key
     * @param value of the item to be matched
     * @returns the item stored at the key; null if not found.
     */
    protected CacheItem _remove(int hashCode, Object key, Object value) {
                int index = getIndex(hashCode);

                CacheItem prev = null, item = null;

                synchronized (bucketLocks[index]) {
                        for (item = buckets[index]; item != null; item = item.next) {
                            if (hashCode == item.hashCode && key.equals(item.key)) {

                                    if (value == null || value == item.value) {

                        if (prev == null) {
                            buckets[index] = item.next;
                        } else  {
                            prev.next = item.next;
                        }
                        item.next = null;

                        itemRemoved(item);
                        break;
                    }
                            }
                            prev = item;
                        }
        }

        if (item != null) {
            decrementEntryCount();
            incrementRemovalCount();

            incrementHitCount();
        } else
            incrementMissCount();

        return item;
    }

    /**
     * remove the item stored at the key.
     * @param item CacheItem to be removed
     * @return the item stored at the key; null if not found.
     */
    protected CacheItem _removeItem(CacheItem ritem) {

                int index = getIndex(ritem.hashCode);

                CacheItem prev = null, item = null;

                synchronized (bucketLocks[index]) {
                        for (item = buckets[index]; item != null; item = item.next) {
                            if (item == ritem) {
                    if (prev == null) {
                        buckets[index] = item.next;
                    } else  {
                        prev.next = item.next;
                    }
                    item.next = null;
                    break;
                            }
                            prev = item;
                        }
        }

        if (item != null) {
            decrementEntryCount();
        }

        return item;
    }

    /**
     * remove all the item with the given key.
     * @param key lookup key
     */
    public void removeAll(Object key) {
        int hashCode = hash(key);
                int index = getIndex(hashCode);

                CacheItem prev = null, item = null;
        ArrayList items = new ArrayList(entryCount);

                synchronized (bucketLocks[index]) {
                        for (item = buckets[index]; item != null;
                                    item = item.next) {
                            if (hashCode == item.hashCode && key.equals(item.key)) {
                        if (prev == null) {
                            buckets[index] = item.next;
                        } else  {
                            prev.next = item.next;
                        }
                        item.next = null;

                        decrementEntryCount();
                        incrementRemovalCount();

                        items.add(item);
                            }
                            prev = item;
                        }
        }

        // notify subclasses
        for (int i = 0; i < items.size(); i++) {
            itemRemoved((CacheItem)items.get(i));
        }
    }

    /**
     * trim the item from the cache and notify listeners
     * @param item to be trimmed
     */
    protected void trimItem(CacheItem item) {
        CacheItem removed = _removeItem(item);

        if (removed != null) {
            for (int i = 0; i < listeners.size(); i++) {
                CacheListener listener = (CacheListener) listeners.get(i);
                listener.trimEvent(removed.key, removed.value);
            }
        }
    }

    /**
     * wait for a refresh on the object associated with the key
     * @param key lookup key
     * @returns true on successful notification, or false if there is
     *  no thread refreshing this entry.
     */
    public boolean waitRefresh(int index) {
                synchronized (bucketLocks[index]) {
            if (refreshFlags[index] == false) {
                refreshFlags[index] = true;
                return false;
            }

            // wait till refresh is finished
            try {
                while(refreshFlags[index])
                        bucketLocks[index].wait();
            } catch (InterruptedException ie) {}
        }
        return true;
    }

    /**
     * notify threads waiting for a refresh on the object associated with the key
     * @param key lookup key
     */
    public void notifyRefresh(int index) {
        // notify other threads waiting for refresh
                synchronized (bucketLocks[index]) {
            refreshFlags[index] = false;
            bucketLocks[index].notifyAll();
        }
    }

    /**
     * clear all the entries from the cache.
     * @returns the number of entries cleared from the cache
     */
    public int clear() {

                CacheItem item=null;
        int count = 0;

        for (int index = 0; index < maxBuckets; index++) {
                    synchronized (bucketLocks[index]) {
                            for (item = buckets[index]; item != null;
                                            item = item.next) {
                    item.next = null;

                    count++;
                    decrementEntryCount();
                    itemRemoved(item);

                    if (entryCount == 0)
                        break;
                            }
                buckets[index] = null;
            }
        }


        return count;
    }

    /**
     * trim the expired entries from the cache.
     * @param maxCount maximum number of invalid entries to trim
     *        specify Integer.MAX_VALUE to trim all timedout entries
     *
     * This call is to be scheduled by a thread managed by the container.
     */
    public void trimExpiredEntries(int maxCount) {}

    /**
     * get the number of entries in the cache
     * @return the number of entries the cache currently holds
     */
    public int getEntryCount() {
        return entryCount;
    }

    /*** methods for monitoring the cache          ***/

    /**
     * is this cache empty?
     * @returns true if the cache is empty; false otherwise.
     */
    public boolean isEmpty() {
        return (entryCount == 0);
    }

    /**
     * synchronized counter updates
     */
    protected final void incrementEntryCount() {
        synchronized(entryCountLk) {
            entryCount++;
        }
    }

    protected final void decrementEntryCount() {
        synchronized(entryCountLk) {
            entryCount--;
        }
    }

    protected final void incrementHitCount() {
        synchronized (hitCountLk) {
            hitCount++;
        }
    }

    protected final void incrementMissCount() {
        synchronized (missCountLk) {
            missCount++;
        }
    }

    protected final void incrementRemovalCount() {
        synchronized (removalCountLk) {
            removalCount++;
        }
    }

    protected final void incrementRefreshCount() {
        synchronized (refreshCountLk) {
            refreshCount++;
        }
    }

    protected final void incrementAddCount() {
        synchronized (addCountLk) {
            addCount++;
        }
    }

    protected final void incrementOverflowCount() {
        synchronized (overflowCountLk) {
            overflowCount++;
        }
    }

    /**
     * get generic stats from subclasses
     */

    /**
     * get the desired statistic counter
     * @param key to corresponding stat
     * @return an Object corresponding to the stat
     * See also: Constant.java for the key
     */
    public Object getStatByName(String key) {
        Object stat = null;

        if (key == null)
            return null;

        if (key.equals(Constants.STAT_BASECACHE_MAX_ENTRIES))
            stat = Integer.valueOf(maxEntries);
        else if (key.equals(Constants.STAT_BASECACHE_THRESHOLD))
            stat = Integer.valueOf(threshold);
        else if (key.equals(Constants.STAT_BASECACHE_TABLE_SIZE))
            stat = Integer.valueOf(maxBuckets);
        else if (key.equals(Constants.STAT_BASECACHE_ENTRY_COUNT))
            stat = Integer.valueOf(entryCount);
        else if (key.equals(Constants.STAT_BASECACHE_HIT_COUNT))
            stat = Integer.valueOf(hitCount);
        else if (key.equals(Constants.STAT_BASECACHE_MISS_COUNT))
            stat = Integer.valueOf(missCount);
        else if (key.equals(Constants.STAT_BASECACHE_REMOVAL_COUNT))
            stat = Integer.valueOf(removalCount);
        else if (key.equals(Constants.STAT_BASECACHE_REFRESH_COUNT))
            stat = Integer.valueOf(refreshCount);
        else if (key.equals(Constants.STAT_BASECACHE_OVERFLOW_COUNT))
            stat = Integer.valueOf(overflowCount);
        else if (key.equals(Constants.STAT_BASECACHE_ADD_COUNT))
            stat = Integer.valueOf(addCount);

        return stat;
    }

    /**
     * get the stats snapshot
     * @return a Map of stats
     * See also: Constant.java for the keys
     */
    public Map getStats() {
        HashMap stats = new HashMap();

        stats.put(Constants.STAT_BASECACHE_MAX_ENTRIES,
                  Integer.valueOf(maxEntries));
        stats.put(Constants.STAT_BASECACHE_THRESHOLD,
                  Integer.valueOf(threshold));
        stats.put(Constants.STAT_BASECACHE_TABLE_SIZE,
                  Integer.valueOf(maxBuckets));
        stats.put(Constants.STAT_BASECACHE_ENTRY_COUNT,
                  Integer.valueOf(entryCount));
        stats.put(Constants.STAT_BASECACHE_HIT_COUNT,
                  Integer.valueOf(hitCount));
        stats.put(Constants.STAT_BASECACHE_MISS_COUNT,
                  Integer.valueOf(missCount));
        stats.put(Constants.STAT_BASECACHE_REMOVAL_COUNT,
                  Integer.valueOf(removalCount));
        stats.put(Constants.STAT_BASECACHE_REFRESH_COUNT,
                  Integer.valueOf(refreshCount));
        stats.put(Constants.STAT_BASECACHE_OVERFLOW_COUNT,
                  Integer.valueOf(overflowCount));
        stats.put(Constants.STAT_BASECACHE_ADD_COUNT,
                  Integer.valueOf(addCount));

        return stats;
    }

    /**
     * Sets all references to null. This method should be called
     * at the end of this object's life cycle.
     */
    public void destroy() {
        if ((listeners != null) && (buckets != null) && (bucketLocks != null)) {
            clear();
            listeners.clear();
        }

        entryCountLk     = null;
        hitCountLk       = null;
        missCountLk      = null;
        removalCountLk   = null;
        refreshCountLk   = null;
        addCountLk       = null;
        overflowCountLk  = null;
        buckets          = null;
        bucketLocks      = null;
        refreshFlags     = null;
        listeners        = null;
    }

    /**
     * clear the stats
     */
    public void clearStats() {
        hitCount = 0;
        missCount = 0;
        removalCount = 0;
        refreshCount = 0;
        overflowCount = 0;
        addCount = 0;
    }

    /** default CacheItem class implementation  ***/
    public static class CacheItem {
        int hashCode;
        Object key;
        Object value;
        int size;

        CacheItem next;

        protected CacheItem(int hashCode, Object key, Object value, int size) {
            this.hashCode = hashCode;
            this.key = key;
            this.value = value;
            this.size = size;
        }

        /**
         * get the item's hashCode
         */
        public int getHashCode() {
            return hashCode;
        }

        /**
         * get the item's key
         */
        public Object getKey() {
            return key;
        }

        /**
         * get the item's next reference
         */
        public CacheItem getNext() {
            return next;
        }

        /**
         * set the item's next reference
         */
        public void setNext(CacheItem next) {
            this.next = next;
        }

        /**
         * get the item's value
         */
        public Object getValue() {
            return value;
        }

        /**
         * @return size of the entry in bytes
         * a value of -1 indicates unknown size
         */
        public int getSize() {
            return size;
        }

        /**
         * refresh the item's value
         * @param value value to be updated
         * @param newSize of the field
         */
        protected Object refreshValue(Object value, int newSize) {
            Object oldValue = this.value;
            this.value = value;
            this.size = newSize;

            return oldValue;
        }

        public String toString() {
            return "key: " + key + "; value: " + value.toString();
        }
    }
}
