package org.openlca.core.matrix.cache; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.openlca.core.database.IDatabase; import org.openlca.core.matrix.CalcAllocationFactor; import org.openlca.core.model.AllocationMethod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; /** * Provides allocation factors from the database. The table is backed by a * loading cache. */ class AllocationCache { public static LoadingCache<Long, List<CalcAllocationFactor>> create( IDatabase database) { return CacheBuilder.newBuilder().build(new FactorLoader(database)); } /** * Loads all allocation factors for a process from the database. */ private static class FactorLoader extends CacheLoader<Long, List<CalcAllocationFactor>> { private Logger log = LoggerFactory.getLogger(getClass()); private IDatabase database; public FactorLoader(IDatabase database) { this.database = database; } @Override public List<CalcAllocationFactor> load(Long processId) throws Exception { log.trace("load allocation factors for process {}", processId); try (Connection con = database.createConnection()) { String sql = "select * from tbl_allocation_factors where f_process = " + processId; Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql); ArrayList<CalcAllocationFactor> factors = new ArrayList<>(); while (rs.next()) { CalcAllocationFactor factor = fetchFactor(rs); factors.add(factor); } stmt.close(); rs.close(); return factors; } catch (Exception e) { log.error("failed to load allocation factors for " + processId, e); return Collections.emptyList(); } } @Override public Map<Long, List<CalcAllocationFactor>> loadAll( Iterable<? extends Long> processIds) throws Exception { log.trace("load allocation factors"); try (Connection con = database.createConnection()) { String sql = "select * from tbl_allocation_factors where f_process in " + CacheUtil.asSql(processIds); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql); Map<Long, List<CalcAllocationFactor>> map = new HashMap<>(); while (rs.next()) { CalcAllocationFactor factor = fetchFactor(rs); CacheUtil.addListEntry(map, factor, factor.getProcessId()); } stmt.close(); rs.close(); CacheUtil.fillEmptyEntries(processIds, map); return map; } catch (Exception e) { log.error("failed to load allocation factors", e); return Collections.emptyMap(); } } private CalcAllocationFactor fetchFactor(ResultSet rs) throws Exception { CalcAllocationFactor factor = new CalcAllocationFactor(); String typeStr = rs.getString("allocation_type"); factor.setMethod(AllocationMethod.valueOf(typeStr)); factor.setProcessId(rs.getLong("f_process")); factor.setProductId(rs.getLong("f_product")); factor.setValue(rs.getDouble("value")); long exchangeId = rs.getLong("f_exchange"); if (!rs.wasNull()) factor.setExchangeId(exchangeId); return factor; } } }