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

be.vlaanderen.informatievlaanderen.ldes.ldi.VersionMaterialiser Maven / Gradle / Ivy

The newest version!
package be.vlaanderen.informatievlaanderen.ldes.ldi;

import be.vlaanderen.informatievlaanderen.ldes.ldi.exceptions.ObjectIdentifierException;
import be.vlaanderen.informatievlaanderen.ldes.ldi.types.LdiOneToOneTransformer;
import org.apache.jena.rdf.model.*;
import org.apache.jena.rdf.model.impl.StatementImpl;

import java.util.*;

import static org.apache.jena.rdf.model.ResourceFactory.createProperty;

/**
 * Will transform a Version Object into a State Object.
 */
public class VersionMaterialiser implements LdiOneToOneTransformer {
	private final Property versionPredicate;
	/**
	 * Represents whether only the statements of the node containing the versionOf property needs to be returned,
	 * including potential nested blank nodes
	 */
	private final boolean restrictToMembers;

	public VersionMaterialiser(Property versionPredicate, boolean restrictToMembers) {
		this.versionPredicate = versionPredicate;
		this.restrictToMembers = restrictToMembers;
	}

	@Override
	public Model transform(Model linkedDataModel) {
		final Model versionMaterialisedModel = ModelFactory.createDefaultModel();

		Map versionIDEntityIDMap = getVersionIDEntityIDMap(linkedDataModel, versionPredicate);

		List deversionedStatements = linkedDataModel.listStatements()
				.toList().stream()
				.filter(statement -> !statement.getPredicate().equals(versionPredicate)) // drop isVersionOf stmts
				.map(statement -> deversionStatement(versionIDEntityIDMap, statement))
				.toList();

		versionMaterialisedModel.add(deversionedStatements);

		if (restrictToMembers) {
			return reduceToLDESMemberOnlyModel(versionMaterialisedModel);
		}
		return versionMaterialisedModel;
	}

	private Statement deversionStatement(Map versionIdEntityIdMap, Statement statement) {
		Resource subject = statement.getSubject();
		RDFNode object = statement.getObject();

		// Statement needs 'de-versioning', replacing the subject.
		if (versionIdEntityIdMap.containsKey(subject)) {
			subject = versionIdEntityIdMap.get(subject);
		}

		// Object references a versioned entity, replace it with the 'de-versioned'
		// identifier.
		if (statement.getObject().isResource()
			&& versionIdEntityIdMap.containsKey(object)) {
			object = versionIdEntityIdMap.get(object);
		}

		return new StatementImpl(subject, statement.getPredicate(), object);
	}

	private static Map getVersionIDEntityIDMap(Model model, Property isVersionOfPredicate) {
		Map map = new HashMap<>();
		model.listStatements(null, isVersionOfPredicate, (RDFNode) null).forEach(memberStatement -> {
			if (!memberStatement.getObject().isResource()) {
				throw new ObjectIdentifierException(memberStatement);
			}
			map.put(memberStatement.getSubject(), memberStatement.getObject().asResource());
		});
		return map;
	}

	/**
	 * Builds a model limited to statements about the ldes:member, including
	 * potential nested blank nodes.
	 * Excludes statements about referenced entities, provided as context.
	 *
	 * @param inputModel The model to reduce.
	 * @return The reduced model.
	 */
	private Model reduceToLDESMemberOnlyModel(Model inputModel) {
		Deque subjectsOfIncludedStatements = new ArrayDeque<>();
		Model ldesMemberModel = ModelFactory.createDefaultModel();

		// LDES Member statements
		inputModel.listStatements(null, createProperty(Tree.MEMBER.toString()), (RDFNode) null)
				.forEach(memberStatement -> subjectsOfIncludedStatements.push((Resource) memberStatement.getObject()));

		/*
		 * LDES members can contain blank node references. All statements of those blank
		 * nodes
		 * need to be included in the output as well. Blank nodes can be nested,
		 * hence the need to keep track of them with a stack.
		 */
		while (!subjectsOfIncludedStatements.isEmpty()) {
			Resource subject = subjectsOfIncludedStatements.pop();
			inputModel.listStatements(subject, null, (RDFNode) null).forEach((Statement includedStatement) -> {
				ldesMemberModel.add(includedStatement);
				RDFNode object = includedStatement.getObject();
				if (object.isAnon()) {
					subjectsOfIncludedStatements.push(object.asResource());
				}
			});
		}
		return ldesMemberModel;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy