package ws.antonov.config.consumer;
import com.google.protobuf.Message;
import ws.antonov.config.api.consumer.ConfigClient;
import ws.antonov.config.api.consumer.ConfigParamsBuilder;
import ws.antonov.config.api.provider.ConfigProvider;
import java.util.*;
/**
* Copyright 2011 Alex Antonov
* 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.
*
* @author aantonov
* @since 0.1
*/
public class CachingConfigClientWrapper implements ConfigClient {
private ConfigClient clientDelegate;
private Map<CacheKey, Message> objectCache;
private Set<CacheKey> negativeCache;
public CachingConfigClientWrapper(ConfigClient clientDelegate) {
this(clientDelegate, new HashMap<CacheKey, Message>(), new HashSet<CacheKey>());
}
public CachingConfigClientWrapper(ConfigClient clientDelegate, Map<CacheKey, Message> objectCache, Set<CacheKey> negativeCache) {
this.clientDelegate = clientDelegate;
this.objectCache = objectCache;
this.negativeCache = negativeCache;
}
@SuppressWarnings({"unchecked"})
@Override
public <U extends Message> U getConfig(Class<U> configClass, ConfigParamsBuilder.ConfigParamsMap configParams) {
CacheKey key = new CacheKey(configClass, configParams);
Message data = objectCache.get(key);
if (data == null) {
if (!negativeCache.contains(key)) {
data = clientDelegate.getConfig(configClass, configParams);
if (data != null) {
objectCache.put(key, data);
} else {
negativeCache.add(key);
}
}
}
return (U) data;
}
@Override
public ConfigProvider getConfigProvider() {
return clientDelegate.getConfigProvider();
}
public boolean reloadConfig() {
this.clearCache();
return true;
}
public synchronized void clearCache() {
this.objectCache.clear();
this.negativeCache.clear();
}
public ConfigClient getClientDelegate() {
return clientDelegate;
}
/**
* @return an immutable version of the underlying object cache
*/
public Map<CacheKey, Message> getObjectCache() {
return Collections.unmodifiableMap(objectCache);
}
/**
* @return an immutable version of the underlying negative/missed request cache
*/
public Set<CacheKey> getNegativeCache() {
return Collections.unmodifiableSet(negativeCache);
}
public class CacheKey {
private Class configClass;
private ConfigParamsBuilder.ConfigParamsMap configParams;
public CacheKey(Class configClass, ConfigParamsBuilder.ConfigParamsMap configParams) {
this.configClass = configClass;
this.configParams = configParams;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CacheKey cacheKey = (CacheKey) o;
if (configClass != null ? !configClass.equals(cacheKey.configClass) : cacheKey.configClass != null)
return false;
if (configParams != null ? !configParams.equals(cacheKey.configParams) : cacheKey.configParams != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = configClass != null ? configClass.hashCode() : 0;
result = 31 * result + (configParams != null ? configParams.hashCode() : 0);
return result;
}
}
}