/* * Copyright (c) 2017 OBiBa. All rights reserved. * * This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.obiba.magma.support; import com.google.common.base.Joiner; import com.google.common.base.Objects; import com.google.common.base.Supplier; import com.google.common.collect.Iterables; import org.obiba.magma.*; import org.springframework.cache.Cache; import javax.validation.constraints.NotNull; import java.util.*; import java.util.stream.Collectors; import java.util.stream.StreamSupport; public class CachedValueTable implements ValueTable { private Cache cache; private ValueTable wrapped; private CachedDatasource datasource; private String name; public CachedValueTable(@NotNull CachedDatasource datasource, @NotNull String tableName, @NotNull Cache cache) { this.name = tableName; this.datasource = datasource; this.cache = cache; try { wrapped = datasource.getWrappedDatasource().getValueTable(tableName); } catch( MagmaRuntimeException ex) { //ignore } } @Override public String getName() { return name; } public ValueTable getWrappedValueTable() { if (this.wrapped == null) throw new MagmaRuntimeException("wrapped value not initialized."); return this.wrapped; } @NotNull @Override public Datasource getDatasource() { return this.datasource; } @Override public String getEntityType() { return getCached(getCacheKey("getEntityType"), new Supplier<String>() { @Override public String get() { return getWrappedValueTable().getEntityType(); } }); } @Override public Value getValue(final Variable variable, final ValueSet valueSet) { return getCached(getCacheKey("getValue", variable.getName(), valueSet.getValueTable().getName(), valueSet.getVariableEntity().getIdentifier()), new Supplier<Value>() { @Override public Value get() { return getWrappedValueTable().getValue(variable, valueSet); } }); } @Override public Set<VariableEntity> getVariableEntities() { return getCached(getCacheKey("getVariableEntities"), new Supplier<Set<VariableEntity>>() { @Override public Set<VariableEntity> get() { return getWrappedValueTable().getVariableEntities(); } }); } @Override public ValueSet getValueSet(final VariableEntity entity) throws NoSuchValueSetException { return new CachedValueSet(this, entity, cache); } @Override public boolean canDropValueSets() { return getCached(getCacheKey("canDropValueSets"), new Supplier<Boolean>() { @Override public Boolean get() { return getWrappedValueTable().canDropValueSets(); } }); } @Override public void dropValueSets() { getWrappedValueTable().canDropValueSets(); } @Override public Timestamps getValueSetTimestamps(final VariableEntity entity) throws NoSuchValueSetException { return new CachedTimestamps(new CachedValueSet(this, entity, cache), cache); } @Override public Iterable<Timestamps> getValueSetTimestamps(final SortedSet<VariableEntity> entities) { List<String> ids = new ArrayList<>(); for(VariableEntity variableEntity : entities) { ids.add(variableEntity.getIdentifier()); } return getCached(getCacheKey("getValueSetTimestamps", Joiner.on(".").join(ids)), new Supplier<Iterable<Timestamps>>() { @Override public Iterable<Timestamps> get() { return getWrappedValueTable().getValueSetTimestamps(entities); } }); } @Override public Iterable<ValueSet> getValueSets() { return getValueSets(getVariableEntities()); } @Override public Iterable<ValueSet> getValueSets(Iterable<VariableEntity> entities) { return StreamSupport.stream(entities.spliterator(), false) // .map(entity -> new CachedValueSet(CachedValueTable.this, entity, cache)) // .collect(Collectors.toList()); } @Override public boolean hasVariable(final String name) { return getCached(getCacheKey("hasVariable", name), new Supplier<Boolean>() { @Override public Boolean get() { return getWrappedValueTable().hasVariable(name); } }); } @Override public Variable getVariable(final String name) throws NoSuchVariableException { return getCached(getCacheKey("getVariable", name), new Supplier<Variable>() { @Override public Variable get() { return getWrappedValueTable().getVariable(name); } }); } @Override public Iterable<Variable> getVariables() { return getCached(getCacheKey("getVariables"), new Supplier<Iterable<Variable>>() { @Override public Iterable<Variable> get() { return getWrappedValueTable().getVariables(); } }); } @Override public VariableValueSource getVariableValueSource(String variableName) throws NoSuchVariableException { return new CachedVariableValueSource(this, variableName, cache); } @Override public boolean hasValueSet(final VariableEntity entity) { return getCached(getCacheKey("hasValueSet", entity.getIdentifier()), new Supplier<Boolean>() { @Override public Boolean get() { return getWrappedValueTable().hasValueSet(entity); } }); } @Override public boolean isForEntityType(final String entityType) { return getCached(getCacheKey("isForEntityType", entityType), new Supplier<Boolean>() { @Override public Boolean get() { return getWrappedValueTable().isForEntityType(entityType); } }); } @NotNull @Override public Timestamps getTimestamps() { return new CachedTimestamps(this, cache); } @Override public boolean isView() { return getCached(getCacheKey("isView"), new Supplier<Boolean>() { @Override public Boolean get() { return getWrappedValueTable().isView(); } }); } @Override public String getTableReference() { return getCached(getCacheKey("getTableReference"), new Supplier<String>() { @Override public String get() { return getWrappedValueTable().getTableReference(); } }); } @Override public int getVariableCount() { return getCached(getCacheKey("getVariableCount"), new Supplier<Integer>() { @Override public Integer get() { return getWrappedValueTable().getVariableCount(); } }); } @Override public int getValueSetCount() { return getCached(getCacheKey("getValueSetCount"), new Supplier<Integer>() { @Override public Integer get() { return getWrappedValueTable().getValueSetCount(); } }); } @Override public int getVariableEntityCount() { return getCached(getCacheKey("getVariableEntityCount"), new Supplier<Integer>() { @Override public Integer get() { return getWrappedValueTable().getVariableEntityCount(); } }); } @Override public int hashCode() { return Objects.hashCode(name); } @Override public boolean equals(Object other) { if (!(other instanceof CachedValueTable)) return false; return Objects.equal(name, ((CachedValueTable)other).getName()); } public void evictValues(VariableEntity variableEntity) { try { for(Variable va : getVariables()) { cache.evict(getCacheKey("getValue", va.getName(), name, variableEntity.getIdentifier())); cache.evict(getCacheKey("hasValueSet", variableEntity.getIdentifier())); CachedVariableValueSource vs = (CachedVariableValueSource) getVariableValueSource(va.getName()); vs.evictValues(variableEntity); } } catch(MagmaRuntimeException ex) { //ignore } } private <T> T getCached(Object key, Supplier<T> supplier) { return CacheUtils.getCached(cache, key, supplier); } private String getCacheKey(Object... parts) { return Joiner.on(".").join(Iterables.concat(Arrays.asList(datasource.getName(), name), Arrays.asList(parts))); } }