package de.is24.guava;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.cache.AbstractLoadingCache;
import com.google.common.collect.Maps;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
/**
* The <code>SequentialLoadingCache</code> is a <code>LoadingCache</code> that is intended for single-threaded access.
* It is based on a {@link java.util.HashMap} and caches <code>null</code> values.
*
* @param <K> the keys' type
* @param <V> the values' type
* @since 2.0.0
*/
public class SequentialLoadingCache<K, V> extends AbstractLoadingCache<K, Optional<V>> {
@Nonnull
private final Map<K, Optional<V>> cache;
@Nonnull
private final Function<K, Optional<V>> cacheLoader;
/**
* Creates a <code>SequentialLoadingCache</code> that uses the given function to load the values.
*
* @since 2.0.0
*/
protected SequentialLoadingCache(@Nonnull Map<K, Optional<V>> cache, @Nonnull Function<K, Optional<V>> cacheLoader) {
this.cache = cache;
this.cacheLoader = cacheLoader;
}
/**
* Creates a <code>SequentialLoadingCache</code> that uses the given function to load the values.
*
* @since 2.0.0
*/
public SequentialLoadingCache(@Nonnull Function<K, Optional<V>> cacheLoader) {
this(Maps.<K, Optional<V>>newHashMap(), cacheLoader);
}
/**
* Creates a <code>SequentialLoadingCache</code> that only caches one value.
*
* @see #SequentialLoadingCache(com.google.common.base.Function)
* @since 2.0.0
*/
public static <K, V> SequentialLoadingCache<K, V> createSingleValueCache(@Nonnull Function<K, Optional<V>> cacheLoader) {
return new SequentialLoadingCache<K, V>(new HashMap<K, Optional<V>>() {
@Override
public Optional<V> put(K key, Optional<V> value) {
super.clear();
return super.put(key, value);
}
}, cacheLoader);
}
@Nonnull
@Override
public Optional<V> get(@Nullable K key) throws ExecutionException {
Optional<V> value = this.cache.get(key);
if (value == null) {
value = cacheLoader.apply(key);
if (value == null) {
value = Optional.absent();
}
this.cache.put(key, value);
}
return value;
}
@Nonnull
@Override
@SuppressWarnings("SuspiciousMethodCalls")
public Optional<V> getIfPresent(@Nonnull Object key) {
final Optional<V> value = this.cache.get(key);
return value == null ? Optional.<V>absent() : value;
}
}