/*
* 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 java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.validation.constraints.NotNull;
import org.obiba.magma.Datasource;
import org.obiba.magma.MagmaRuntimeException;
import org.obiba.magma.NoSuchValueTableException;
import org.obiba.magma.ValueTable;
import org.obiba.magma.VariableEntity;
import org.springframework.cache.Cache;
import com.google.common.base.Joiner;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class CachedDatasource extends AbstractDatasourceWrapper {
private Cache cache;
private final Map<String, ValueTable> cachedValueTablesMap = Maps.newHashMap();
public CachedDatasource(@NotNull Datasource wrapped, @NotNull Cache cache) {
super(wrapped);
this.cache = cache;
}
@Override
public Datasource getWrappedDatasource() {
Datasource wrapped = super.getWrappedDatasource();
if (wrapped == null) throw new MagmaRuntimeException("wrapped value not initialized");
return wrapped;
}
@Override
public void initialise() {
try {
cachedValueTablesMap.clear();
getWrappedDatasource().initialise();
} catch(MagmaRuntimeException ex) {
//ignore
}
}
@Override
public boolean hasValueTable(final String tableName) {
return getCached(getCacheKey("hasValueTable", tableName), new Supplier<Boolean>() {
@Override
public Boolean get() {
return getWrappedDatasource().hasValueTable(tableName);
}
});
}
@Override
public ValueTable getValueTable(final String tableName) throws NoSuchValueTableException {
if (cachedValueTablesMap.isEmpty()) getValueTables();
if (!cachedValueTablesMap.containsKey(tableName)) throw new NoSuchValueTableException(getName(), tableName);
return cachedValueTablesMap.get(tableName);
}
@Override
public Set<ValueTable> getValueTables() {
if (!cachedValueTablesMap.isEmpty()) return ImmutableSet.<ValueTable>builder().addAll(cachedValueTablesMap.values()).build();
List<String> valueTableNames = getCached(getCacheKey("getValueTables"), new Supplier<List<String>>() {
@Override
public List<String> get() {
List<String> res = Lists.newArrayList();
for(ValueTable table : getWrappedDatasource().getValueTables()) {
res.add(table.getName());
}
return res;
}
});
for(String tableName : valueTableNames) {
cachedValueTablesMap.put(tableName, new CachedValueTable(this, tableName, cache));
}
return ImmutableSet.<ValueTable>builder().addAll(cachedValueTablesMap.values()).build();
}
public void evictValues(VariableEntity variableEntity) {
for (ValueTable valueTable: getValueTables()) {
((CachedValueTable)valueTable).evictValues(variableEntity);
}
}
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(getName()), Arrays.asList(parts)));
}
}