package net.krautchan.backend; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; import net.krautchan.data.KODataListener; import net.krautchan.data.KrautObject; public class KCCache<T extends KrautObject> implements KODataListener<T> { private CachePersister<T> persister; private ConcurrentLinkedQueue<T> krautObjects = new ConcurrentLinkedQueue<T>(); private int capacity = 200; public KCCache() { super(); } public KCCache(int capacity) { this.capacity = capacity; } public void setPersister(CachePersister<T> persister) { this.persister = persister; } public void add (T obj) { obj.cachedTime = new Date().getTime(); if (krautObjects.contains(obj)) { krautObjects.remove(obj); } krautObjects.add(obj); if (krautObjects.size() > capacity) { trimCache (krautObjects.size() - capacity); } } public void add (Collection<T> objs) { for (T obj : objs) { add (obj); } } public T get (Long id) { Iterator<T> iter = krautObjects.iterator(); while (iter.hasNext()) { T obj = iter.next(); if (obj.dbId.equals(id)) { return obj; } } return null; } public List<T>getAll () { List<T> retVal = new ArrayList<T>(); retVal.addAll(krautObjects); return retVal; } private void trimCache (int numEntriesToRemove) { List<T> sorter = new ArrayList<T>(); Iterator<T> iter = krautObjects.iterator(); int count = 0; while (iter.hasNext()) { T obj = iter.next(); sorter.add(obj); count++; } Collections.sort(sorter, new Comparator <T>() { @Override public int compare(T arg0, T arg1) { return (int) (arg0.cachedTime - arg1.cachedTime); } }); List<T> removed = new ArrayList<T>(); for (int i = sorter.size()-1; i > numEntriesToRemove; i--) { krautObjects.remove(sorter.get(i)); removed.add(sorter.get(i)); } if (null != persister) { persister.persist(removed); } } public void freeze() { if (null != persister) { persister.persist(krautObjects); } } public void thaw() { if (null != persister) { krautObjects.clear(); krautObjects.addAll(persister.retrieveAll()); } } public int size() { return krautObjects.size(); } public void clear() { krautObjects.clear(); } @Override public void notifyAdded(T item, Object token) { add(item); } @Override public void notifyDone(Object token) { // TODO Auto-generated method stub } @Override public void notifyError(Exception ex, Object token) { // TODO Auto-generated method stub } public interface CachePersister<T extends KrautObject> { public void persist(T obj); public void persist(Collection<T> objects); public T retrieve(Long dbId); public Collection<T> retrieveAll(); } }