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

org.openlca.io.olca.ProcessImport Maven / Gradle / Ivy

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

import gnu.trove.list.array.TLongArrayList;
import gnu.trove.map.hash.TLongLongHashMap;
import org.openlca.core.database.NativeSql;
import org.openlca.core.database.ProcessDao;
import org.openlca.core.io.ImportLog;
import org.openlca.core.model.Exchange;
import org.openlca.core.model.Process;
import org.openlca.core.model.descriptors.ProcessDescriptor;

import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.Objects;

class ProcessImport {

	private final Config conf;
	private final ImportLog log;
	private final ProcessDao srcDao;
	private final ProcessDao destDao;
	private final RefSwitcher refs;

	// Required for translating the default provider links: we import exchanges
	// with possible links to processes that are not yet imported
	private final TLongLongHashMap providerMap = new TLongLongHashMap();

	// Contains the exchange IDs and old default provider IDs that need to be
	// updated after the import.
	private final TLongLongHashMap oldExchangeProviders = new TLongLongHashMap();

	private ProcessImport(Config config) {
		this.conf = config;
		this.log = config.log();
		this.srcDao = new ProcessDao(config.source());
		this.destDao = new ProcessDao(config.target());
		this.refs = new RefSwitcher(conf);
	}

	static void run(Config conf) {
		new ProcessImport(conf).run();
	}

	private void run() {
		for (var d : srcDao.getDescriptors()) {
			try {
				long destId = conf.seq().get(Seq.PROCESS, d.refId);
				if (destId != 0) {
					providerMap.put(d.id, destId);
				} else {
					copy(d);
				}
			} catch (Exception e) {
				log.error("failed to copy process " + d.refId, e);
			}
		}
		swapDefaultProviders();
	}

	private void copy(ProcessDescriptor d) {

		// init copy
		var process = srcDao.getForId(d.id);
		if (process == null)
			return;
		var copy = process.copy();
		copy.refId = process.refId;

		// swap references
		copy.category = conf.swap(process.category);
		copy.location = conf.swap(process.location);
		copy.dqSystem = conf.swap(copy.dqSystem);
		copy.exchangeDqSystem = conf.swap(copy.exchangeDqSystem);
		copy.socialDqSystem = conf.swap(copy.socialDqSystem);

		swapExchangeRefs(copy);
		swapAllocationProducts(process, copy);
		swapDocRefs(copy);
		for (var a : copy.socialAspects) {
			a.indicator = conf.swap(a.indicator);
			a.source = conf.swap(a.source);
		}

		copy = destDao.insert(copy);
		conf.seq().put(Seq.PROCESS, process.refId, copy.id);
		providerMap.put(process.id, copy.id);

		// collect old default providers; they have a negative sign
		for (var e : copy.exchanges) {
			if (e.defaultProviderId >= 0)
				continue;
			oldExchangeProviders.put(e.id, Math.abs(e.defaultProviderId));
		}
	}

	/**
	 * Returns also the list of provider IDs from the source database that need
	 * to be updated after the import.
	 */
	private void swapExchangeRefs(Process copy) {
		var removals = new ArrayList();
		for (Exchange e : copy.exchanges) {
			if (!isValid(e)) {
				removals.add(e);
				continue;
			}

			// swap references
			e.flow = conf.swap(e.flow);
			e.flowPropertyFactor = refs.switchRef(e.flowPropertyFactor, e.flow);
			e.unit = refs.switchRef(e.unit);
			e.currency = conf.swap(e.currency);
			e.location = conf.swap(e.location);

			// handle the default provider
			if (e.defaultProviderId > 0) {
				long oldId = e.defaultProviderId;
				long newId = providerMap.get(oldId);
				if (newId != 0) {
					// default provider already in database
					e.defaultProviderId = newId;
				} else {
					// update required after import indicated by a negative sign
					// we can handle it when IDs are available after insertion
					e.defaultProviderId = -oldId;
				}
			}
		}

		if (!removals.isEmpty()) {
			log.warn(copy,
					"had invalid exchanges that were removed in the import");
			copy.exchanges.removeAll(removals);
		}
	}


	private boolean isValid(Exchange e) {
		return e.flow != null
				&& e.flowPropertyFactor != null
				&& e.flowPropertyFactor.flowProperty != null
				&& e.unit != null;
	}

	private void swapAllocationProducts(Process process, Process copy) {
		for (var f : copy.allocationFactors) {
			String productId = null;
			for (var e : process.exchanges) {
				if (e.flow != null && e.flow.id == f.productId) {
					productId = e.flow.refId;
					break;
				}
			}
			f.productId = conf.seq().get(Seq.FLOW, productId);
		}
	}

	private void swapDocRefs(Process copy) {
		if (copy.documentation == null)
			return;
		var doc = copy.documentation;
		doc.dataGenerator = conf.swap(doc.dataGenerator);
		doc.dataDocumentor = conf.swap(doc.dataDocumentor);
		doc.dataOwner = conf.swap(doc.dataOwner);
		doc.publication = conf.swap(doc.publication);

		// sources
		var sources = doc.sources.stream()
				.map(conf::swap)
				.filter(Objects::nonNull)
				.toList();
		doc.sources.clear();
		doc.sources.addAll(sources);

		// reviews
		for (var rev : doc.reviews) {
			rev.report = conf.swap(rev.report);
			var reviewers = rev.reviewers.stream()
					.map(conf::swap)
					.filter(Objects::nonNull)
					.toList();
			rev.reviewers.clear();
			rev.reviewers.addAll(reviewers);
		}

		// compliance declarations
		for (var dec : doc.complianceDeclarations) {
			dec.system = conf.swap(dec.system);
		}
	}

	private void swapDefaultProviders() {
		conf.target()
				.getEntityFactory()
				.getCache()
				.evictAll();

		var exchangeIds = new TLongArrayList();
		var providerIds = new TLongArrayList();
		var it = oldExchangeProviders.iterator();
		while (it.hasNext()) {
			it.advance();
			long exchangeId = it.key();
			long newId = providerMap.get(it.value());
			exchangeIds.add(exchangeId);
			providerIds.add(newId);
		}

		var stmt = "update tbl_exchanges set f_default_provider = ? where id = ?";
		try {
			NativeSql.on(conf.target()).batchInsert(stmt, exchangeIds.size(),
					(int i, PreparedStatement ps) -> {
						ps.setLong(1, providerIds.get(i));
						ps.setLong(2, exchangeIds.get(i));
						return true;
					});
		} catch (Exception e) {
			log.error("failed to update default provider", e);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy