package org.openlca.io.ilcd.input; import java.util.List; import java.util.UUID; import javax.xml.namespace.QName; import org.apache.commons.lang3.StringUtils; import org.openlca.core.database.FlowDao; import org.openlca.core.database.ImpactCategoryDao; import org.openlca.core.database.ImpactMethodDao; import org.openlca.core.model.Flow; import org.openlca.core.model.FlowProperty; import org.openlca.core.model.ImpactCategory; import org.openlca.core.model.ImpactFactor; import org.openlca.core.model.ImpactMethod; import org.openlca.core.model.Unit; import org.openlca.core.model.UnitGroup; import org.openlca.ilcd.commons.LangString; import org.openlca.ilcd.methods.DataSetInfo; import org.openlca.ilcd.methods.Factor; import org.openlca.ilcd.methods.FactorList; import org.openlca.ilcd.methods.LCIAMethod; import org.openlca.ilcd.methods.MethodInfo; import org.openlca.ilcd.methods.QuantitativeReference; import org.openlca.io.maps.FlowMapEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Imports an ILCD impact method data set. Note that the ILCD data sets contain * impact categories and not methods. Thus, this import searches for matching * impact methods and appends the ILCD data set as impact category to these * methods. */ public class MethodImport { private Logger log = LoggerFactory.getLogger(getClass()); private final ImportConfig config; private ImpactMethodDao dao; public MethodImport(ImportConfig config) { this.config = config; this.dao = new ImpactMethodDao(config.db); } public void run(LCIAMethod iMethod) { if (iMethod == null) return; if (exists(iMethod)) return; String categoryName = getCategoryName(iMethod); if (categoryName == null) return; for (ImpactMethod oMethod : MethodFetch.getOrCreate(iMethod, config)) { if (!hasCategory(oMethod, categoryName)) addCategory(oMethod, categoryName, iMethod); } } private boolean exists(LCIAMethod iMethod) { String uuid = getUUID(iMethod); if (uuid == null) return false; try { ImpactCategoryDao dao = new ImpactCategoryDao(config.db); ImpactCategory category = dao.getForRefId(uuid); if (category != null) { log.info("LCIA category {} not imported because it " + "already exists in the database", uuid); return true; } log.trace("import LCIA category {}", uuid); return false; } catch (Exception e) { log.error("failed to check if LCIA category exists " + uuid, e); return false; } } private String getCategoryName(LCIAMethod iMethod) { MethodInfo info = iMethod.methodInfo; if (info == null || info.dataSetInfo == null) return null; DataSetInfo dataInfo = info.dataSetInfo; List<String> categoryNames = dataInfo.impactCategories; if (categoryNames == null || categoryNames.isEmpty()) return null; return categoryNames.get(0); } private boolean hasCategory(org.openlca.core.model.ImpactMethod oMethod, String categoryName) { for (ImpactCategory category : oMethod.getImpactCategories()) { if (StringUtils.equalsIgnoreCase(category.getName(), categoryName)) return true; } return false; } private void addCategory(org.openlca.core.model.ImpactMethod oMethod, String categoryName, LCIAMethod iMethod) { log.trace("Add category {} to {}", categoryName, oMethod); String categoryUnit = getCategoryUnit(iMethod); ImpactCategory category = new ImpactCategory(); String refId = getUUID(iMethod); category.setRefId(refId != null ? refId : UUID.randomUUID().toString()); category.setName(categoryName); category.setReferenceUnit(categoryUnit); category.setDescription(getCategoryDescription(iMethod)); addFactors(iMethod, category); oMethod.getImpactCategories().add(category); dao.update(oMethod); } private String getUUID(LCIAMethod iMethod) { MethodInfo info = iMethod.methodInfo; if (info == null || info.dataSetInfo == null) return null; DataSetInfo dataInfo = info.dataSetInfo; return dataInfo.uuid; } private String getCategoryUnit(LCIAMethod iMethod) { String extensionUnit = getExtentionUnit(iMethod); if (extensionUnit != null) return extensionUnit; MethodInfo info = iMethod.methodInfo; if (info == null || info.quantitativeReference == null) return null; QuantitativeReference qRef = info.quantitativeReference; if (qRef.quantity == null) return null; String propertyId = qRef.quantity.uuid; if (propertyId == null) return null; Unit unit = getReferenceUnit(propertyId); return unit == null ? null : unit.getName(); } private String getExtentionUnit(LCIAMethod iMethod) { MethodInfo info = iMethod.methodInfo; if (info == null || info.dataSetInfo == null) return null; DataSetInfo dataInfo = info.dataSetInfo; QName extName = new QName("http://openlca.org/ilcd-extensions", "olca_category_unit"); return dataInfo.otherAttributes.get(extName); } private String getCategoryDescription(LCIAMethod iMethod) { MethodInfo info = iMethod.methodInfo; if (info == null || info.dataSetInfo == null) return null; return LangString.getFirst(info.dataSetInfo.comment, config.langs); } private Unit getReferenceUnit(String propertyId) { try { FlowPropertyImport propertyImport = new FlowPropertyImport(config); FlowProperty prop = propertyImport.run(propertyId); if (prop == null) return null; return getReferenceUnit(prop); } catch (Exception e) { return null; } } private Unit getReferenceUnit(FlowProperty prop) { UnitGroup group = prop.getUnitGroup(); if (group != null && group.getReferenceUnit() != null) return group.getReferenceUnit(); return null; } private void addFactors(LCIAMethod iMethod, ImpactCategory category) { FactorList list = iMethod.characterisationFactors; if (list == null) return; for (Factor factor : list.factors) { try { addFactor(category, factor); } catch (Exception e) { log.warn("Failed to add factor " + factor, e); } } } private void addFactor(ImpactCategory category, Factor factor) throws Exception { String flowId = factor.flow.uuid; Flow flow = getFlow(flowId); if (flow == null) { log.warn("Could not import flow {}", flowId); return; } ImpactFactor oFactor = new ImpactFactor(); oFactor.setFlow(flow); oFactor.setFlowPropertyFactor(flow.getReferenceFactor()); oFactor.setUnit(getRefUnit(flow)); oFactor.setValue(factor.meanValue); category.getImpactFactors().add(oFactor); } private Flow getFlow(String flowId) throws Exception { Flow flow = getMappedFlow(flowId); if (flow != null) return flow; return new FlowImport(config).run(flowId); } private Flow getMappedFlow(String flowId) { FlowMapEntry entry = config.flowMap.getEntry(flowId); if (entry == null) return null; FlowDao dao = new FlowDao(config.db); return dao.getForRefId(entry.getOpenlcaFlowKey()); } private Unit getRefUnit(Flow flow) { if (flow == null) return null; FlowProperty prop = flow.getReferenceFlowProperty(); return getReferenceUnit(prop); } }