/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.geofence.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
*
* @author ETj (etj at geo-solutions.it)
*/
public class CategorizedCircularBuffer<T, K> {
// protected final static Logger LOGGER = LogManager.getLogger(CategorizedCircularBuffer.class);
private final int maxSize;
LinkedList<Pair<T, K>> mainList;
private Map<K, LinkedList<T>> typedLists = new HashMap<K, LinkedList<T>>();
public CategorizedCircularBuffer(int maxCount) {
if (maxCount < 1)
throw new IllegalArgumentException("Bad size");
this.maxSize = maxCount;
mainList = new LinkedList<Pair<T, K>>();
}
public void add(K key, T value) {
// add to main list
mainList.addFirst(new Pair<T, K>(key, value));
while (mainList.size() > maxSize) {
removeLastEntry();
}
LinkedList<T> typedList = typedLists.get(key);
if (typedList == null) {
typedList = new LinkedList<T>();
typedLists.put(key, typedList);
}
typedList.addFirst(value);
}
private void removeLastEntry() {
Pair<T, K> lastEntry = mainList.pollLast();
LinkedList<T> typedList = typedLists.get(lastEntry.key);
if (typedList == null)
throw new IllegalStateException("Internal error - can't find list for " + lastEntry);
T remove = typedList.removeLast();
if (!lastEntry.value.equals(remove))
throw new IllegalStateException("Internal error - mismatching values "
+ lastEntry.value + " , " + remove);
if (typedList.size() == 0)
typedLists.remove(lastEntry.key);
}
public List<T> subList(int fromIndex, int toIndex) {
List<T> ret = new ArrayList<T>(toIndex - fromIndex);
for (Pair<T, K> pair : mainList.subList(fromIndex, toIndex)) {
ret.add(pair.value);
}
return ret;
}
public int size() {
return mainList.size();
}
public List<T> subListByKey(K key, int fromIndex, int toIndex) {
LinkedList<T> typedList = typedLists.get(key);
if (typedList == null)
return Collections.EMPTY_LIST;
return typedList.subList(fromIndex, toIndex);
}
public int sizeByKey(K key) {
LinkedList<T> typedList = typedLists.get(key);
if (typedList == null)
return 0;
return typedList.size();
}
static class Pair<T, K> {
K key;
T value;
public Pair(K key, T value) {
this.key = key;
this.value = value;
}
@Override
public String toString() {
return "Pair{" + "key=" + key + " value=" + value + '}';
}
}
}