package org.openlca.io.xls.process.input; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Objects; import org.apache.poi.ss.usermodel.Sheet; import org.openlca.core.database.FlowDao; import org.openlca.core.model.Flow; import org.openlca.core.model.FlowProperty; import org.openlca.core.model.FlowPropertyFactor; import org.openlca.core.model.FlowType; import org.openlca.core.model.Location; import org.openlca.core.model.ModelType; import org.openlca.core.model.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Strings; class FlowSheets { private Logger log = LoggerFactory.getLogger(getClass()); private final Config config; private final FlowDao dao; private final Sheet factorSheet; private final Sheet flowSheet; private HashMap<String, List<Factor>> factors = new HashMap<>(); private FlowSheets(Config config) { this.config = config; this.dao = new FlowDao(config.database); this.factorSheet = config.workbook.getSheet("Flow property factors"); this.flowSheet = config.workbook.getSheet("Flows"); } public static void read(Config config) { new FlowSheets(config).read(); } private void read() { if (flowSheet == null || factorSheet == null) { return; } try { log.trace("import flows"); readFactors(); readFlows(); } catch (Exception e) { log.error("failed to import flows", e); } } private void readFactors() { int row = 1; while (true) { String name = config.getString(factorSheet, row, 0); if (Strings.isNullOrEmpty(name)) { break; } String category = config.getString(factorSheet, row, 1); String key = key(name, category); List<Factor> list = factors.get(key); if (list == null) { factors.put(key, list = new ArrayList<>()); } Factor factor = new Factor(row); list.add(factor); row++; } } private void readFlows() { int row = 1; while (true) { String uuid = config.getString(flowSheet, row, 0); if (Strings.isNullOrEmpty(uuid)) { break; } Flow flow = dao.getForRefId(uuid); if (flow != null) { syncFlow(row, flow); } else { createFlow(row, uuid); } row++; } } private void syncFlow(int row, Flow flow) { String name = config.getString(flowSheet, row, 1); String category = config.getString(flowSheet, row, 3); List<Factor> factors = this.factors.get(key(name, category)); if (factors == null || flow.getReferenceFlowProperty() == null) { config.refData.putFlow(name, category, flow); return; } String refProperty = config.getString(flowSheet, row, 10); if (!Objects.equals(refProperty, flow.getReferenceFlowProperty() .getName())) { // cannot add more factors as the reference flow property is not // the same config.refData.putFlow(name, category, flow); return; } boolean updated = addFactors(flow, factors); if (updated) { flow = dao.update(flow); } config.refData.putFlow(name, category, flow); } private boolean addFactors(Flow flow, List<Factor> factors) { boolean updated = false; for (Factor factor : factors) { FlowProperty property = config.refData .getFlowProperty(factor.property); if (property == null || flow.getFactor(property) != null) { continue; } FlowPropertyFactor f = new FlowPropertyFactor(); f.setFlowProperty(property); f.setConversionFactor(factor.factor); flow.getFlowPropertyFactors().add(f); updated = true; } return updated; } private void createFlow(int row, String uuid) { String name = config.getString(flowSheet, row, 1); String category = config.getString(flowSheet, row, 3); Flow flow = new Flow(); flow.setRefId(uuid); flow.setName(name); flow.setCategory(config.getCategory(category, ModelType.FLOW)); setAttributes(row, flow); List<Factor> factors = this.factors.get(key(name, category)); if (factors == null) { log.error("could not create flow {}/{}; no flow property factors", name, category); return; } createPropertyFactors(row, flow, factors); flow = dao.insert(flow); config.refData.putFlow(name, category, flow); } private void setAttributes(int row, Flow flow) { flow.setDescription(config.getString(flowSheet, row, 2)); String version = config.getString(flowSheet, row, 4); flow.setVersion(Version.fromString(version).getValue()); Date lastChange = config.getDate(flowSheet, row, 5); if (lastChange != null) { flow.setLastChange(lastChange.getTime()); } flow.setFlowType(getType(row)); flow.setCasNumber(config.getString(flowSheet, row, 7)); flow.setFormula(config.getString(flowSheet, row, 8)); flow.setLocation(getLocation(row)); } private void createPropertyFactors(int row, Flow flow, List<Factor> factors) { String refProperty = config.getString(flowSheet, row, 10); RefData refData = config.refData; for (Factor factor : factors) { FlowProperty property = refData.getFlowProperty(factor.property); if (property == null) { log.error("could not find flow property {} of flow property " + "factor ", factor.property); continue; } FlowPropertyFactor f = new FlowPropertyFactor(); f.setFlowProperty(property); f.setConversionFactor(factor.factor); flow.getFlowPropertyFactors().add(f); if (Objects.equals(refProperty, property.getName())) { flow.setReferenceFlowProperty(property); } } } private Location getLocation(int row) { String code = config.getString(flowSheet, row, 9); if (Strings.isNullOrEmpty(code)) { return null; } else { return config.refData.getLocation(code); } } private FlowType getType(int row) { String t = config.getString(flowSheet, row, 6); if (Strings.isNullOrEmpty(t)) { return FlowType.ELEMENTARY_FLOW; } t = t.toLowerCase().trim(); switch (t) { case "elementary flow": return FlowType.ELEMENTARY_FLOW; case "product flow": return FlowType.PRODUCT_FLOW; case "waste flow": return FlowType.WASTE_FLOW; default: log.warn("unknown flow type {}", t); return FlowType.ELEMENTARY_FLOW; } } private String key(String name, String category) { return category == null ? name : name + category; } private class Factor { double factor; String property; String refUnit; Factor(int row) { property = config.getString(factorSheet, row, 2); factor = config.getDouble(factorSheet, row, 3); refUnit = config.getString(factorSheet, row, 4); } } }