package com.github.jknack.antlr4ide.services;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import com.google.common.base.Function;
/**
* Guava cache conflict between Eclipse build and Maven build... until I can figure it out how to
* use Guava without conflict ... I must fallback to something simply :S.
*
* @author edgar
*/
public class Caches<K, V> {
private final int maxSize;
private Procedure1<V> removalListener;
public Caches(final int maxSize) {
this.maxSize = maxSize;
}
public Caches<K, V> removalListener(final Procedure1<V> removalListener) {
this.removalListener = removalListener;
return this;
}
public Map<K, V> build(final Function<K, V> loader) {
return cache(maxSize, loader, removalListener);
}
/**
* Build a simple loading cache with a maxSize and an optional removal listener.
*
* @param maxSize The cache max size.
* @param loader A cache loader. Required.
* @param removalListener A removal listener. Optional.
* @return A simple cache.
*/
@SuppressWarnings("serial")
private static <K, V> Map<K, V> cache(final int maxSize, final Function<K, V> loader,
final Procedure1<V> removalListener) {
return Collections.synchronizedMap(new LinkedHashMap<K, V>() {
@SuppressWarnings("unchecked")
@Override
public V get(final Object key) {
V value = super.get(key);
if (value == null) {
value = loader.apply((K) key);
super.put((K) key, value);
}
return value;
}
@Override
public void clear() {
for (Map.Entry<K, V> entry : this.entrySet()) {
if (removalListener != null) {
removalListener.apply(entry.getValue());
}
}
super.clear();
}
@Override
protected boolean removeEldestEntry(final java.util.Map.Entry<K, V> eldest) {
boolean remove = super.size() > maxSize;
if (remove && removalListener != null) {
removalListener.apply(eldest.getValue());
}
return remove;
}
});
}
}