00001 package gov.nasa.arc.ase.util;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 import java.util.*;
00012
00013
00014 public class Cache {
00015 public interface Listener {
00016 public void elementRemoved(Object o);
00017 }
00018
00019 private class EntryComparator implements Comparator {
00020 public int compare(Object o1, Object o2) {
00021
00022
00023
00024
00025 Map.Entry e1 = (Map.Entry)o1;
00026 Map.Entry e2 = (Map.Entry)o2;
00027
00028 Index c1 = (Index)e1.getValue();
00029 Index c2 = (Index)e2.getValue();
00030
00031 return c1.cnt - c2.cnt;
00032 }
00033 }
00034
00035 private class Index {
00036 int cnt;
00037
00038 public Index() {
00039 cnt = 0;
00040 }
00041
00042 public Index(int value) {
00043 cnt = value;
00044 }
00045
00046 public Object clone() {
00047 return new Index(cnt);
00048 }
00049
00050 public boolean equals(Object o) {
00051 return ((Index)o).cnt == cnt;
00052 }
00053
00054 public String toString() {
00055 return new Integer(cnt).toString();
00056 }
00057 }
00058
00059 private Hashtable ht = new Hashtable();
00060 private Index lowest = new Index(0);
00061 private Index highest = new Index(0);
00062 private int count = 0;
00063 private int size;
00064 private Listener listener;
00065
00066 public Cache(int s) {
00067 size = s;
00068 listener = null;
00069 }
00070 public Cache(int s, Listener l) {
00071 size = s;
00072 listener = l;
00073 }
00074 private Object getKey(Index c) {
00075 for(Enumeration e = ht.keys(); e.hasMoreElements(); ) {
00076 Object k = e.nextElement();
00077 Object v = ht.get(k);
00078 if(v.equals(c)) return k;
00079 }
00080 return null;
00081 }
00082 private Index getValue(Index c) {
00083 for(Enumeration e = ht.keys(); e.hasMoreElements(); ) {
00084 Object k = e.nextElement();
00085 Object v = ht.get(k);
00086 if(v.equals(c)) return (Index)v;
00087 }
00088 return null;
00089 }
00090 private int lowestValue() {
00091 int min = 0;
00092 boolean found = false;
00093
00094 for(Enumeration e = ht.elements(); e.hasMoreElements(); ) {
00095 Index v = (Index)e.nextElement();
00096
00097 if(!found || v.cnt < min) {
00098 found = true;
00099 min = v.cnt;
00100 }
00101 }
00102
00103 return min;
00104 }
00105 private void next() {
00106 highest.cnt++;
00107 if(highest.cnt < 0) {
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 ArrayList entries = new ArrayList(ht.entrySet());
00126 Collections.sort(entries, new EntryComparator());
00127
00128 int idx = 0;
00129
00130 ht = new Hashtable();
00131 for(Iterator i = entries.iterator(); i.hasNext(); idx++) {
00132
00133
00134
00135 Map.Entry e = (Map.Entry)i.next();
00136
00137 ht.put(e.getKey(), new Index(idx));
00138 }
00139
00140 lowest.cnt = 0;
00141 highest.cnt = entries.size();
00142 }
00143 }
00144 public boolean put(Object o) {
00145 if(ht.containsKey(o)) {
00146 Index c = (Index)ht.get(o);
00147
00148 if(c.cnt != highest.cnt-1) {
00149 int old = c.cnt;
00150
00151 c.cnt = highest.cnt;
00152 if(old == lowest.cnt)
00153 lowest.cnt = lowestValue();
00154 next();
00155 }
00156
00157 return false;
00158 }
00159
00160 if(count == size)
00161 removeLowest();
00162 else
00163 count++;
00164
00165 ht.put(o, new Index(highest.cnt));
00166 next();
00167
00168 return true;
00169 }
00170 private void removeLowest() {
00171 Object key = getKey(lowest);
00172
00173 ht.remove(key);
00174 lowest.cnt = lowestValue();
00175 if(count == 1) highest.cnt = 0;
00176
00177 if(listener != null) listener.elementRemoved(key);
00178 }
00179 public void setSize(int s) {
00180 if(s > count) {
00181 size = s;
00182 } else {
00183 while(count > s) {
00184 removeLowest();
00185 count--;
00186 }
00187 size = s;
00188 }
00189 }
00190 public String toString() {
00191 return ht.toString();
00192 }
00193 }