package org.openlca.io.ilcd.input;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.openlca.core.database.ProductSystemDao;
import org.openlca.core.model.Category;
import org.openlca.core.model.Exchange;
import org.openlca.core.model.Flow;
import org.openlca.core.model.FlowProperty;
import org.openlca.core.model.ModelType;
import org.openlca.core.model.Process;
import org.openlca.core.model.ProcessLink;
import org.openlca.core.model.ProductSystem;
import org.openlca.core.model.Unit;
import org.openlca.core.model.UnitGroup;
import org.openlca.ilcd.productmodel.Connector;
import org.openlca.ilcd.productmodel.ConsumedBy;
import org.openlca.ilcd.productmodel.Parameter;
import org.openlca.ilcd.productmodel.ProcessNode;
import org.openlca.ilcd.productmodel.Product;
import org.openlca.ilcd.productmodel.ProductModel;
import org.openlca.ilcd.util.ProcessBag;
import org.openlca.ilcd.util.ProcessInfoExtension;
public class SystemImport {
private final ImportConfig config;
private ProcessBag ilcdProcessBag;
private ProductSystem system;
public SystemImport(ImportConfig config) {
this.config = config;
}
public ProductSystem run(org.openlca.ilcd.processes.Process ilcdProcess)
throws ImportException {
ilcdProcessBag = new ProcessBag(ilcdProcess, config.langs);
if (!ilcdProcessBag.hasProductModel())
return null;
ProductSystem system = findExisting(ilcdProcessBag.getId());
if (system != null)
return system;
return createNew();
}
private ProductSystem findExisting(String systemId) throws ImportException {
try {
ProductSystemDao dao = new ProductSystemDao(config.db);
return dao.getForRefId(systemId);
} catch (Exception e) {
throw new ImportException("Could not load product system id="
+ systemId, e);
}
}
private ProductSystem createNew() throws ImportException {
system = new ProductSystem();
ProductModel model = ilcdProcessBag.getProductModel();
system.setRefId(ilcdProcessBag.getId());
system.setName(model.getName());
importAndSetCategory();
mapContent();
try {
config.db.createDao(ProductSystem.class).insert(system);
return system;
} catch (Exception e) {
throw new ImportException("Failed to save in database", e);
}
}
private void importAndSetCategory() throws ImportException {
CategoryImport categoryImport = new CategoryImport(config,
ModelType.PRODUCT_SYSTEM);
Category category = categoryImport.run(ilcdProcessBag
.getSortedClasses());
system.setCategory(category);
}
private void mapContent() throws ImportException {
Map<String, Process> processes = addProcesses();
setRefProcess(processes);
addProcessLinks(processes);
addParameters();
}
private Map<String, Process> addProcesses() throws ImportException {
HashMap<String, Process> result = new HashMap<>();
ProductModel model = ilcdProcessBag.getProductModel();
for (ProcessNode node : model.getNodes()) {
String processId = node.getUuid();
ProcessImport processImport = new ProcessImport(config);
Process p = processImport.run(processId);
if (p != null) {
result.put(processId, p);
system.getProcesses().add(p.getId());
}
}
return result;
}
private void setRefProcess(Map<String, Process> processes)
throws ImportException {
String refProcessId = new ProcessInfoExtension(ilcdProcessBag
.getValue().processInfo).getModelRefProcess();
Process refProc = processes.get(refProcessId);
system.setReferenceProcess(refProc);
org.openlca.ilcd.processes.Exchange iExchange = ilcdProcessBag
.getExchanges().get(0);
String flowId = iExchange.flow.uuid;
Exchange refExchange = findRefExchange(refProc, flowId, false);
system.setReferenceExchange(refExchange);
system.setTargetAmount(iExchange.resultingAmount);
Flow flow = refExchange.getFlow();
system.setTargetFlowPropertyFactor(flow.getReferenceFactor());
system.setTargetUnit(getRefUnit(flow.getReferenceFlowProperty()));
}
private Exchange findRefExchange(Process refProc, String flowId,
boolean input) {
for (Exchange exchange : refProc.getExchanges()) {
if (exchange.getFlow() == null || exchange.isInput() != input)
continue;
if (Objects.equals(exchange.getFlow().getRefId(), flowId))
return exchange;
}
return null;
}
private Unit getRefUnit(FlowProperty prop) throws ImportException {
try {
UnitGroup group = prop.getUnitGroup();
return group.getReferenceUnit();
} catch (Exception e) {
throw new ImportException("Could not load ref-unit of property "
+ prop, e);
}
}
private void addProcessLinks(Map<String, Process> processes) {
ProductModel model = ilcdProcessBag.getProductModel();
for (Connector con : model.getConnections()) {
ProcessLink link = new ProcessLink();
// provider process
Process provider = processes.get(con.getOrigin());
if (provider == null)
continue;
link.providerId = provider.getId();
// provider output flow
Product product = con.getProducts().get(0);
String flowId = product.getUuid();
Exchange output = findExchange(provider, flowId, false);
if (output == null)
continue;
link.flowId = output.getFlow().getId();
// linked exchange
ConsumedBy consumedBy = product.getConsumedBy();
Process recipient = processes.get(consumedBy.getProcessId());
if (recipient == null)
continue;
link.processId = recipient.getId();
Exchange input = findExchange(recipient, flowId, true);
if (input == null)
continue;
link.exchangeId = input.getId();
system.getProcessLinks().add(link);
}
}
private Exchange findExchange(Process p, String flowRefId, boolean input) {
if (p == null || flowRefId == null)
return null;
for (Exchange e : p.getExchanges()) {
if (e.getFlow() == null || e.isInput() != input)
continue;
if (Objects.equals(e.getFlow().getRefId(), flowRefId))
return e;
}
return null;
}
private void addParameters() {
for (Parameter iParam : ilcdProcessBag.getProductModel()
.getParameters()) {
if (!valid(iParam))
continue;
// TODO: parameter handling
// org.openlca.core.model.Parameter oParam = convert(iParam);
// addOrInsert(oParam);
}
}
private boolean valid(Parameter iParam) {
return iParam.getFormula() != null && iParam.getValue() != null
&& iParam.getName() != null && iParam.getScope() != null;
}
// private ParameterRedef convert(Parameter iParam) {
// ParameterRedef redef = new ParameterRedef();
// redef.setName(iParam.getName());
// redef.setValue(iParam.getValue());
// return redef;
// }
// private void addOrInsert(org.openlca.core.model.Parameter param) {
// if (param.getScope() == ParameterScope.PRODUCT_SYSTEM) {
// system.getParameters().add(param);
// return;
// }
// try {
// ParameterDao dao = new ParameterDao(database);
// List<org.openlca.core.model.Parameter> params = dao.getAllForName(
// param.getName(), param.getScope());
// if (params.isEmpty())
// dao.insert(param);
// } catch (Exception e) {
// log.error("Failed to store parameter in database", e);
// }
// }
}