package org.openlca.core.matrix; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import org.openlca.core.database.IDatabase; import org.openlca.core.database.NativeSql; import org.openlca.core.results.ImpactResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Stores the factors of a normalization and weighting set. As creating such a * table is quite simple there is no separate builder class for reading this * kind of data from a database but a factory method in this class. */ public class NwSetTable { private final HashMap<Long, Double> weightFactors = new HashMap<>(); private final HashMap<Long, Double> normFactors = new HashMap<>(); private boolean hasWeightFactors = false; private boolean hasNormFactors = false; /** * Builds the table by reading the factors for the NW-set with the given ID * from the given database. */ public static NwSetTable build(IDatabase database, long nwSetId) { final NwSetTable table = new NwSetTable(); String query = "select * from tbl_nw_factors where f_nw_set = " + nwSetId; try { NativeSql.on(database).query(query, new NativeSql.QueryResultHandler() { @Override public boolean nextResult(ResultSet result) throws SQLException { fetchResult(result, table); return true; } }); } catch (Exception e) { Logger log = LoggerFactory.getLogger(NwSetTable.class); log.error("failed to get nw-factors", e); } return table; } private static void fetchResult(ResultSet result, NwSetTable table) throws SQLException { long categoryId = result.getLong("f_impact_category"); double weightingFactor = result.getDouble("weighting_factor"); if (!result.wasNull()) { table.weightFactors.put(categoryId, weightingFactor); table.hasWeightFactors = true; } double normalisationFactor = result.getDouble("normalisation_factor"); if (!result.wasNull()) { table.normFactors.put(categoryId, normalisationFactor); table.hasNormFactors = true; } } public boolean hasWeightingFactors() { return hasWeightFactors; } public boolean hasNormalisationFactors() { return hasNormFactors; } /** * Get the weighting factor for the given LCIA category. */ public double getWeightingFactor(long impactCategoryId) { Double f = weightFactors.get(impactCategoryId); return f == null ? 0 : f; } /** * Get the normalization factor for the given LCIA category. */ public double getNormalisationFactor(long impactCategoryId) { Double f = normFactors.get(impactCategoryId); return f == null ? 0 : f; } /** * Applies the normalization factors to the given impact assessment result. * Returns a normalized result for each result item in the given list. The * given list is not modified. */ public List<ImpactResult> applyNormalisation(List<ImpactResult> results) { return apply(results, 0); } /** * Applies the weighting factors to the given impact assessment result. * Returns a weighted result for each result item in the given list. The * given list is not modified. */ public List<ImpactResult> applyWeighting(List<ImpactResult> results) { return apply(results, 1); } /** * Applies the normalization and weighting factors to the given impact * assessment result. Returns a normalized and weighted result for each * result item in the given list. The given list is not modified. */ public List<ImpactResult> applyBoth(List<ImpactResult> results) { return apply(results, 2); } /** * Applies the factors in this table depending on the given type: * <ul> * <li>0: normalization * <li>1: weighting * <li>2: both */ private List<ImpactResult> apply(List<ImpactResult> results, int type) { if (results == null) return Collections.emptyList(); List<ImpactResult> applied = new ArrayList<>(); for (ImpactResult result : results) { if (result.impactCategory == null) continue; ImpactResult r = new ImpactResult(); r.impactCategory = result.impactCategory; applied.add(r); long impactId = result.impactCategory.getId(); double f = getFactor(type, impactId); r.value = f * result.value; } return applied; } private double getFactor(int type, long impactId) { switch (type) { case 0: double nf = getNormalisationFactor(impactId); return nf == 0 ? 0 : 1 / nf; case 1: return getWeightingFactor(impactId); case 2: double nff = getNormalisationFactor(impactId); return nff == 0 ? 0 : getWeightingFactor(impactId) / nff; default: return 0; } } }