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

org.openlca.proto.io.input.ImportCache Maven / Gradle / Ivy

package org.openlca.proto.io.input;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.openlca.core.model.Actor;
import org.openlca.core.model.Currency;
import org.openlca.core.model.DQSystem;
import org.openlca.core.model.Flow;
import org.openlca.core.model.FlowProperty;
import org.openlca.core.model.Location;
import org.openlca.core.model.ModelType;
import org.openlca.core.model.RootEntity;
import org.openlca.core.model.SocialIndicator;
import org.openlca.core.model.Source;
import org.openlca.core.model.UnitGroup;
import org.openlca.core.model.descriptors.Descriptor;
import org.openlca.jsonld.input.UpdateMode;

class ImportCache {

	private final ProtoImport imp;

	private final Map, Map> cache = new HashMap<>();

	// small independent instances that we cache as full objects, instances
	// of classes that are not in this set are cached as descriptors
	private final Set> fullyCached = Set.of(
		Actor.class,
		Currency.class,
		DQSystem.class,
		Flow.class,
		FlowProperty.class,
		Location.class,
		SocialIndicator.class,
		Source.class,
		UnitGroup.class
	);

	ImportCache(ProtoImport imp) {
		this.imp = imp;
	}

	void visited(RootEntity entity) {
		if (entity == null)
			return;
		var type = entity.getClass();
		var cacheMap = cache.computeIfAbsent(type, t -> new HashMap<>());
		var cacheObj = fullyCached.contains(type)
			? entity
			: Descriptor.of(entity);
		cacheMap.put(entity.refId, cacheObj);
	}

	Descriptor getDescriptor(Class type, String refId) {
		var cacheMap = cache.get(type);
		if (cacheMap == null)
			return null;
		var cacheObj = cacheMap.get(refId);
		if (cacheObj == null)
			return null;
		if (cacheObj instanceof Descriptor d)
			return d;
		if (cacheObj instanceof RootEntity e)
			return Descriptor.of(e);
		return null;
	}

	@SuppressWarnings("unchecked")
	 ImportItem fetch(Class type, String refId) {
		if (type == null || refId == null)
			return ImportItem.error();
		var modelType = imp.types.get(type);
		if (modelType == null)
			return ImportItem.error();

		// first, try to read it from cache
		var cacheMap = cache.computeIfAbsent(type, t -> new HashMap<>());
		var cached = cacheMap.get(refId);
		if (cached != null) {
			if (type.isInstance(cached))
				return ImportItem.visited(type.cast(cached));
			if (cached instanceof Descriptor d) {
				var model = imp.db().get(type, d.id);
				if (model != null)
					return ImportItem.visited(model);
			}
		}

		// try to read it from the database
		T model = imp.db().get(type, refId);
		if (model != null) {
			if (imp.updateMode == UpdateMode.NEVER) {
				visited(model);
				return ImportItem.visited(model);
			}
		}

		var proto = (ProtoBox)readProto(modelType, refId);
		if (proto == null) {
			if (model == null)
				return ImportItem.error();
			visited(model);
			return ImportItem.visited(model);
		}

		if (skipImport(model, proto)) {
			visited(model);
			return ImportItem.visited(model);
		}

		return model == null
			? ImportItem.newOf(proto)
			: ImportItem.update( proto, model);
	}

	private  boolean skipImport(T model, ProtoBox proto) {
		if (model == null || imp.updateMode == UpdateMode.ALWAYS)
			return false;
		long jsonVersion = Util.versionOf(proto);
		if (jsonVersion != model.version)
			return jsonVersion < model.version;
		long jsonDate = Util.lastChangeOf(proto);
		return jsonDate <= model.lastChange;
	}

	private ProtoBox readProto(ModelType type, String refId) {
		if (type == null)
			return null;
		return switch (type) {
			case PROJECT -> {
				var proto = imp.reader.getProject(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case IMPACT_METHOD -> {
				var proto = imp.reader.getImpactMethod(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case IMPACT_CATEGORY -> {
				var proto = imp.reader.getImpactCategory(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case PRODUCT_SYSTEM -> {
				var proto = imp.reader.getProductSystem(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case PROCESS -> {
				var proto = imp.reader.getProcess(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case FLOW -> {
				var proto = imp.reader.getFlow(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case FLOW_PROPERTY -> {
				var proto = imp.reader.getFlowProperty(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case UNIT_GROUP -> {
				var proto = imp.reader.getUnitGroup(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case ACTOR -> {
				var proto = imp.reader.getActor(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case SOURCE -> {
				var proto = imp.reader.getSource(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case LOCATION -> {
				var proto = imp.reader.getLocation(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case SOCIAL_INDICATOR -> {
				var proto = imp.reader.getSocialIndicator(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case CURRENCY -> {
				var proto = imp.reader.getCurrency(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case PARAMETER -> {
				var proto = imp.reader.getParameter(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case DQ_SYSTEM -> {
				var proto = imp.reader.getDQSystem(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case RESULT -> {
				var proto = imp.reader.getResult(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			case EPD -> {
				var proto = imp.reader.getEpd(refId);
				yield proto != null ? ProtoBox.of(proto) : null;
			}
			default -> null;
		};
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy