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

org.openlca.io.ilcd.output.ProcessExport Maven / Gradle / Ivy

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

import java.util.Objects;

import org.openlca.core.model.Exchange;
import org.openlca.core.model.ProcessType;
import org.openlca.core.model.doc.ProcessDoc;
import org.openlca.ilcd.commons.*;
import org.openlca.ilcd.processes.ComplianceDeclaration;
import org.openlca.ilcd.processes.FlowCompletenessEntry;
import org.openlca.ilcd.processes.Process;
import org.openlca.ilcd.processes.Review;
import org.openlca.ilcd.processes.ReviewMethod;
import org.openlca.ilcd.processes.ReviewScope;
import org.openlca.ilcd.util.TimeExtension;
import org.openlca.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The export of an openLCA process to an ILCD process data set.
 */
public class ProcessExport {

	private final Logger log = LoggerFactory.getLogger(this.getClass());
	private final Export exp;
	private org.openlca.core.model.Process process;
	private ProcessDoc doc;

	public ProcessExport(Export exp) {
		this.exp = exp;
	}

	public void write(org.openlca.core.model.Process p) {
		if (p == null || exp.store.contains(Process.class, p.refId))
			return;
		log.trace("Run process export with {}", p);
		this.process = p;
		this.doc = p.documentation;

		var ds = new Process();
		mapDataSetInfo(ds);
		mapTime(ds);
		mapGeography(ds);
		mapTechnology(ds);
		mapInventoryMethod(ds);
		mapRepresentativeness(ds);
		mapReviews(ds);
		mapCompleteness(ds);
		mapComplianceSystems(ds);

		ds.withAdminInfo(new ProcessAdminInfo(exp).create(p));
		var params = new ProcessParameterConversion(exp).run(p);
		if (!params.isEmpty()) {
			ds.withProcessInfo()
					.withParameterModel()
					.withParameters()
					.addAll(params);
		}

		Exchange qRef = p.quantitativeReference;
		if (qRef != null) {
			ds.withProcessInfo()
					.withQuantitativeReference()
					.withType(QuantitativeReferenceType.REFERENCE_FLOWS)
					.withReferenceFlows()
					.add(qRef.internalId);
		}

		new ExchangeConversion(p, exp).run(ds);
		exp.store.put(ds);
	}

	private void mapDataSetInfo(Process ds) {
		var info = ds.withProcessInfo()
				.withDataSetInfo()
				.withUUID(process.refId);
		var name = info.withProcessName();
		exp.add(name::withBaseName, process.name);
		exp.add(info::withComment, process.description);
		Categories.toClassification(process.category, info::withClassifications);
	}

	private void mapTime(Process ds) {
		if (doc == null)
			return;
		var time = ds.withProcessInfo().withTime();
		var ext = new TimeExtension(time);
		if (doc.validFrom != null) {
			time.withReferenceYear(Export.getYear(doc.validFrom));
			ext.setStartDate(doc.validFrom);
		}
		if (doc.validUntil != null) {
			time.withValidUntil(Export.getYear(doc.validUntil));
			ext.setEndDate(doc.validUntil);
		}
		exp.add(time::withDescription, doc.time);
	}

	private void mapGeography(Process ds) {
		if (doc == null)
			return;
		if (process.location == null && doc.geography == null)
			return;
		var loc = ds.withProcessInfo()
				.withGeography()
				.withLocation();
		if (process.location != null) {
			var oLoc = process.location;
			loc.withCode(oLoc.code);
			// do not write (0.0, 0.0) locations; these are the default
			// location coordinates in openLCA but probably never a valid
			// process location, right?
			if (!(oLoc.latitude == 0.0 && oLoc.longitude == 0.0)) {
				loc.withLatitudeAndLongitude(oLoc.latitude + ";" + oLoc.longitude);
			}
		}
		exp.add(loc::withDescription, doc.geography);
	}

	private void mapTechnology(Process ds) {
		if (doc == null)
			return;
		if (Strings.notEmpty(doc.technology)) {
			var tech = ds.withProcessInfo().withTechnology();
			exp.add(tech::withDescription, doc.technology);
		}
	}

	private void mapInventoryMethod(Process ds) {
		var method = ds.withModelling().withInventoryMethod();
		if (process.processType != null) {
			method.withProcessType(
					process.processType == ProcessType.UNIT_PROCESS
							? org.openlca.ilcd.commons.ProcessType.UNIT_PROCESS_BLACK_BOX
							: org.openlca.ilcd.commons.ProcessType.LCI_RESULT);
		}
		method.withPrinciple(ModellingPrinciple.OTHER);
		if (doc != null) {
			exp.add(method::withPrincipleDeviations, doc.inventoryMethod);
			exp.add(method::withConstants, doc.modelingConstants);
		}
		var allocation = getAllocationMethod();
		if (allocation != null) {
			method.withApproaches().add(allocation);
		}
	}

