package edu.mayo.cts2.framework.webapp.naming; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import edu.mayo.cts2.framework.model.codesystemversion.CodeSystemVersionCatalogEntry; import edu.mayo.cts2.framework.model.command.ResolvedReadContext; import edu.mayo.cts2.framework.model.util.ModelUtils; import edu.mayo.cts2.framework.service.profile.codesystemversion.CodeSystemVersionReadService; import edu.mayo.cts2.framework.service.provider.ServiceProviderChangeObserver; import org.springframework.stereotype.Component; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @Component public class CodeSystemVersionNameResolver extends TagResolver implements ServiceProviderChangeObserver { private static final int CACHE_SIZE = 200; private static final int CACHE_EXPIRE_MINUTES = 10; private Cache<Integer, String> nameCache = CacheBuilder.newBuilder(). expireAfterWrite(CACHE_EXPIRE_MINUTES, TimeUnit.MINUTES).maximumSize(CACHE_SIZE).build(); private Cache<Integer, String> versionIdCache = CacheBuilder.newBuilder(). expireAfterWrite(CACHE_EXPIRE_MINUTES, TimeUnit.MINUTES).maximumSize(CACHE_SIZE).build(); @Override public void onServiceProviderChange() { this.clearCaches(); } protected void clearCaches(){ this.nameCache.invalidateAll(); this.versionIdCache.invalidateAll(); } public String getVersionIdFromCodeSystemVersionName( final CodeSystemVersionReadService codeSystemVersionReadService, final String codeSystemVersionName, final ResolvedReadContext readContext) { int key = this.getCacheKey(codeSystemVersionName); try { return this.versionIdCache.get(key, new Callable<String>(){ @Override public String call() throws Exception { CodeSystemVersionCatalogEntry csv = null; if (codeSystemVersionReadService != null) { csv = codeSystemVersionReadService.read( ModelUtils.nameOrUriFromName(codeSystemVersionName), null); } String versionId; if (csv != null && csv.getOfficialResourceVersionId() != null) { versionId = csv.getOfficialResourceVersionId(); } else { versionId = codeSystemVersionName; } return versionId; } }); } catch (ExecutionException e) { throw new RuntimeException(e); } } public String getCodeSystemVersionNameFromVersionId( final CodeSystemVersionReadService codeSystemVersionReadService, final String codeSystemName, final String versionId, final ResolvedReadContext readContext) { int key = this.getCacheKey(codeSystemName, versionId); try { return this.nameCache.get(key, new Callable<String>(){ @Override public String call() throws Exception { CodeSystemVersionCatalogEntry csv = null; if (codeSystemVersionReadService != null) { try { csv = codeSystemVersionReadService .getCodeSystemByVersionId(ModelUtils .nameOrUriFromName(codeSystemName), versionId, readContext); // try without the ReadContext if (csv == null) { csv = codeSystemVersionReadService .getCodeSystemByVersionId(ModelUtils .nameOrUriFromName(codeSystemName), versionId, null); } } catch (UnsupportedOperationException e) { // if this isn't available, we can't resolve the name from // the version id. } } String name; if (csv != null) { name = csv.getCodeSystemVersionName(); } else { name = versionId; } return name; } }); } catch (ExecutionException e) { throw new RuntimeException(e); } } protected int getCacheKey(String... keys) { StringBuffer sb = new StringBuffer(); for (String key : keys) { sb.append(key); } return sb.toString().hashCode(); } }