/**
* Copyright 2010 JBoss Inc
*
* 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 bitronix.tm.utils;
import java.util.*;
/**
* Last Recently Used Map with eviction listeners support implementation.
* <p>© <a href="http://www.bitronix.be">Bitronix Software</a></p>
*
* @author lorban
*/
public class LruMap extends HashMap {
private int maxSize;
private Map usageMap = new HashMap();
private List evictionListners = new ArrayList();
public LruMap(int maxSize) {
this.maxSize = maxSize;
}
public Object put(Object key, Object value) {
if (maxSize < 1) {
return null;
}
if (size() >= maxSize)
evictOne();
usageMap.put(key, new Integer(0));
return super.put(key, value);
}
public Object get(Object key) {
incrementUsage(key);
return super.get(key);
}
public Object remove(Object key) {
usageMap.remove(key);
return super.remove(key);
}
public void clear() {
usageMap.clear();
super.clear();
}
private void incrementUsage(Object key) {
Integer value = (Integer) usageMap.get(key);
if (value == null)
return;
Integer newValue = new Integer(value.intValue() + 1);
usageMap.put(key, newValue);
}
private void evictOne() {
int lowestValue = 0;
Object lruKey = null;
Iterator it = usageMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
Object key = entry.getKey();
Integer value = (Integer) entry.getValue();
if (lruKey == null || value.intValue() < lowestValue) {
lowestValue = value.intValue();
lruKey = key;
}
}
if (lruKey != null) {
usageMap.remove(lruKey);
Object value = remove(lruKey);
fireEvictionEvent(value);
}
}
private void fireEvictionEvent(Object value) {
for (int i = 0; i < evictionListners.size(); i++) {
LruEvictionListener listener = (LruEvictionListener) evictionListners.get(i);
listener.onEviction(value);
}
}
public void addEvictionListener(LruEvictionListener listener) {
evictionListners.add(listener);
}
public void removeEvictionListener(LruEvictionListener listener) {
evictionListners.remove(listener);
}
}