package org.openlca.io.xls.process.output; import org.apache.poi.ss.usermodel.Sheet; import org.openlca.core.model.AllocationFactor; import org.openlca.core.model.AllocationMethod; import org.openlca.core.model.Exchange; import org.openlca.core.model.FlowType; import org.openlca.io.CategoryPath; import org.openlca.io.xls.Excel; import org.openlca.util.Strings; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Objects; class AllocationSheet { private Config config; private Sheet sheet; private int row = 0; private AllocationSheet(Config config) { this.config = config; sheet = config.workbook.createSheet("Allocation"); } public static void write(Config config) { new AllocationSheet(config).write(); } private void write() { config.pair(sheet, row++, "Default allocation method", getAllocationMethod()); List<Exchange> outputs = getProducts(); writeFactorSection(outputs); row += 2; writeCausalFactorSection(outputs); Excel.autoSize(sheet, 0, 3); } private String getAllocationMethod() { AllocationMethod method = config.process.getDefaultAllocationMethod(); if (method == null) return "none"; switch (method) { case CAUSAL: return "causal"; case ECONOMIC: return "economic"; case PHYSICAL: return "physical"; default: return "none"; } } private void writeFactorSection(List<Exchange> outputs) { row++; config.header(sheet, row++, 0, "Physical & economic allocation"); config.header(sheet, row, 0, "Product"); config.header(sheet, row, 1, "Category"); config.header(sheet, row, 2, "Physical"); config.header(sheet, row, 3, "Economic"); for (Exchange product : outputs) { row++; writeFactors(product); } } private void writeFactors(Exchange product) { Excel.cell(sheet, row, 0, product.getFlow().getName()); Excel.cell(sheet, row, 1, CategoryPath.getFull( product.getFlow().getCategory())); Excel.cell(sheet, row, 2, getFactor(product, AllocationMethod.PHYSICAL)); Excel.cell(sheet, row, 3, getFactor(product, AllocationMethod.ECONOMIC)); } private void writeCausalFactorSection(List<Exchange> outputs) { row++; config.header(sheet, row++, 0, "Causal allocation"); config.header(sheet, row, 0, "Flow"); config.header(sheet, row, 1, "Category"); config.header(sheet, row, 2, "Direction"); config.header(sheet, row, 3, "Amount"); for (int i = 0; i < outputs.size(); i++) config.header(sheet, row, 4 + i, outputs.get(i).getFlow().getName()); for (Exchange flow : getNonProducts()) { row++; writeCausalRowInfo(flow); for (int i = 0; i < outputs.size(); i++) { Exchange product = outputs.get(i); Excel.cell(sheet, row, 4 + i, getCausalFactor(product, flow)); } } } private void writeCausalRowInfo(Exchange e) { if(e.getFlow() == null) return; Excel.cell(sheet, row, 0, e.getFlow().getName()); Excel.cell(sheet, row, 1, CategoryPath.getFull(e.getFlow().getCategory())); String direction = e.isInput() ? "Input" : "Output"; Excel.cell(sheet, row, 2, direction); String amount = Double.toString(e.getAmountValue()); if(e.getUnit() != null) amount += " " + e.getUnit().getName(); Excel.cell(sheet, row, 3, amount); } private List<Exchange> getProducts() { List<Exchange> outputs = new ArrayList<>(); for (Exchange exchange : config.process.getExchanges()) { if (isOutputProduct(exchange)) outputs.add(exchange); } Collections.sort(outputs, new ExchangeSorter()); return outputs; } private List<Exchange> getNonProducts() { List<Exchange> exchanges = new ArrayList<>(); for (Exchange exchange : config.process.getExchanges()) { if (!isOutputProduct(exchange)) exchanges.add(exchange); } Collections.sort(exchanges, new ExchangeSorter()); return exchanges; } private boolean isOutputProduct(Exchange exchange) { return exchange != null && exchange.getFlow() != null && !exchange.isInput() && !exchange.isAvoidedProduct() && exchange.getFlow().getFlowType() == FlowType.PRODUCT_FLOW; } private double getFactor(Exchange product, AllocationMethod method) { for (AllocationFactor factor : config.process.getAllocationFactors()) { if (method == factor.getAllocationType() && factor.getProductId() == product.getFlow().getId()) return factor.getValue(); } return 1.0; } private double getCausalFactor(Exchange product, Exchange flow) { for (AllocationFactor factor : config.process.getAllocationFactors()) { if (factor.getAllocationType() != AllocationMethod.CAUSAL) continue; if (factor.getProductId() == product.getFlow().getId() && Objects.equals(factor.getExchange(), flow)) return factor.getValue(); } return 1.0; } private class ExchangeSorter implements Comparator<Exchange> { @Override public int compare(Exchange e1, Exchange e2) { return Strings.compare( e1.getFlow().getName(), e2.getFlow().getName()); } } }