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.CalcImpactFactor; import org.openlca.core.model.UncertaintyType; 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; public class ImpactFactorCache { static LoadingCache<Long, List<CalcImpactFactor>> create( IDatabase database, ConversionTable conversionTable) { return CacheBuilder.newBuilder().build( new FactorLoader(database, conversionTable)); } private static class FactorLoader extends CacheLoader<Long, List<CalcImpactFactor>> { private Logger log = LoggerFactory.getLogger(getClass()); private IDatabase database; private ConversionTable conversionTable; public FactorLoader(IDatabase database, ConversionTable conversionTable) { this.database = database; this.conversionTable = conversionTable; } @Override public List<CalcImpactFactor> load(Long impactId) throws Exception { log.trace("load impact factors for category {}", impactId); try (Connection con = database.createConnection()) { String query = "select * from tbl_impact_factors where f_impact_category = " + impactId; Statement statement = con.createStatement(); ResultSet result = statement.executeQuery(query); List<CalcImpactFactor> factors = new ArrayList<>(); while (result.next()) { CalcImpactFactor factor = nextFactor(result); factors.add(factor); } result.close(); statement.close(); return factors; } catch (Exception e) { log.error("failed to load impact factors for " + impactId, e); return Collections.emptyList(); } } @Override public Map<Long, List<CalcImpactFactor>> loadAll( Iterable<? extends Long> impactCategoryIds) throws Exception { log.trace("load impact factors for multiple categories"); try (Connection con = database.createConnection()) { String query = "select * from tbl_impact_factors where f_impact_category in " + CacheUtil.asSql(impactCategoryIds); Statement statement = con.createStatement(); ResultSet result = statement.executeQuery(query); Map<Long, List<CalcImpactFactor>> map = new HashMap<>(); while (result.next()) { CalcImpactFactor factor = nextFactor(result); CacheUtil.addListEntry(map, factor, factor.getImactCategoryId()); } result.close(); statement.close(); CacheUtil.fillEmptyEntries(impactCategoryIds, map); return map; } catch (Exception e) { log.error("failed to load impact factors", e); return Collections.emptyMap(); } } private CalcImpactFactor nextFactor(ResultSet r) throws Exception { CalcImpactFactor f = new CalcImpactFactor(); f.setImactCategoryId(r.getLong("f_impact_category")); f.setAmount(r.getDouble("value")); f.setAmountFormula(r.getString("formula")); f.setConversionFactor(getConversionFactor(r)); f.setFlowId(r.getLong("f_flow")); int uncertaintyType = r.getInt("distribution_type"); if (!r.wasNull()) { f.setUncertaintyType(UncertaintyType.values()[uncertaintyType]); f.setParameter1(r.getDouble("parameter1_value")); f.setParameter2(r.getDouble("parameter2_value")); f.setParameter3(r.getDouble("parameter3_value")); f.setParameter1Formula(r.getString("parameter1_formula")); f.setParameter2Formula(r.getString("parameter2_formula")); f.setParameter3Formula(r.getString("parameter3_formula")); } return f; } private double getConversionFactor(ResultSet record) throws Exception { long propertyFactorId = record.getLong("f_flow_property_factor"); double propertyFactor = conversionTable .getPropertyFactor(propertyFactorId); long unitId = record.getLong("f_unit"); double unitFactor = conversionTable.getUnitFactor(unitId); if (unitFactor == 0) return 0; return propertyFactor / unitFactor; } } }