	private ModellingApproach getAllocationMethod() {
		if (process.defaultAllocationMethod == null)
			return null;
		return switch (process.defaultAllocationMethod) {
			case CAUSAL -> ModellingApproach.ALLOCATION_OTHER_EXPLICIT_ASSIGNMENT;
			case ECONOMIC -> ModellingApproach.ALLOCATION_MARKET_VALUE;
			case PHYSICAL -> ModellingApproach.ALLOCATION_PHYSICAL_CAUSALITY;
			default -> null;
		};
	}

	private void mapRepresentativeness(Process ds) {
		if (doc == null)
			return;
		var rep = ds.withModelling().withRepresentativeness();
		exp.add(rep::withCompleteness, doc.dataCompleteness);
		exp.add(rep::withDataSelection, doc.dataSelection);
		exp.add(rep::withDataTreatment, doc.dataTreatment);
		exp.add(rep::withSamplingProcedure, doc.samplingProcedure);
		exp.add(rep::withDataCollectionPeriod, doc.dataCollectionPeriod);
		exp.add(rep::withUseAdvice, doc.useAdvice);
		doc.sources.stream()
				.map(exp::writeRef)
				.filter(Objects::nonNull)
				.forEach(s -> rep.withSources().add(s));
	}

	private void mapReviews(Process ds) {
		if (doc == null || doc.reviews.isEmpty())
			return;
		var reviews = ds.withModelling()
				.withValidation()
				.withReviews();
		for (var r : doc.reviews) {
			var rev = new Review();
			reviews.add(rev);
			rev.withType(ReviewType.fromValue(r.type).orElse(null))
					.withReport(exp.writeRef(r.report));
			exp.add(rev::withDetails, r.details);
			for (var reviewer : r.reviewers) {
				var ref = exp.writeRef(reviewer);
				if (ref != null) {
					rev.withReviewers().add(ref);
				}
			}

			// review scopes & methods
			for (var s : r.scopes.values()) {
				var name = ReviewScope.fromValue(s.name).orElse(null);
				if (name == null)
					continue;
				var scope = new Review.Scope().withName(name);
				rev.withScopes().add(scope);
				for (var m : s.methods) {
					ReviewMethod.fromValue(m).ifPresent(method -> {
						var entry = new Review.Method().withName(method);
						scope.withMethods().add(entry);
					});
				}
			}

			// data quality assessment
			for (var dq : QualityIndicator.values()) {
				var a = r.assessment.get(dq.value());
				if (a == null)
					continue;
				var v = Quality.fromValue(a).orElse(null);
				if (v == null)
					continue;
				rev.withIndicators().add(
						new DataQualityIndicator()
								.withName(dq)
								.withValue(v));
			}
		}
	}

	private void mapCompleteness(Process ds) {
		if (doc == null || doc.flowCompleteness.isEmpty())
			return;
		var c = doc.flowCompleteness;
		var productAspect = FlowCompleteness
				.fromValue(c.get("Product model"))
				.orElse(null);
		var completeness = ds.withModelling()
				.withCompleteness()
				.withProductCompleteness(productAspect);
		for (var impact : ImpactCategory.values()) {
			var aspect = FlowCompleteness
					.fromValue(c.get(impact.value()))
					.orElse(null);
			if (aspect == null)
				continue;
			var e = new FlowCompletenessEntry()
					.withImpact(impact)
					.withValue(aspect);
			completeness.withEntries().add(e);
		}
	}

	private void mapComplianceSystems(Process ds) {
		if (doc == null || doc.complianceDeclarations.isEmpty())
			return;
		var decs = ds.withModelling().withComplianceDeclarations();
		for (var c : doc.complianceDeclarations) {
			var dec = new ComplianceDeclaration()
					.withSystem(exp.writeRef(c.system));
		  Compliance.fromValue(c.aspects.get("Overall compliance"))
					.ifPresent(dec::withApproval);
			Compliance.fromValue(c.aspects.get("Nomenclature compliance"))
					.ifPresent(dec::withNomenclature);
			Compliance.fromValue(c.aspects.get("Methodological compliance"))
					.ifPresent(dec::withMethod);
			Compliance.fromValue(c.aspects.get("Review compliance"))
					.ifPresent(dec::withReview);
			Compliance.fromValue(c.aspects.get("Documentation compliance"))
					.ifPresent(dec::withDocumentation);
			Compliance.fromValue(c.aspects.get("Quality compliance"))
					.ifPresent(dec::withQuality);
			decs.add(dec);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy