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

org.openlca.jsonld.JsonDatabaseTransfer Maven / Gradle / Ivy

The newest version!
package org.openlca.jsonld;

import jakarta.persistence.Table;
import org.openlca.core.database.IDatabase;
import org.openlca.core.database.NativeSql;
import org.openlca.core.model.ModelType;
import org.openlca.core.model.ProductSystem;
import org.openlca.jsonld.input.JsonImport;
import org.openlca.jsonld.input.UpdateMode;
import org.openlca.util.ProductSystems;
import org.openlca.util.Strings;

import java.util.EnumMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * Transfers data sets from one database to another using JSON serialization.
 * This is like exporting data sets from a source database to a JSON package
 * and importing that package into the target database. A use case for this
 * would be for example, when a foreground system of the same background
 * database should be transferred, e.g. to a library based target database.
 * Note that this works without updates only, means it will never update an
 * already existing data set in the target database.
 */
public class JsonDatabaseTransfer {

	private final IDatabase source;
	private final Map> transfers = new EnumMap<>(ModelType.class);
	private IDatabase target;

	private JsonDatabaseTransfer(IDatabase source) {
		this.source = Objects.requireNonNull(source);
	}

	public static JsonDatabaseTransfer from(IDatabase source) {
		return new JsonDatabaseTransfer(source);
	}

	public JsonDatabaseTransfer to(IDatabase target) {
		this.target = target;
		return this;
	}

	public JsonDatabaseTransfer add(ModelType type, String refId) {
		if (type == null || refId == null)
			return this;
		var ids = transfers.computeIfAbsent(type, $ -> new HashSet<>());
		ids.add(refId);
		return this;
	}

	public JsonDatabaseTransfer addAllOf(ModelType type) {
		if (type == null || type == ModelType.CATEGORY || target == null)
			return this;

		var table = type.getModelClass()
				.getAnnotation(Table.class)
				.name();
		var query = type == ModelType.PARAMETER
				? "select ref_id from " + table + " where scope = 'GLOBAL'"
				: "select ref_id from " + table;

		var existing = new HashSet();
		NativeSql.on(target).query(query, r -> {
			var id = r.getString(1);
			if (Strings.notEmpty(id)) {
				existing.add(id);
			}
			return true;
		});

		NativeSql.on(source).query(query, r -> {
			var id = r.getString(1);
			if (Strings.notEmpty(id) && !existing.contains(id)) {
				add(type, id);
			}
			return true;
		});
		return this;
	}

	public JsonDatabaseTransfer addAll() {
		for (var type : ModelType.values()) {
			addAllOf(type);
		}
		return this;
	}

	public void run() {
		if (target == null)
			return;
		if (transfers.isEmpty()) {
			addAll();
		}
		checkParameters();

		var store = JsonDatabaseStore.of(source);
		var imp = new JsonImport(store, target)
				.setUpdateMode(UpdateMode.NEVER);

		for (var type : ModelType.values()) {
			var ids = transfers.get(type);
			if (ids == null)
				continue;
			var clazz = type.getModelClass();
			for (var id : ids) {
				var model = imp.get(clazz, id);

				// transferred systems may need to be cleaned up
				// (e.g. when transferring to a library based database)
				if (model instanceof ProductSystem system) {
					ProductSystems.tidy(system);
					target.update(system);
				}
			}
		}
	}

	private void checkParameters() {
		if (transfers.get(ModelType.PARAMETER) != null)
			return;
		// if these types are transferred, we also should
		// transfer global parameters
		var types = List.of(
				ModelType.PROJECT,
				ModelType.PRODUCT_SYSTEM,
				ModelType.PROCESS,
				ModelType.IMPACT_METHOD,
				ModelType.IMPACT_CATEGORY);
		boolean doTransfer = false;
		for (var type : types) {
			if (transfers.get(type) != null) {
				doTransfer = true;
				break;
			}
		}
		if (doTransfer) {
			addAllOf(ModelType.PARAMETER);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy