package org.openlca.io.simapro.csv.input;
import org.openlca.core.database.IDatabase;
import org.openlca.core.database.ParameterDao;
import org.openlca.core.model.Parameter;
import org.openlca.core.model.ParameterScope;
import org.openlca.core.model.Process;
import org.openlca.expressions.FormulaInterpreter;
import org.openlca.expressions.Scope;
import org.openlca.simapro.csv.model.CalculatedParameterRow;
import org.openlca.simapro.csv.model.InputParameterRow;
import org.openlca.simapro.csv.model.process.ProcessBlock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class ProcessParameterMapper {
private Logger log = LoggerFactory.getLogger(getClass());
private final ParameterDao dao;
private final FormulaInterpreter interpreter;
private Process process;
private long nextScope = 0;
public ProcessParameterMapper(IDatabase database) {
this.dao = new ParameterDao(database);
this.interpreter = initInterpreter(dao);
}
private FormulaInterpreter initInterpreter(ParameterDao dao) {
FormulaInterpreter interpreter = new FormulaInterpreter();
for (Parameter parameter : dao.getGlobalParameters()) {
interpreter.bind(parameter.getName(),
Double.toString(parameter.getValue()));
}
return interpreter;
}
/**
* Maps the parameter of the SimaPro process to the given openLCA process
* and creates an interpreter scope for this process. The parameters of the
* process are bound to this scope and can be used in evaluations later.
*/
public long map(ProcessBlock block, Process process) {
this.process = process;
long scopeId = ++nextScope;
Scope scope = interpreter.createScope(scopeId);
for (InputParameterRow row : block.getInputParameters()) {
Parameter parameter = create(row);
String val = Double.toString(parameter.getValue());
scope.bind(parameter.getName(), val);
}
for (CalculatedParameterRow row : block.getCalculatedParameters()) {
Parameter parameter = create(row);
scope.bind(parameter.getName(), parameter.getFormula());
}
evalProcessParameters(scopeId);
this.process = null;
return scopeId;
}
private Parameter create(InputParameterRow row) {
Parameter parameter = new Parameter();
parameter.setName(row.getName());
parameter.setInputParameter(true);
parameter.setScope(ParameterScope.PROCESS);
parameter.setValue(row.getValue());
parameter.setUncertainty(Uncertainties.get(row.getValue(),
row.getUncertainty()));
parameter.setDescription(row.getComment());
process.getParameters().add(parameter);
return parameter;
}
private Parameter create(CalculatedParameterRow row) {
Parameter parameter = new Parameter();
parameter.setName(row.getName());
parameter.setInputParameter(false);
parameter.setScope(ParameterScope.PROCESS);
parameter.setFormula(row.getExpression());
parameter.setDescription(row.getComment());
process.getParameters().add(parameter);
return parameter;
}
private void evalProcessParameters(long scopeId) {
Scope scope = interpreter.getScope(scopeId);
for (Parameter param : process.getParameters()) {
if (param.isInputParameter())
continue;
try {
double val = scope.eval(param.getName());
param.setValue(val);
} catch (Exception e) {
log.error("failed to evaluate process parameter " + param
+ "; set it as an input parameter with value 1", e);
param.setFormula(null);
param.setValue(1);
param.setInputParameter(true);
scope.bind(param.getName(), "1");
}
}
}
public double eval(String formula, long scopeId) {
try {
Scope scope = interpreter.getScope(scopeId);
return scope.eval(formula);
} catch (Exception e) {
log.error("failed to evaluate formula " + formula
+ "; set value to NaN", e);
return Double.NaN;
}
}
}