/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.core.security.impl; import java.util.Collection; import java.util.HashMap; import java.util.Map; import net.sf.ehcache.Cache; import net.sf.ehcache.Element; import com.opengamma.core.change.ChangeManager; import com.opengamma.core.security.Security; import com.opengamma.core.security.SecuritySource; import com.opengamma.id.ExternalIdBundle; import com.opengamma.id.ObjectId; import com.opengamma.id.UniqueId; import com.opengamma.id.VersionCorrection; import com.opengamma.util.ArgumentChecker; /** * An implementation of {@link SecuritySource} designed to work with any non-versioned * SecuritySource for basic caching. * It also does not cache failures to resolve (e.g. a result of null) so that if the underlying * is changed underneath this will be picked up. * @see NonVersionedRedisSecuritySource */ public class NonVersionedEHCachingSecuritySource implements SecuritySource { private final SecuritySource _underlying; private final Cache _cache; public NonVersionedEHCachingSecuritySource(SecuritySource underlying, Cache cache) { ArgumentChecker.notNull(underlying, "underlying"); ArgumentChecker.notNull(cache, "cache"); _underlying = underlying; _cache = cache; } /** * Gets the underlying. * @return the underlying */ protected SecuritySource getUnderlying() { return _underlying; } /** * Gets the cache. * @return the cache */ protected Cache getCache() { return _cache; } private enum CacheEntryType { SINGLE, COLLECTION } private static class SecurityCacheEntry { public SecurityCacheEntry(CacheEntryType entryType, ExternalIdBundle bundle, UniqueId uniqueId) { _entryType = entryType; _bundle = bundle; _uniqueId = uniqueId; _hashCode = generateHashCode(); } private final CacheEntryType _entryType; private final ExternalIdBundle _bundle; private final UniqueId _uniqueId; private final int _hashCode; private int generateHashCode() { final int prime = 31; int result = 1; result = prime * result + ((_bundle == null) ? 0 : _bundle.hashCode()); result = prime * result + ((_entryType == null) ? 0 : _entryType.hashCode()); result = prime * result + ((_uniqueId == null) ? 0 : _uniqueId.hashCode()); return result; } @Override public int hashCode() { return _hashCode; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } SecurityCacheEntry other = (SecurityCacheEntry) obj; if (_bundle == null) { if (other._bundle != null) { return false; } } else if (!_bundle.equals(other._bundle)) { return false; } if (_uniqueId == null) { if (other._uniqueId != null) { return false; } } else if (!_uniqueId.equals(other._uniqueId)) { return false; } if (_entryType != other._entryType) { return false; } return true; } } @Override public Collection<Security> get(ExternalIdBundle bundle, VersionCorrection versionCorrection) { return get(bundle); } @Override public Map<ExternalIdBundle, Collection<Security>> getAll(Collection<ExternalIdBundle> bundles, VersionCorrection versionCorrection) { Map<ExternalIdBundle, Collection<Security>> result = new HashMap<ExternalIdBundle, Collection<Security>>(); for (ExternalIdBundle bundle : bundles) { result.put(bundle, get(bundle)); } return result; } @SuppressWarnings("unchecked") @Override public Collection<Security> get(ExternalIdBundle bundle) { SecurityCacheEntry cacheEntry = new SecurityCacheEntry(CacheEntryType.COLLECTION, bundle, null); Element element = getCache().get(cacheEntry); Collection<Security> result = null; if (element == null) { result = getUnderlying().get(bundle); if (result != null) { element = new Element(cacheEntry, result); getCache().put(element); } } else { result = (Collection<Security>) element.getObjectValue(); } return result; } @Override public Security getSingle(ExternalIdBundle bundle) { SecurityCacheEntry cacheEntry = new SecurityCacheEntry(CacheEntryType.SINGLE, bundle, null); Element element = getCache().get(cacheEntry); Security result = null; if (element == null) { result = getUnderlying().getSingle(bundle); if (result != null) { element = new Element(cacheEntry, result); getCache().put(element); } } else { result = (Security) element.getObjectValue(); } return result; } @Override public Security getSingle(ExternalIdBundle bundle, VersionCorrection versionCorrection) { return getSingle(bundle); } @Override public Map<ExternalIdBundle, Security> getSingle(Collection<ExternalIdBundle> bundles, VersionCorrection versionCorrection) { Map<ExternalIdBundle, Security> result = new HashMap<ExternalIdBundle, Security>(); for (ExternalIdBundle bundle : bundles) { result.put(bundle, getSingle(bundle)); } return result; } @Override public Security get(UniqueId uniqueId) { SecurityCacheEntry cacheEntry = new SecurityCacheEntry(CacheEntryType.SINGLE, null, uniqueId); Element element = getCache().get(cacheEntry); Security result = null; if (element == null) { result = getUnderlying().get(uniqueId); if (result != null) { element = new Element(cacheEntry, result); getCache().put(element); } } else { result = (Security) element.getObjectValue(); } return result; } @Override public Security get(ObjectId objectId, VersionCorrection versionCorrection) { return get(UniqueId.of(objectId, null)); } @Override public Map<UniqueId, Security> get(Collection<UniqueId> uniqueIds) { Map<UniqueId, Security> result = new HashMap<UniqueId, Security>(); for (UniqueId uniqueId : uniqueIds) { result.put(uniqueId, get(uniqueId)); } return result; } @Override public Map<ObjectId, Security> get(Collection<ObjectId> objectIds, VersionCorrection versionCorrection) { Map<ObjectId, Security> result = new HashMap<ObjectId, Security>(); for (ObjectId objectId : objectIds) { result.put(objectId, get(UniqueId.of(objectId, null))); } return result; } @Override public ChangeManager changeManager() { return getUnderlying().changeManager(); } }