/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.master.config.impl;
import static com.opengamma.util.ehcache.EHCacheUtils.putValue;
import java.util.Arrays;
import java.util.Collection;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import com.opengamma.core.change.ChangeEvent;
import com.opengamma.core.change.ChangeListener;
import com.opengamma.core.config.impl.ConfigItem;
import com.opengamma.id.ObjectId;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.master.config.ConfigDocument;
import com.opengamma.master.config.ConfigMaster;
import com.opengamma.master.config.ConfigSearchRequest;
import com.opengamma.master.config.ConfigSearchResult;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.ehcache.EHCacheUtils;
import com.opengamma.util.paging.PagingRequest;
/**
* A cache to optimize the results of {@code MasterConfigSource}.
*/
public class EHCachingMasterConfigSource extends MasterConfigSource {
/**
* Cache key for configs.
*/
/*package*/static final String CONFIG_CACHE = "config";
/**
* The result cache.
*/
private final Cache _configCache;
/**
* Creates the cache around an underlying config source.
*
* @param underlying the underlying data, not null
* @param cacheManager the cache manager, not null
*/
public EHCachingMasterConfigSource(final ConfigMaster underlying, final CacheManager cacheManager) {
super(underlying);
underlying.changeManager().addChangeListener(new ConfigDocumentChangeListener());
ArgumentChecker.notNull(cacheManager, "cacheManager");
EHCacheUtils.addCache(cacheManager, CONFIG_CACHE);
_configCache = EHCacheUtils.getCacheFromManager(cacheManager, CONFIG_CACHE);
}
//-------------------------------------------------------------------------
@SuppressWarnings("unchecked")
@Override
public <R> R getConfig(final Class<R> clazz, final UniqueId uniqueId) {
ArgumentChecker.notNull(clazz, "clazz");
ArgumentChecker.notNull(uniqueId, "uniqueId");
final Element element = _configCache.get(uniqueId);
if (element != null) {
final ConfigDocument doc = (ConfigDocument) EHCacheUtils.get(element);
if (doc != null) {
return (R) doc.getConfig().getValue();
} else {
return null;
}
}
try {
final ConfigDocument doc = getMaster().get(uniqueId);
putValue(uniqueId.getObjectId(), doc, _configCache);
return (R) putValue(uniqueId, doc, _configCache).getConfig().getValue();
} catch (final RuntimeException ex) {
return EHCacheUtils.<R>putException(uniqueId, ex, _configCache);
}
}
@SuppressWarnings("unchecked")
@Override
public <R> R getConfig(final Class<R> clazz, final ObjectId objectId, final VersionCorrection versionCorrection) {
ArgumentChecker.notNull(clazz, "clazz");
ArgumentChecker.notNull(objectId, "objectId");
ArgumentChecker.notNull(versionCorrection, "versionCorrection");
final Object searchKey = Arrays.asList(clazz, objectId, versionCorrection);
final Element element = _configCache.get(searchKey);
if (element != null) {
final ConfigDocument doc = (ConfigDocument) EHCacheUtils.get(element);
if (doc != null) {
return (R) doc.getConfig().getValue();
} else {
return null;
}
}
try {
final ConfigDocument doc = getMaster().get(objectId, versionCorrection);
final ConfigItem<R> item = (ConfigItem<R>) doc.getConfig();
putValue(item.getUniqueId().getObjectId(), doc, _configCache);
putValue(item.getUniqueId(), doc, _configCache);
return (R) putValue(searchKey, doc, _configCache).getConfig().getValue();
} catch (final RuntimeException ex) {
return EHCacheUtils.<R>putException(searchKey, ex, _configCache);
}
}
@SuppressWarnings("unchecked")
@Override
public <R> R getSingle(final Class<R> clazz, final String configName, final VersionCorrection versionCorrection) {
ArgumentChecker.notNull(clazz, "clazz");
ArgumentChecker.notNull(configName, "configName");
ArgumentChecker.notNull(versionCorrection, "versionCorrection");
final Object searchKey = Arrays.asList("single", clazz, configName, versionCorrection);
final Element element = _configCache.get(searchKey);
if (element != null) {
final ConfigDocument doc = (ConfigDocument) EHCacheUtils.get(element);
if (doc != null) {
return (R) doc.getConfig().getValue();
} else {
return null;
}
}
try {
final ConfigSearchRequest<R> searchRequest = new ConfigSearchRequest<R>(clazz);
searchRequest.setName(configName);
searchRequest.setVersionCorrection(versionCorrection);
final ConfigDocument doc = getMaster().search(searchRequest).getFirstDocument();
putValue(searchKey, doc, _configCache);
if (doc != null) {
putValue(doc.getUniqueId().getObjectId(), doc, _configCache);
putValue(doc.getUniqueId(), doc, _configCache);
return (R) doc.getConfig().getValue();
} else {
return null;
}
} catch (final RuntimeException ex) {
return EHCacheUtils.<R>putException(searchKey, ex, _configCache);
}
}
@SuppressWarnings({"unchecked", "rawtypes" })
@Override
public <R> Collection<ConfigItem<R>> get(final Class<R> clazz, final String name, final VersionCorrection versionCorrection) {
ArgumentChecker.notNull(clazz, "clazz");
ArgumentChecker.notNull(name, "name");
final Object searchKey = Arrays.asList("search", clazz, name, versionCorrection);
final Element element = _configCache.get(searchKey);
if (element != null) {
return ((ConfigSearchResult) EHCacheUtils.get(element)).getValues();
}
try {
final ConfigSearchRequest<R> searchRequest = new ConfigSearchRequest<R>(clazz);
searchRequest.setName(name);
searchRequest.setVersionCorrection(versionCorrection);
final ConfigSearchResult<R> searchResult = getMaster().search(searchRequest);
for (final ConfigDocument doc : searchResult.getDocuments()) {
putValue(doc.getUniqueId().getObjectId(), doc, _configCache);
putValue(doc.getUniqueId(), doc, _configCache);
}
putValue(searchKey, searchResult, _configCache);
return searchResult.getValues();
} catch (final RuntimeException ex) {
return EHCacheUtils.<Collection<ConfigItem<R>>>putException(searchKey, ex, _configCache);
}
}
@Override
public <R> Collection<ConfigItem<R>> getAll(final Class<R> clazz, final VersionCorrection versionCorrection) {
ArgumentChecker.notNull(clazz, "clazz");
final ConfigSearchRequest<R> request = new ConfigSearchRequest<R>();
request.setPagingRequest(PagingRequest.ALL);
request.setVersionCorrection(versionCorrection);
request.setType(clazz);
final ConfigSearchResult<R> searchResult = getMaster().search(request);
return searchResult.getValues();
}
@Override
public <R> R getLatestByName(final Class<R> clazz, final String name) {
return getSingle(clazz, name, VersionCorrection.LATEST);
}
//-------------------------------------------------------------------------
private class ConfigDocumentChangeListener implements ChangeListener {
@Override
public void entityChanged(final ChangeEvent event) {
switch (event.getType()) {
case CHANGED:
case REMOVED:
cleanCaches(event);
break;
default:
break;
}
}
private void cleanCaches(final ChangeEvent event) {
// final ObjectId objectId = event.getObjectId();
// if (inCache(objectId)) {
_configCache.removeAll(); // Jim - 5-Aug-2013 -- This was too conservative I think. Just flush everything for the moment.
// }
}
// private boolean inCache(final ObjectId objectId) {
// final Element element = _configCache.get(objectId);
// return element != null;
// }
}
}