/* * The contents of this file are subject to the Mozilla Public License Version 1.1 * (the "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at . * * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.util.cache; import java.lang.ref.*; import java.util.*; /** * An entry from the CacheMap class. This object holds the key, a SoftReference * to the value, the timestamp of its last access, and the number of times this element has been accessed. * The latter two values are frequently used by an object implementing the CacheMapStrategy * interface to compute a "figure of merit" for the entry that decides whether or not it gets discarded. * * @author Eric J. Bowersox <erbo@users.sf.net> * @version X * @see CacheMap * @see CacheMapStrategy * @see java.lang.ref.SoftReference */ public final class CacheMapEntry implements Map.Entry { /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- */ private Object key; // the key for this entry private SoftReference value; // reference to (discardable) value private int hits = 0; // number of hits on this entry private long timestamp; // timestamp of this entry /*-------------------------------------------------------------------------------- * Constructors *-------------------------------------------------------------------------------- */ /** * Creates a new CacheMapEntry. * * @param key The key for this entry. * @param value The value to be held in this entry. */ CacheMapEntry(Object key, Object value) { this.key = key; this.value = new SoftReference(value); this.timestamp = System.currentTimeMillis(); } // end constructor /** * Creates a new CacheMapEntry. * * @param key The key for this entry. * @param value The value to be held in this entry. * @param q The ReferenceQueue to add the new reference generated by this constructor to. */ CacheMapEntry(Object key, Object value, ReferenceQueue q) { this.key = key; this.value = new SoftReference(value,q); this.timestamp = System.currentTimeMillis(); } // end constructor /*-------------------------------------------------------------------------------- * finalize() function *-------------------------------------------------------------------------------- */ /** * Called by the garbage collector on an object when garbage collection determines that there are no * more references to the object. */ protected void finalize() { key = null; value.clear(); value = null; } // end finalize /*-------------------------------------------------------------------------------- * Implementations from interface Map.Entry *-------------------------------------------------------------------------------- */ /** * Returns the key corresponding to this entry. * * @return The key corresponding to this entry. */ public final Object getKey() { return key; } // end getKey /** * Returns the value corresponding to this entry. If the value has already been reclaimed by the * garbage collector, the return value is null. * * @return The value corresponding to this entry. */ public final Object getValue() { return value.get(); } // end getValue /** * Replaces the value corresponding to this entry with the specified value. * * @param o The new value to be stored in this entry. * @return The former value stored in this entry. If the value has already been reclaimed by the * garbage collector, the return value is null. */ public final Object setValue(Object o) { Object rc = value.get(); value.clear(); value = new SoftReference(o); return rc; } // end setValue /** * Compares the specified object with this object for equality. The CacheMap considers * two entries to be equivalent if they have the same key. (The value is not considered because it * might already have been garbage-collected.) * * @param o The other object to compare to. * @return true if the specified object is equal to this entry. */ public final boolean equals(Object o) { // make sure the other element is a Map.Entry if ((o==null) || !(o instanceof Map.Entry)) return false; Map.Entry other = (Map.Entry)o; // compare the keys only (the values may change) if (key==null) return (other.getKey()==null); else return ((other.getKey()!=null) && key.equals(other.getKey())); } // end equals /** * Returns the hash code value for this map entry, defined to be the hash code value of the key. * * @return The hash code value for this map entry. */ public final int hashCode() { return ((key==null) ? 0 : key.hashCode()); } // end hashCode /*-------------------------------------------------------------------------------- * External operations *-------------------------------------------------------------------------------- */ /** * Replaces the value corresponding to this entry with the specified value. * * @param o The new value to be stored in this entry. * @param q The ReferenceQueue to add the freshly-generated reference to. * @return The former value stored in this entry. If the value has already been reclaimed by the * garbage collector, the return value is null. */ final Object setValue(Object o, ReferenceQueue q) { Object rc = value.get(); value.clear(); value = new SoftReference(o,q); return rc; } // end setValue /** * Returns true if the value in this map entry has been cleared by the garbage collector. * * @return true if the value has been cleared, false if not. */ public final boolean isCleared() { return (value.get()==null); } // end isCleared /** * Returns true if the specified reference is the one contained in this map entry. * * @param r The reference we're trying to match. * @return true/CODE> if this reference is the same as the one contained in the map entry, * false if not. */ final boolean matchReference(Reference r) { if (r instanceof SoftReference) return (value==(SoftReference)r); else return false; } // end matchReference /** * Clears out all references held by this map entry. */ final void discard() { key = null; value.clear(); value = null; } // end discard /** * Returns the number of times this map entry has been referenced. * * @return The number of times this map entry has been referenced. */ public final int getHits() { return hits; } // end getHits /** * Returns the timestamp of the most recent reference to this map entry. * * @return The timestamp of the most recent reference to this map entry. */ public final long getTimestamp() { return timestamp; } // end getTimestamp /** * Returns the number of milliseconds since this map entry was last referenced. * * @param tick The current time tick of the system in milliseconds. * @return The number of milliseconds since this map entry was last referenced. */ public final long getAge(long tick) { return (tick - timestamp); } // end getAge /** * References this entry, which increments its "hit" counter and updates its current time stamp. */ final void touch() { hits++; timestamp = System.currentTimeMillis(); } // end touch } // end class CacheMapEntry