package humanize.spi.cache; import humanize.config.ConfigLoader; import java.util.Locale; import java.util.Properties; import java.util.ResourceBundle; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilderSpec; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; /** * {@link CacheProvider} implementation that uses Guava caches as in memory * storage. * * @author mfornos * */ public class GuavaCacheProvider implements CacheProvider { private static final CacheBuilderSpec spec = initSpec(); private static CacheBuilderSpec initSpec() { final Properties properties = ConfigLoader.loadProperties(); return CacheBuilderSpec.parse(properties.getProperty(ConfigLoader.CACHE_BUILDER_SPEC)); } private final Cache<Locale, ResourceBundle> bundles; private final LoadingCache<String, Cache<Locale, Object>> formats; private final LoadingCache<String, Cache<Locale, String[]>> stringCaches; public GuavaCacheProvider() { bundles = CacheBuilder.from(spec).<Locale, ResourceBundle> build(); formats = CacheBuilder.from(spec).build(new CacheLoader<String, Cache<Locale, Object>>() { @Override public Cache<Locale, Object> load(String cache) throws Exception { return CacheBuilder.from(spec).<Locale, Object> build(); } }); stringCaches = CacheBuilder.from(spec).build(new CacheLoader<String, Cache<Locale, String[]>>() { @Override public Cache<Locale, String[]> load(String cache) throws Exception { return CacheBuilder.from(spec).<Locale, String[]> build(); } }); } @Override public boolean containsBundle(Locale locale) { return bundles.getIfPresent(locale) != null; } @Override public boolean containsFormat(String cache, Locale locale) { return getFormatsCache(cache).getIfPresent(locale) != null; } @Override public boolean containsStrings(String cache, Locale locale) { return getStringCache(cache).getIfPresent(locale) != null; } @Override public ResourceBundle getBundle(Locale locale, Callable<ResourceBundle> getCall) { try { return bundles.get(locale, getCall); } catch (ExecutionException e) { throw new RuntimeException(e); } } @SuppressWarnings("unchecked") @Override public <T> T getFormat(String cache, Locale locale, Callable<T> getCall) { try { return (T) getFormatsCache(cache).get(locale, getCall); } catch (ExecutionException e) { throw new RuntimeException(e); } } @Override public String[] getStrings(String cache, Locale locale, Callable<String[]> getCall) { try { return getStringCache(cache).get(locale, getCall); } catch (ExecutionException e) { throw new RuntimeException(e); } } @Override public ResourceBundle putBundle(Locale locale, ResourceBundle bundle) { bundles.put(locale, bundle); return bundle; } @Override public <T> T putFormat(String cache, Locale locale, T format) { Cache<Locale, T> numberFormatCache = getFormatsCache(cache); numberFormatCache.put(locale, format); return format; } @Override public String[] putStrings(String cache, Locale locale, String[] value) { Cache<Locale, String[]> stringCache = getStringCache(cache); stringCache.put(locale, value); return value; } @SuppressWarnings("unchecked") private <T> Cache<Locale, T> getFormatsCache(String cache) { try { return (Cache<Locale, T>) formats.get(cache); } catch (ExecutionException e) { throw new RuntimeException(e); } } private Cache<Locale, String[]> getStringCache(String cache) { try { return stringCaches.get(cache); } catch (ExecutionException e) { throw new RuntimeException(e); } } }