All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openlca.io.ilcd.input.EpdImport Maven / Gradle / Ivy

There is a newer version: 2.2.1
Show newest version
package org.openlca.io.ilcd.input;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import org.openlca.core.model.*;
import org.openlca.ilcd.epd.EpdIndicatorResult;
import org.openlca.ilcd.processes.Process;
import org.openlca.ilcd.processes.epd.EpdValue;
import org.openlca.ilcd.util.Epds;
import org.openlca.ilcd.util.Processes;
import org.openlca.util.KeyGen;
import org.openlca.util.Lists;
import org.openlca.util.Strings;

public class EpdImport {

	private final Import imp;
	private final Process ds;
	private final List results;
	private final AtomicBoolean hasRefError;

	public EpdImport(Import imp, Process ds) {
		this.imp = imp;
		this.ds = ds;
		this.results = EpdIndicatorResult.allOf(ds);
		this.hasRefError = new AtomicBoolean(false);
	}

	public void run() {
		var id = Processes.getUUID(ds);
		var oEpd = imp.db().get(Epd.class, id);
		if (oEpd != null) {
			imp.log().skipped(oEpd);
			return;
		}

		oEpd = new Epd();
		oEpd.refId = id;
		oEpd.name = Strings.cut(
				Processes.getFullName(ds, imp.lang()), 2048);
		oEpd.category = imp.syncCategory(ds, ModelType.EPD);
		oEpd.tags = tags();
		Import.mapVersionInfo(ds, oEpd);
		mapEpdMetaData(oEpd);

		// declared product
		var refFlow = getRefFlow();
		if (refFlow != null) {
			oEpd.product = new EpdProduct();
			oEpd.product.flow = refFlow.flow;
			oEpd.product.property = refFlow.flowPropertyFactor != null
					? refFlow.flowPropertyFactor.flowProperty
					: null;
			oEpd.product.unit = refFlow.unit;
			oEpd.product.amount = refFlow.amount;
		}

		for (var scope : Scope.allOf(results)) {
			var suffix = scope.toString();

			var refId = KeyGen.get(id, suffix);
			var result = imp.db().get(Result.class, refId);
			if (result != null) {
				var module = EpdModule.of(scope.toString(), result);
				oEpd.modules.add(module);
				imp.log().skipped(result);
				continue;
			}

			result = new Result();
			result.refId = refId;
			result.tags = suffix;
			result.version = oEpd.version;
			result.lastChange = oEpd.lastChange;

			// result meta-data
			result.name = Strings.cut(
					Processes.getFullName(ds, imp.lang()),
					2044 - suffix.length()) + " - " + suffix;
			imp.log().info("import EPD result: " + result.name);
			result.category = imp.syncCategory(ds, ModelType.RESULT);

			if (refFlow != null) {
				var resultRef = refFlow.copy();
				result.referenceFlow = resultRef;
				result.flowResults.add(resultRef);
			}

			addResultsOf(scope, result);
			result = imp.insert(result);
			oEpd.modules.add(EpdModule.of(scope.toString(), result));
		}

		imp.insert(oEpd);
	}

	private void mapEpdMetaData(Epd oEpd) {
		var info = Processes.getDataSetInfo(ds);
		if (info != null) {
			oEpd.description = imp.str(info.getComment());
		}
		oEpd.verifier = verifier();
		oEpd.programOperator = operator();
		oEpd.manufacturer = manufacturer();
		oEpd.pcr = pcr();

		// EPD type
		var iType = Epds.getSubType(ds);
		if (iType != null) {
			oEpd.epdType = switch (iType) {
				case AVERAGE_DATASET -> EpdType.AVERAGE_DATASET;
				case GENERIC_DATASET -> EpdType.GENERIC_DATASET;
				case SPECIFIC_DATASET -> EpdType.SPECIFIC_DATASET;
				case TEMPLATE_DATASET -> EpdType.TEMPLATE_DATASET;
				case REPRESENTATIVE_DATASET -> EpdType.REPRESENTATIVE_DATASET;
			};
		}

		// time
		var iTime = Epds.getTime(ds);
		var pubDate = Epds.getPublicationDate(ds);
		oEpd.validFrom = pubDate != null
				? pubDate.toGregorianCalendar().getTime()
				: ProcessTime.validFrom(iTime).orElse(null);
		oEpd.validUntil = ProcessTime.validUntil(iTime).orElse(null);

		// tech. description
		var iTech = Epds.getTechnology(ds);
		if (iTech != null) {
			oEpd.productUsage = imp.str(iTech.getApplicability());
			oEpd.manufacturing = imp.str(iTech.getDescription());
		}

		// location
		var iLoc = Epds.getLocation(ds);
		if (iLoc != null) {
			oEpd.location = imp.cache.locationOf(iLoc.getCode());
		}

		// use advice & original EPD
		var iRepr = Epds.getRepresentativeness(ds);
		if (iRepr != null) {
			oEpd.useAdvice = imp.str(iRepr.getUseAdvice());

			var ext = iRepr.getEpdExtension();
			if (ext != null) {
				Lists.first(ext.getOriginalEpds()).ifPresent(ref ->
						oEpd.originalEpd = SourceImport.get(imp, ref.getUUID())
				);
			}
		}

		// registration ID
		var iPub = Epds.getPublication(ds);
		if (iPub != null) {
			oEpd.registrationId = iPub.getRegistrationNumber();
		}

		// data generator
		var iGen = Epds.getDataGenerator(ds);
		if (iGen != null) {
			Lists.first(iGen.getContacts()).ifPresent(ref ->
					oEpd.dataGenerator = ContactImport.get(imp, ref.getUUID()));
		}
	}

	private FlowResult getRefFlow() {
		var qRef = Processes.getQuantitativeReference(ds);
		if (qRef == null || qRef.getReferenceFlows().isEmpty())
			return null;

		var exchange = ds.getExchanges().stream()
				.filter(e -> qRef.getReferenceFlows().contains(e.getId()))
				.findAny()
				.orElse(null);
		if (exchange == null || exchange.getFlow() == null)
			return null;

		var flowId = exchange.getFlow().getUUID();
		var f = FlowImport.get(imp, flowId);
		if (f.isEmpty()) {
			if (!hasRefError.get()) {
				hasRefError.set(true);
				imp.log().error("EPD " + Processes.getUUID(ds)
						+ " has invalid references; e.g. flow: " + flowId);
			}
			return null;
		}

		var ref = new FlowResult();
		ref.flow = f.flow();
		ref.isInput = f.flow().flowType == FlowType.WASTE_FLOW;
		ref.flowPropertyFactor = f.property();
		ref.unit = f.unit();

		double amount = exchange.getResultingAmount() != null
				? exchange.getResultingAmount()
				: exchange.getMeanAmount();
		if (f.isMapped() && f.mapFactor() != 0) {
			amount *= f.mapFactor();
		}
		ref.amount = amount;

		return ref;
	}

	private void addResultsOf(Scope scope, Result result) {
		for (var r : results) {
			if (r.indicator() == null)
				continue;
			var v = scope.valueOf(r);
			if (v == null || v.getAmount() == null)
				continue;
			var impact = imp.resolveIndicatorOf(r);
			if (impact == null)
				continue;
			var ir = new ImpactResult();
			ir.indicator = impact;
			ir.amount = v.getAmount();
			result.impactResults.add(ir);
		}
	}

	private Actor operator() {
		var pub = Processes.getPublication(ds);
		if (pub == null || pub.getRegistrationAuthority() == null)
			return null;
		var id = pub.getRegistrationAuthority().getUUID();
		return ContactImport.get(imp, id);
	}

	private Actor manufacturer() {
		var pub = Processes.getPublication(ds);
		if (pub == null || pub.getOwner() == null)
			return null;
		var id = pub.getOwner().getUUID();
		return ContactImport.get(imp, id);
	}

	private Actor verifier() {
		var v = Processes.getValidation(ds);
		if (v == null)
			return null;
		var review = Lists.first(v.getReviews()).orElse(null);
		if (review == null)
			return null;
		var ref = Lists.first(review.getReviewers()).orElse(null);
		if (ref == null)
			return null;
		return ContactImport.get(imp, ref.getUUID());
	}

	private Source pcr() {
		var m = Epds.getInventoryMethod(ds);
		if (m == null)
			return null;
		var ref = Lists.first(m.getSources()).orElse(null);
		if (ref == null)
			return null;
		return SourceImport.get(imp, ref.getUUID());
	}

	private String tags() {
		var decls = Processes.getComplianceDeclarations(ds);
		if (Lists.isEmpty(decls))
			return null;
		var tags = new StringBuilder();
		for (var decl : decls) {
			if (decl.getSystem() == null)
				continue;
			var sys = imp.str(decl.getSystem().getName());
			if (Strings.nullOrEmpty(sys))
				continue;
			if (!tags.isEmpty()) {
				tags.append(',');
			}
			tags.append(sys);
		}
		return tags.isEmpty() ? null : tags.toString();
	}

	private record Scope(String module, String scenario) {

		static Set allOf(List results) {
			var scopes = new HashSet();
			for (var result : results) {
				for (var v : result.values()) {
					if (Strings.nullOrEmpty(v.getModule()))
						continue;
					scopes.add(new Scope(v.getModule(), v.getScenario()));
				}
			}
			return scopes;
		}

		EpdValue valueOf(EpdIndicatorResult result) {
			if (result == null)
				return null;
			for (var a : result.values()) {
				if (Objects.equals(a.getModule(), module)
						&& Objects.equals(a.getScenario(), scenario)) {
					return a;
				}
			}
			return null;
		}

		@Override
		public String toString() {
			if (module == null)
				return "";
			return scenario != null
					? module + " - " + scenario
					: module;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy