use of org.openlca.core.model.Flow in project olca-app by GreenDelta.
the class DBProvider method sync.
/**
* Sync the flow references with the respective flow in the database (when
* it exists). It tests that the definition of the flow reference can be
* fulfilled with a database flow (i.e. the ref-IDs match and the flow
* property and unit is defined for that flow). If this is not the case it
* returns it sets an error state to the given reference. Otherwise, it will
* mutate the flow reference to have the respective database IDs of the
* corresponding flow and sets the property and unit to the respective
* defaults if they are missing. Also, it will return the matching flow in
* case there was no error (otherwise null).
*/
public Flow sync(FlowRef ref) {
if (Sync.isInvalidFlowRef(ref))
return null;
// we update the status in the following sync. steps
ref.status = null;
// check the flow
Flow flow = new FlowDao(db).getForRefId(ref.flow.refId);
if (flow == null) {
ref.status = MappingStatus.error("there is no flow with id=" + ref.flow.refId + " in the database");
return null;
}
// check the flow property
FlowProperty prop = null;
if (ref.property == null) {
prop = flow.referenceFlowProperty;
} else {
for (FlowPropertyFactor f : flow.flowPropertyFactors) {
if (f.flowProperty == null)
continue;
if (Objects.equals(ref.property.refId, f.flowProperty.refId)) {
prop = f.flowProperty;
break;
}
}
}
if (prop == null || prop.unitGroup == null) {
ref.status = MappingStatus.error("the flow in the database has" + " no corresponding flow property");
return null;
}
// check the unit
Unit u = null;
if (ref.unit == null) {
u = prop.unitGroup.referenceUnit;
} else {
for (Unit ui : prop.unitGroup.units) {
if (Objects.equals(ref.unit.refId, ui.refId)) {
u = ui;
break;
}
}
}
if (u == null) {
ref.status = MappingStatus.error("the flow in the database has" + " no corresponding unit");
return null;
}
// check a possible provider
Process provider = null;
if (ref.provider != null) {
provider = new ProcessDao(db).getForRefId(ref.provider.refId);
if (provider == null) {
ref.status = MappingStatus.error("the provider does not exist in the database");
return null;
}
boolean exists = provider.exchanges.stream().anyMatch(e -> !e.isAvoided && Objects.equals(e.flow, flow) && ((e.isInput && flow.flowType == FlowType.WASTE_FLOW) || (!e.isInput && flow.flowType == FlowType.PRODUCT_FLOW)));
if (!exists) {
ref.status = MappingStatus.error("the given provider does not deliver that flow");
return null;
}
}
// sync the reference data
if (ref.property == null) {
ref.property = Descriptor.of(prop);
}
if (ref.unit == null) {
ref.unit = Descriptor.of(u);
}
ref.flow.id = flow.id;
ref.property.id = prop.id;
ref.unit.id = u.id;
if (provider != null) {
ref.provider = Descriptor.of(provider);
}
Sync.checkFlowName(ref, flow.name);
Sync.checkFlowCategory(ref, String.join("/", Categories.path(flow.category)));
Sync.checkFlowType(ref, flow.flowType);
Sync.checkFlowLocation(ref, flow.location == null ? null : flow.location.code);
if (provider != null) {
Sync.checkProviderLocation(ref, provider.location == null ? null : provider.location.code);
}
if (ref.status == null) {
ref.status = MappingStatus.ok("flow in sync. with database");
}
return flow;
}
use of org.openlca.core.model.Flow in project olca-app by GreenDelta.
the class JsonProvider method persist.
@Override
public void persist(List<FlowRef> refs, IDatabase db) {
if (refs == null || db == null)
return;
try (ZipStore store = ZipStore.open(file)) {
FlowDao dao = new FlowDao(db);
JsonImport imp = new JsonImport(store, db);
for (FlowRef ref : refs) {
Flow flow = dao.getForRefId(ref.flow.refId);
if (flow != null)
continue;
imp.run(ModelType.FLOW, ref.flow.refId);
}
} catch (Exception e) {
Logger log = LoggerFactory.getLogger(getClass());
log.error("failed persist flows", e);
}
}
use of org.openlca.core.model.Flow in project olca-app by GreenDelta.
the class Replacer method run.
@Override
public void run() {
if (conf == null || (conf.models.isEmpty())) {
log.info("no configuration; nothing to replace");
return;
}
// collect the IDs of processes and LCIA categories
// where flows should be replaced
processes.clear();
impacts.clear();
for (var model : conf.models) {
if (model.type == ModelType.PROCESS) {
processes.add(model.id);
} else if (model.type == ModelType.IMPACT_METHOD) {
ImpactMethodDao dao = new ImpactMethodDao(db);
dao.getCategoryDescriptors(model.id).forEach(d -> impacts.add(d.id));
}
}
buildIndices();
if (entries.isEmpty()) {
log.info("found no flows that can be mapped");
return;
}
log.info("found {} flows that can be mapped", entries.size());
try {
// start and wait for the cursors to finish
log.info("start updatable cursors");
List<UpdatableCursor> cursors = createCursors();
ExecutorService pool = Executors.newFixedThreadPool(4);
for (UpdatableCursor c : cursors) {
pool.execute(c);
}
pool.shutdown();
int i = 0;
while (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
i++;
log.info("waiting for cursors to finish; {} seconds", i * 10);
}
log.info("cursors finished");
db.getEntityFactory().getCache().evictAll();
// TODO when products were replaced we also need to check
// whether these products are used in the quant. ref. of
// product systems and project variants and convert the
// amounts there.
// TODO also: we need to replace such flows in allocation
// factors; the application of the conversion factor is
// not required there.
// collect and log statistics
Stats stats = new Stats();
for (UpdatableCursor c : cursors) {
stats.add(c.stats);
c.stats.log(c.getClass().getName(), flows);
}
// TODO: update the version and last-update fields
// of the changed models; also call the indexer
// when the database is a connected repository
boolean deleteMapped = false;
Set<Long> usedFlows = null;
if (conf.deleteMapped) {
if (stats.failures > 0) {
log.warn("Will not delete mapped flows because" + " there were {} failures in replacement process", stats.failures);
} else {
deleteMapped = true;
usedFlows = new FlowDao(db).getUsed();
}
}
// update the mapping entries
for (Long flowID : entries.keySet()) {
FlowMapEntry e = entries.get(flowID);
if (flowID == null || e == null)
continue;
if (stats.hadFailures(flowID)) {
e.sourceFlow().status = MappingStatus.error("Replacement error");
continue;
}
if (deleteMapped && !usedFlows.contains(flowID)) {
FlowDao dao = new FlowDao(db);
Flow flow = dao.getForId(flowID);
dao.delete(flow);
log.info("removed mapped flow {} uuid={}", Labels.name(flow), flow.refId);
e.sourceFlow().status = MappingStatus.ok("Applied and removed");
} else {
e.sourceFlow().status = MappingStatus.ok("Applied (not removed)");
}
}
} catch (Exception e) {
log.error("Flow replacement failed", e);
}
}
use of org.openlca.core.model.Flow in project olca-app by GreenDelta.
the class Stats method log.
void log(String context, HashMap<Long, Flow> flows) {
Logger log = LoggerFactory.getLogger(getClass());
if (replacements == 0 && failures == 0) {
log.info("No flows replaced in {}", context);
return;
}
if (failures > 0) {
log.warn("There were failures while replacing flows in {}", context);
}
log.info("{} replacements and {} failures in {}", replacements, failures, context);
if (!log.isTraceEnabled())
return;
HashSet<Long> ids = new HashSet<>();
ids.addAll(flowFailures.keySet());
ids.addAll(flowReplacements.keySet());
for (Long id : ids) {
Flow flow = flows.get(id);
if (flow == null)
continue;
int rcount = flowReplacements.getOrDefault(id, 0);
int fcount = flowFailures.getOrDefault(id, 0);
if (rcount == 0 && fcount == 0)
continue;
log.trace("Flow {} uuid={} :: {} replacements, {} failures in {}", Labels.name(flow), flow.refId, rcount, fcount, context);
}
}
use of org.openlca.core.model.Flow in project olca-app by GreenDelta.
the class FactorClipboard method factor.
private ImpactFactor factor(String[] row) {
if (row.length < 4)
return null;
String name = row[0];
String category = row[1];
String amount = row[2];
String unit = row[3];
// filter the flows by matching names and categories
List<Flow> candidates = flows.stream().filter(d -> Strings.nullOrEqual(d.name, name)).map(d -> new FlowDao(db).getForId(d.id)).filter(flow -> {
if (flow.category == null)
return Strings.nullOrEmpty(category);
String path = CategoryPath.getFull(flow.category);
return Strings.nullOrEqual(path, category);
}).collect(Collectors.toList());
if (candidates.isEmpty())
return null;
// find a matching flow for the unit
// the unit in the table has the format:
// <LCIA ref. unit> / <flow unit>
// the following only works if the LCIA
// ref. unit does not contain a slash, but
// this should be very unlikely
int i = unit.indexOf('/');
if (i >= 0) {
unit = unit.substring(i + 1).trim();
}
ImpactFactor factor = new ImpactFactor();
for (Flow flow : candidates) {
for (FlowPropertyFactor p : flow.flowPropertyFactors) {
if (p.flowProperty == null || p.flowProperty.unitGroup == null)
continue;
Unit u = p.flowProperty.unitGroup.getUnit(unit);
if (u == null)
continue;
factor.flow = flow;
factor.flowPropertyFactor = p;
factor.unit = u;
if (Objects.equals(p.flowProperty, flow.referenceFlowProperty))
break;
}
if (factor.flow != null)
break;
}
if (factor.flow == null)
return null;
// set the amount value / formula
try {
factor.value = Double.parseDouble(amount);
} catch (Exception e) {
factor.formula = amount;
}
// uncertainty value
if (row.length > 4) {
factor.uncertainty = Uncertainty.fromString(row[4]);
}
// location
if (row.length > 5) {
String code = row[5];
if (!Strings.nullOrEmpty(code)) {
LocationDao dao = new LocationDao(db);
factor.location = dao.getDescriptors().stream().filter(d -> Strings.nullOrEqual(code, d.code)).map(d -> dao.getForId(d.id)).findFirst().orElse(null);
}
}
return factor;
}
Aggregations