io.carml.engine.rdf.RdfRefObjectMapper Maven / Gradle / Ivy
package io.carml.engine.rdf;
import io.carml.engine.ExpressionEvaluation;
import io.carml.engine.RefObjectMapper;
import io.carml.engine.TriplesMapper;
import io.carml.engine.join.ChildSideJoin;
import io.carml.engine.join.ChildSideJoinCondition;
import io.carml.engine.join.ChildSideJoinStore;
import io.carml.engine.join.ChildSideJoinStoreProvider;
import io.carml.engine.join.ParentSideJoinConditionStore;
import io.carml.engine.join.ParentSideJoinKey;
import io.carml.model.RefObjectMap;
import io.carml.model.TriplesMap;
import io.carml.util.Models;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.ValueFactory;
import reactor.core.publisher.Flux;
@Slf4j
public class RdfRefObjectMapper implements RefObjectMapper {
@NonNull
private final RefObjectMap refObjectMap;
@NonNull
private final TriplesMap triplesMap;
private final ChildSideJoinStore childSideJoinStore;
@NonNull
private final ValueFactory valueFactory;
public static RdfRefObjectMapper of(@NonNull RefObjectMap refObjectMap, @NonNull TriplesMap triplesMap,
@NonNull RdfMapperConfig rdfMapperConfig,
@NonNull ChildSideJoinStoreProvider childSideJoinStoreProvider) {
if (LOG.isDebugEnabled()) {
LOG.debug("Creating mapper for RefObjectMap {}", refObjectMap.getResourceName());
}
return new RdfRefObjectMapper(refObjectMap, triplesMap,
childSideJoinStoreProvider.createChildSideJoinStore(refObjectMap.getId()),
rdfMapperConfig.getValueFactorySupplier()
.get());
}
private RdfRefObjectMapper(@NonNull RefObjectMap refObjectMap, @NonNull TriplesMap triplesMap,
ChildSideJoinStore childSideJoinStore, @NonNull ValueFactory valueFactory) {
this.refObjectMap = refObjectMap;
this.triplesMap = triplesMap;
this.childSideJoinStore = childSideJoinStore;
this.valueFactory = valueFactory;
}
@Override
public TriplesMap getTriplesMap() {
return triplesMap;
}
@Override
public RefObjectMap getRefObjectMap() {
return refObjectMap;
}
public void map(Map, Set> subjectsAndAllGraphs, Set predicates,
ExpressionEvaluation expressionEvaluation) {
prepareChildSideJoins(subjectsAndAllGraphs, predicates, expressionEvaluation);
}
private void prepareChildSideJoins(Map, Set> subjectsAndAllGraphs, Set predicates,
ExpressionEvaluation expressionEvaluation) {
Set childSideJoinConditions = refObjectMap.getJoinConditions()
.stream()
.map(joinCondition -> {
String childReference = joinCondition.getChild();
ArrayList childValues = expressionEvaluation.apply(joinCondition.getChild())
.map(expressionResult -> new ArrayList<>(ExpressionEvaluation.extractValues(expressionResult)))
.orElse(new ArrayList<>());
return ChildSideJoinCondition.of(childReference, childValues, joinCondition.getParent());
})
.collect(Collectors.toSet());
Set> childSideJoins = subjectsAndAllGraphs.entrySet()
.stream()
.map(subjectsAndAllGraphsEntry -> prepareChildSideJoin(subjectsAndAllGraphsEntry.getKey(), predicates,
subjectsAndAllGraphsEntry.getValue(), childSideJoinConditions))
.collect(Collectors.toUnmodifiableSet());
childSideJoinStore.addAll(childSideJoins);
}
private ChildSideJoin prepareChildSideJoin(Set subjects, Set predicates,
Set graphs, Set childSideJoinConditions) {
return ChildSideJoin.builder()
.subjects(new HashSet<>(subjects))
.predicates(new HashSet<>(predicates))
.graphs(new HashSet<>(graphs))
.childSideJoinConditions(new HashSet<>(childSideJoinConditions))
.build();
}
@Override
public Flux resolveJoins(TriplesMapper parentTriplesMapper) {
return childSideJoinStore.clearingFlux()
.flatMap(childSideJoin -> resolveJoin(parentTriplesMapper, childSideJoin));
}
private Flux resolveJoin(TriplesMapper parentTriplesMapper,
ChildSideJoin childSideJoin) {
ParentSideJoinConditionStore parentJoinConditions = parentTriplesMapper.getParentSideJoinConditions();
Set objects = checkJoinAndGetObjects(childSideJoin, parentJoinConditions);
if (!objects.isEmpty()) {
Set subjects = childSideJoin.getSubjects();
Set predicates = childSideJoin.getPredicates();
Set graphs = childSideJoin.getGraphs();
return Flux.fromStream(Models.streamCartesianProductStatements(subjects, predicates, objects, graphs,
RdfTriplesMapper.defaultGraphModifier, valueFactory, RdfTriplesMapper.logAddStatements));
}
return Flux.empty();
}
private Set checkJoinAndGetObjects(ChildSideJoin childSideJoin,
ParentSideJoinConditionStore parentJoinConditions) {
List> parentResults = childSideJoin.getChildSideJoinConditions()
.stream()
.map(childSideJoinCondition -> checkChildSideJoinCondition(childSideJoinCondition, parentJoinConditions))
.collect(Collectors.toList());
if (parentResults.isEmpty()) {
return Set.of();
} else if (parentResults.size() == 1) {
return parentResults.get(0);
}
// return intersection of parentResults
return parentResults.stream()
.skip(1)
.collect(() -> new HashSet<>(parentResults.get(0)), Set::retainAll, Set::retainAll);
}
private Set checkChildSideJoinCondition(ChildSideJoinCondition childSideJoinCondition,
ParentSideJoinConditionStore parentJoinConditions) {
return childSideJoinCondition.getChildValues()
.stream()
.flatMap(childValue -> checkChildSideJoinConditionChildValue(childSideJoinCondition, childValue,
parentJoinConditions).stream())
.collect(Collectors.toUnmodifiableSet());
}
private Set checkChildSideJoinConditionChildValue(ChildSideJoinCondition childSideJoinCondition,
String childValue, ParentSideJoinConditionStore parentJoinConditions) {
ParentSideJoinKey parentSideKey = ParentSideJoinKey.of(childSideJoinCondition.getParentReference(), childValue);
return parentJoinConditions.containsKey(parentSideKey) ? parentJoinConditions.get(parentSideKey) : Set.of();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy