/* * * * Copyright (c) 2016. David Sowerby * * * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * * the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * * specific language governing permissions and limitations under the License. * */ package uk.q3c.krail.core.i18n; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.inject.Inject; import uk.q3c.krail.core.persist.cache.i18n.DefaultPatternCacheLoader; import uk.q3c.krail.core.persist.cache.i18n.PatternCacheKey; import uk.q3c.krail.core.persist.cache.i18n.PatternCacheLoader; import javax.annotation.Nonnull; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.List; import java.util.Locale; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.cache.CacheBuilder.newBuilder; /** * A cached, single access point for I18N patterns, which may ultimately come from multiple sources. The patterns are actually loaded into the cache by a * {@link PatternCacheLoader} Note that the scope of this class is set in {@link I18NModule#bindPatternSource()} or its sub-class. * * This class does NOT check that Locales requested are supported Locales as defined by {@link I18NModule}. This is the responsibility of {@link CurrentLocale} * <p> * Created by David Sowerby on 07/12/14. */ public class DefaultPatternSource implements PatternSource<LoadingCache<PatternCacheKey, String>> { private LoadingCache<PatternCacheKey, String> cache; @Inject protected DefaultPatternSource(PatternCacheLoader cacheLoader) { //CacheLoader has no interface so the cast is necessary to allow alternative PatternCacheLLoader implementations //although all implementations would need to extend CacheLoader //noinspection unchecked cache = newBuilder() .build((CacheLoader) cacheLoader); // TODO will be using a config object } /** * Retrieves a pattern string from cache, or loads the cache with a value from persistence if needed (see {@link * DefaultPatternCacheLoader}. This method always returns a value. Keys without values will have a value * assigned of the key.name(), with underscores replaced by spaces. * <p> * Note that this method does not check that the {@code locale} is supported ... it is assumed that by this stage * any unsupported locales have been dealt with. This method will, however, return the name of the key if no * entry is found, including when a locale is not supported * * @param key * the I18NKey to identify the pattern * @param locale * the locale for the translation - note that this is not checked to be a supported locale * @param <E> * an Enum implementing I18NKey * * @return a pattern for the key and locale, or the name of the key if no value is found for the key */ @Override public <E extends Enum<E> & I18NKey> String retrievePattern(@Nonnull E key, @Nonnull Locale locale) { checkNotNull(key); checkNotNull(locale); PatternCacheKey cacheKey = new PatternCacheKey(key, locale); return cache.getUnchecked(cacheKey); } @Override public LoadingCache<PatternCacheKey, String> getCache() { return cache; } @Override public void clearCache() { cache.invalidateAll(); cache.cleanUp(); } /** * Clears the cache of all entries for {@code source}. * * @param source the PatternSource annotation associated with a cache entry */ @Override public void clearCache(@Nonnull Class<? extends Annotation> source) { checkNotNull(source); List<PatternCacheKey> keysToRemove = new ArrayList<>(); for (PatternCacheKey key : cache.asMap() .keySet()) { if (key.getSource() .equals(source)) { keysToRemove.add(key); } } cache.invalidateAll(keysToRemove); cache.cleanUp(); } }