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.CalcExchange;
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;
class ExchangeCache {
public static LoadingCache<Long, List<CalcExchange>> create(
IDatabase database, ConversionTable conversionTable,
FlowTypeTable flowTypes) {
return CacheBuilder.newBuilder().build(
new ExchangeLoader(database, conversionTable, flowTypes));
}
private static class ExchangeLoader extends
CacheLoader<Long, List<CalcExchange>> {
private Logger log = LoggerFactory.getLogger(getClass());
private IDatabase database;
private ConversionTable conversionTable;
private FlowTypeTable flowTypes;
public ExchangeLoader(IDatabase database,
ConversionTable conversionTable, FlowTypeTable flowTypes) {
this.database = database;
this.conversionTable = conversionTable;
this.flowTypes = flowTypes;
}
@Override
public List<CalcExchange> load(Long key) throws Exception {
if (key == null)
return Collections.emptyList();
log.trace("fetch exchanges for key {}", key);
String query = "select * from tbl_exchanges where f_owner = " + key;
try (Connection con = database.createConnection()) {
Statement statement = con.createStatement();
ResultSet result = statement.executeQuery(query);
ArrayList<CalcExchange> exchanges = new ArrayList<>();
while (result.next()) {
CalcExchange exchange = nextExchange(result);
exchanges.add(exchange);
}
result.close();
statement.close();
log.trace("fetched {} exchanges", exchanges.size());
return exchanges;
} catch (Exception e) {
log.error("failed to fetch exchange vector", e);
return Collections.emptyList();
}
}
@Override
public Map<Long, List<CalcExchange>> loadAll(
Iterable<? extends Long> keys) throws Exception {
log.trace("fetch exchanges for multiple keys");
try (Connection con = database.createConnection()) {
String query = "select * from tbl_exchanges where f_owner in "
+ CacheUtil.asSql(keys);
Statement statement = con.createStatement();
HashMap<Long, List<CalcExchange>> map = new HashMap<>();
ResultSet result = statement.executeQuery(query);
while (result.next()) {
CalcExchange e = nextExchange(result);
CacheUtil.addListEntry(map, e, e.processId);
}
result.close();
statement.close();
log.trace("{} lists loaded", map.size());
return map;
} catch (Exception e) {
log.error("failed to fetch exchange vectors", e);
return Collections.emptyMap();
}
}
private CalcExchange nextExchange(ResultSet r) throws Exception {
CalcExchange e = new CalcExchange();
e.processId = r.getLong("f_owner");
e.amount = r.getDouble("resulting_amount_value");
e.amountFormula = r.getString("resulting_amount_formula");
double factor = getConversionFactor(r);
e.conversionFactor = factor;
e.exchangeId = r.getLong("id");
e.flowId = r.getLong("f_flow");
e.flowType = flowTypes.get(e.flowId);
e.input = r.getBoolean("is_input");
e.defaultProviderId = r.getLong("f_default_provider");
e.avoidedProduct = r.getBoolean("avoided_product");
e.costValue = r.getDouble("cost_value");
e.costFormula = r.getString("cost_formula");
e.currency = r.getLong("f_currency");
int uncertaintyType = r.getInt("distribution_type");
if (!r.wasNull()) {
e.uncertaintyType = UncertaintyType.values()[uncertaintyType];
e.parameter1 = r.getDouble("parameter1_value");
e.parameter2 = r.getDouble("parameter2_value");
e.parameter3 = r.getDouble("parameter3_value");
e.parameter1Formula = r.getString("parameter1_formula");
e.parameter2Formula = r.getString("parameter2_formula");
e.parameter3Formula = r.getString("parameter3_formula");
}
return e;
}
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 (propertyFactor == 0)
return 0;
return unitFactor / propertyFactor;
}
}
}