package org.openlca.core.matrix.cache;
import java.util.List;
import org.openlca.core.database.IDatabase;
import org.openlca.core.matrix.CalcAllocationFactor;
import org.openlca.core.matrix.CalcExchange;
import org.openlca.core.matrix.CalcImpactFactor;
import org.openlca.core.model.ModelType;
import com.google.common.cache.LoadingCache;
public final class MatrixCache {
private final boolean lazy;
private final IDatabase database;
private FlowTypeTable flowTypeTable;
private ConversionTable conversionTable;
private ProcessTable processTable;
private LoadingCache<Long, List<CalcAllocationFactor>> allocationCache;
private LoadingCache<Long, List<CalcImpactFactor>> impactCache;
private LoadingCache<Long, List<CalcExchange>> exchangeCache;
public static MatrixCache createEager(IDatabase database) {
return new MatrixCache(database, false);
}
public static MatrixCache createLazy(IDatabase database) {
return new MatrixCache(database, true);
}
private MatrixCache(IDatabase database, boolean lazy) {
this.database = database;
this.lazy = lazy;
if (!lazy) {
flowTypeTable = FlowTypeTable.create(database);
conversionTable = ConversionTable.create(database);
processTable = ProcessTable.create(database, flowTypeTable);
exchangeCache = ExchangeCache.create(database, conversionTable,
flowTypeTable);
allocationCache = AllocationCache.create(database);
impactCache = ImpactFactorCache.create(database, conversionTable);
}
}
public IDatabase getDatabase() {
return database;
}
private FlowTypeTable getFlowTypeTable() {
if (flowTypeTable == null)
flowTypeTable = FlowTypeTable.create(database);
return flowTypeTable;
}
private ConversionTable getConversionTable() {
if (conversionTable == null)
conversionTable = ConversionTable.create(database);
return conversionTable;
}
public ProcessTable getProcessTable() {
if (processTable == null)
processTable = ProcessTable.create(database, getFlowTypeTable());
return processTable;
}
public LoadingCache<Long, List<CalcAllocationFactor>> getAllocationCache() {
if (allocationCache == null)
allocationCache = AllocationCache.create(database);
return allocationCache;
}
public LoadingCache<Long, List<CalcImpactFactor>> getImpactCache() {
if (impactCache == null)
impactCache = ImpactFactorCache.create(database,
getConversionTable());
return impactCache;
}
public LoadingCache<Long, List<CalcExchange>> getExchangeCache() {
if (exchangeCache == null)
exchangeCache = ExchangeCache.create(database,
getConversionTable(), getFlowTypeTable());
return exchangeCache;
}
public synchronized void evictAll() {
if (flowTypeTable != null)
flowTypeTable.reload();
if (conversionTable != null)
conversionTable.reload();
if (exchangeCache != null)
exchangeCache.invalidateAll();
if (allocationCache != null)
allocationCache.invalidateAll();
if (impactCache != null)
impactCache.invalidateAll();
processTable = null;
}
public synchronized void evict(ModelType type, long id) {
if (type == null)
return;
switch (type) {
case FLOW:
baseEviction();
break;
case FLOW_PROPERTY:
baseEviction();
break;
case IMPACT_CATEGORY:
if (impactCache != null)
impactCache.invalidate(id);
break;
case IMPACT_METHOD:
if (impactCache != null)
impactCache.invalidateAll();
break;
case PROCESS:
evictProcess(id);
break;
case UNIT:
baseEviction();
break;
case UNIT_GROUP:
baseEviction();
break;
default:
break;
}
}
private void baseEviction() {
if (conversionTable == null && flowTypeTable == null)
return; // there cannot be an exchange or impact cache
if (lazy) {
conversionTable = null;
flowTypeTable = null;
exchangeCache = null;
impactCache = null;
} else {
conversionTable.reload();
flowTypeTable.reload();
exchangeCache.invalidateAll();
impactCache.invalidateAll();
}
processTable = null;
}
private void evictProcess(long id) {
processTable = null;
if (exchangeCache != null)
exchangeCache.invalidate(id);
if (allocationCache != null)
allocationCache.invalidate(id);
}
public synchronized void registerNew(ModelType type, long id) {
if (type == null)
return;
switch (type) {
case FLOW:
baseEviction();
break;
case FLOW_PROPERTY:
baseEviction();
break;
case PROCESS:
processTable = null;
break;
case UNIT:
baseEviction();
break;
case UNIT_GROUP:
baseEviction();
break;
default:
break;
}
}
}