/**
* =============================================================================
*
* ORCID (R) Open Source
* http://orcid.org
*
* Copyright (c) 2012-2014 ORCID, Inc.
* Licensed under an MIT-Style License (MIT)
* http://orcid.org/open-source-license
*
* This copyright and license information (including a link to the full license)
* shall be included in its entirety in all copies or substantial portion of
* the software.
*
* =============================================================================
*/
package org.orcid.core.manager.impl;
import java.util.Date;
import javax.annotation.Resource;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.orcid.core.manager.LoadOptions;
import org.orcid.core.manager.OrcidProfileCacheManager;
import org.orcid.core.manager.OrcidProfileManagerReadOnly;
import org.orcid.jaxb.model.message.OrcidProfile;
import org.orcid.utils.ReleaseNameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OrcidProfileCacheManagerImpl implements OrcidProfileCacheManager {
private OrcidProfileManagerReadOnly orcidProfileManager;
@Resource(name = "publicProfileCache")
private Cache publicProfileCache;
LockerObjectsManager pubLocks = new LockerObjectsManager();
@Resource(name = "publicBioCache")
private Cache publicBioCache;
LockerObjectsManager pubBioLocks = new LockerObjectsManager();
@Resource(name = "profileCache")
private Cache profileCache;
LockerObjectsManager profileLockers = new LockerObjectsManager();
@Resource(name = "profileBioAndInternalCache")
private Cache profileBioAndInternalCache;
LockerObjectsManager profileBioAndInternalLockers = new LockerObjectsManager();
private String releaseName = ReleaseNameUtils.getReleaseName();
private static final Logger LOG = LoggerFactory.getLogger(OrcidProfileCacheManagerImpl.class);
public void setOrcidProfileManager(OrcidProfileManagerReadOnly orcidProfileManager) {
this.orcidProfileManager = orcidProfileManager;
}
@Override
public OrcidProfile retrievePublic(String orcid) {
Object key = new OrcidCacheKey(orcid, releaseName);
Date dbDate = retrieveLastModifiedDate(orcid);
OrcidProfile op = toOrcidProfile(publicProfileCache.get(key));
if (needsFresh(dbDate, op))
try {
synchronized (pubLocks.obtainLock(orcid)) {
op = toOrcidProfile(publicProfileCache.get(orcid));
if (needsFresh(dbDate, op)) {
op = orcidProfileManager.retrievePublicOrcidProfile(orcid);
publicProfileCache.put(new Element(key, op));
}
}
} finally {
pubLocks.releaseLock(orcid);
}
return op;
}
@Override
public OrcidProfile retrievePublicBio(String orcid) {
Object key = new OrcidCacheKey(orcid, releaseName);
Date dbDate = retrieveLastModifiedDate(orcid);
OrcidProfile op = toOrcidProfile(publicBioCache.get(key));
if (needsFresh(dbDate, op))
try {
synchronized (pubBioLocks.obtainLock(orcid)) {
op = toOrcidProfile(publicBioCache.get(orcid));
if (needsFresh(dbDate, op)) {
op = orcidProfileManager.retrievePublicOrcidProfile(orcid, LoadOptions.BIO_ONLY);
publicBioCache.put(new Element(key, op));
}
}
} finally {
pubBioLocks.releaseLock(orcid);
}
return op;
}
@Override
public OrcidProfile retrieveProfileBioAndInternal(String orcid) {
Object key = new OrcidCacheKey(orcid, releaseName);
Date dbDate = retrieveLastModifiedDate(orcid);
OrcidProfile op = toOrcidProfile(profileBioAndInternalCache.get(key));
if (needsFresh(dbDate, op))
try {
synchronized (profileBioAndInternalLockers.obtainLock(orcid)) {
op = toOrcidProfile(profileBioAndInternalCache.get(orcid));
if (needsFresh(dbDate, op)) {
op = orcidProfileManager.retrieveFreshOrcidProfile(orcid, LoadOptions.BIO_AND_INTERNAL_ONLY);
profileBioAndInternalCache.put(new Element(key, op));
}
}
} finally {
profileBioAndInternalLockers.releaseLock(orcid);
}
return op;
}
@Override
public OrcidProfile retrieve(String orcid) {
Object key = new OrcidCacheKey(orcid, releaseName);
Date dbDate = retrieveLastModifiedDate(orcid);
OrcidProfile op = toOrcidProfile(profileCache.get(key));
if (needsFresh(dbDate, op))
try {
synchronized (profileLockers.obtainLock(orcid)) {
op = toOrcidProfile(profileCache.get(orcid));
if (needsFresh(dbDate, op)) {
op = orcidProfileManager.retrieveFreshOrcidProfile(orcid, LoadOptions.ALL);
profileCache.put(new Element(key, op));
}
}
} finally {
profileLockers.releaseLock(orcid);
}
return op;
}
private Date retrieveLastModifiedDate(String orcid) {
Date date = null;
try {
date = orcidProfileManager.retrieveLastModifiedDate(orcid);
} catch (javax.persistence.NoResultException e) {
LOG.debug("Missing retrieveLastModifiedDate orcid:" + orcid);
}
return date;
}
public void put(OrcidProfile orcidProfile) {
put(orcidProfile.getOrcidIdentifier().getPath(), orcidProfile);
}
public void put(String orcid, OrcidProfile orcidProfile) {
try {
synchronized (profileLockers.obtainLock(orcid)) {
profileCache.put(new Element(new OrcidCacheKey(orcid, releaseName), orcidProfile));
}
} finally {
profileLockers.releaseLock(orcid);
}
}
public void removeAll() {
profileCache.removeAll();
}
public void remove(String orcid) {
profileCache.remove(new OrcidCacheKey(orcid, releaseName));
}
static public OrcidProfile toOrcidProfile(Element element) {
return (OrcidProfile) (element != null ? element.getObjectValue() : null);
}
static public boolean needsFresh(Date dbDate, OrcidProfile orcidProfile) {
if (orcidProfile == null)
return true;
if (dbDate == null) // not sure when this happens?
return true;
if (orcidProfile.extractLastModifiedDate().getTime() != dbDate.getTime())
return true;
return false;
}
}