package org.openlca.io.ecospold2.output;
import org.openlca.core.database.IDatabase;
import org.openlca.core.model.Exchange;
import org.openlca.io.maps.Maps;
import org.openlca.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.ParseDouble;
import org.supercsv.cellprocessor.ift.CellProcessor;
import spold2.Compartment;
import spold2.ElementaryExchange;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
class ElemFlowMap {
private Logger log = LoggerFactory.getLogger(getClass());
private final HashMap<String, ExportRecord> map = new HashMap<>();
public ElemFlowMap(IDatabase database) {
initMap(database);
}
private void initMap(IDatabase database) {
try {
CellProcessor[] processors = getCellProcessors();
List<List<Object>> rows = Maps.readAll(Maps.ES2_FLOW_EXPORT,
database, processors);
for (List<Object> row : rows) {
String refId = Maps.getString(row, 0);
ExportRecord record = createRecord(row);
map.put(refId, record);
}
} catch (Exception e) {
log.error("failed to initialize flow export map", e);
}
}
private CellProcessor[] getCellProcessors() {
CellProcessor string = null;
CellProcessor optional = new Optional();
CellProcessor number = new ParseDouble();
//@formatter:off
return new CellProcessor[]{
string, // 0: openLCA ID
optional, // 1: openLCA name
string, // 2: openLCA property ID
optional, // 3: openLCA property name
string, // 4: openLCA unit ID
optional, // 5: openLCA unit name
string, // 6: ecoinvent ID
string, // 7: ecoinvent name
string, // 8: ecoinvent unit ID
string, // 9: ecoinvent unit name
string, // 10: ecoinvent sub-compartment ID
string, // 11: ecoinvent compartment name
string, // 12: ecoinvent sub-compartment name
number // 13: conversion factor
};
//@formatter:on
}
private ExportRecord createRecord(List<Object> row) {
ExportRecord record = new ExportRecord();
record.olcaPropertyId = Maps.getString(row, 2);
record.olcaUnitId = Maps.getString(row, 4);
record.id = Maps.getString(row, 6);
record.name = Maps.getString(row, 7);
record.unitId = Maps.getString(row, 8);
record.unitName = Maps.getString(row, 9);
record.subCompartmentId = Maps.getString(row, 10);
record.compartment = Maps.getString(row, 11);
record.subCompartment = Maps.getString(row, 12);
record.conversionFactor = Maps.getDouble(row, 13);
return record;
}
public ElementaryExchange apply(Exchange olca) {
if (olca == null || olca.getFlow() == null) {
log.warn("could not map exchange {}, exchange or flow is null",
olca);
return null;
}
ExportRecord record = map.get(olca.getFlow().getRefId());
if (record == null || !isValid(record, olca)) {
log.warn(
"elementary flow {} cannot be mapped to an ecoinvent flow",
olca.getFlow());
return null;
}
return createExchange(olca, record);
}
private boolean isValid(ExportRecord record, Exchange olca) {
return record != null
&& olca != null
&& olca.getFlowPropertyFactor() != null
&& olca.getFlowPropertyFactor().getFlowProperty() != null
&& Objects.equals(record.olcaPropertyId, olca
.getFlowPropertyFactor().getFlowProperty().getRefId())
&& olca.getUnit() != null
&& Objects.equals(record.olcaUnitId, olca.getUnit().getRefId());
}
private ElementaryExchange createExchange(Exchange olca, ExportRecord record) {
ElementaryExchange exchange = new ElementaryExchange();
if (olca.isInput())
exchange.inputGroup = 4;
else
exchange.outputGroup = 4;
exchange.id = new UUID(olca.getId(), 0L).toString();
exchange.flowId = record.id;
exchange.name = Strings.cut(record.name, 120);
exchange.compartment = createCompartment(record);
exchange.unit = record.unitName;
exchange.unitId = record.unitId;
exchange.amount = record.conversionFactor * olca.getAmountValue();
if (olca.getAmountFormula() != null) {
exchange.mathematicalRelation = record.conversionFactor + " * ("
+ olca.getAmountFormula() + ")";
}
// TODO: convert uncertainty information
return exchange;
}
private Compartment createCompartment(ExportRecord record) {
Compartment compartment = new Compartment();
compartment.id = record.subCompartmentId;
compartment.compartment = record.compartment;
compartment.subCompartment = record.subCompartment;
return compartment;
}
private class ExportRecord {
String id;
String name;
String unitId;
String unitName;
String subCompartmentId;
String subCompartment;
String compartment;
String olcaPropertyId;
String olcaUnitId;
double conversionFactor;
}
}