io.carml.engine.rdf.RdfPredicateObjectMapper Maven / Gradle / Ivy
package io.carml.engine.rdf;
import static io.carml.util.LogUtil.exception;
import static io.carml.util.LogUtil.log;
import io.carml.engine.ExpressionEvaluation;
import io.carml.engine.TermGenerator;
import io.carml.engine.TriplesMapperException;
import io.carml.model.BaseObjectMap;
import io.carml.model.LogicalSource;
import io.carml.model.ObjectMap;
import io.carml.model.PredicateObjectMap;
import io.carml.model.RefObjectMap;
import io.carml.model.TriplesMap;
import io.carml.util.Models;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
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.Value;
import org.eclipse.rdf4j.model.ValueFactory;
import reactor.core.publisher.Flux;
@Slf4j
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class RdfPredicateObjectMapper {
private final Set> graphGenerators;
private final Set> predicateGenerators;
private final Set> objectGenerators;
@Getter(AccessLevel.PACKAGE)
private final Set rdfRefObjectMappers;
@NonNull
private final ValueFactory valueFactory;
public static RdfPredicateObjectMapper of(@NonNull PredicateObjectMap pom, @NonNull TriplesMap triplesMap,
Set refObjectMappers, @NonNull RdfMapperConfig rdfMapperConfig) {
RdfTermGeneratorFactory rdfTermGeneratorFactory =
(RdfTermGeneratorFactory) rdfMapperConfig.getTermGeneratorFactory();
Set> graphGenerators =
RdfTriplesMapper.createGraphGenerators(pom.getGraphMaps(), rdfTermGeneratorFactory);
Set> predicateGenerators = createPredicateGenerators(pom, triplesMap, rdfTermGeneratorFactory);
Set objectMaps = pom.getObjectMaps();
Set> objectGenerators =
createObjectGenerators(objectMaps, triplesMap, rdfTermGeneratorFactory);
Set filteredRefObjectMappers = refObjectMappers.stream()
.filter(rom -> pom.getObjectMaps()
.contains(rom.getRefObjectMap()))
.collect(Collectors.toUnmodifiableSet());
return new RdfPredicateObjectMapper(graphGenerators, predicateGenerators, objectGenerators,
filteredRefObjectMappers, rdfMapperConfig.getValueFactorySupplier()
.get());
}
static Set> createPredicateGenerators(PredicateObjectMap pom, TriplesMap triplesMap,
RdfTermGeneratorFactory termGeneratorFactory) {
return pom.getPredicateMaps()
.stream()
.map(predicateMap -> {
try {
return termGeneratorFactory.getPredicateGenerator(predicateMap);
} catch (RuntimeException ex) {
throw new TriplesMapperException(
String.format("Exception occurred while creating predicate generator for %s",
exception(triplesMap, predicateMap)),
ex);
}
})
.collect(Collectors.toUnmodifiableSet());
}
private static Set> createObjectGenerators(Set objectMaps,
TriplesMap triplesMap, RdfTermGeneratorFactory termGeneratorFactory) {
return Stream.concat(
// object maps -> object generators
createObjectMapGenerators(objectMaps, triplesMap, termGeneratorFactory),
// ref object maps without joins -> object generators.
createJoinlessRefObjectMapGenerators(objectMaps, triplesMap, termGeneratorFactory))
.collect(Collectors.toUnmodifiableSet());
}
@SuppressWarnings("java:S3864")
static Stream> createObjectMapGenerators(Set objectMaps,
TriplesMap triplesMap, RdfTermGeneratorFactory termGeneratorFactory) {
return objectMaps.stream()
.filter(ObjectMap.class::isInstance)
.peek(objectMap -> LOG.debug("Creating term generator for ObjectMap {}", objectMap.getResourceName()))
.map(objectMap -> {
try {
return termGeneratorFactory.getObjectGenerator((ObjectMap) objectMap);
} catch (RuntimeException ex) {
throw new TriplesMapperException(String.format("Exception occurred while creating object generator for %s",
exception(triplesMap, objectMap)), ex);
}
});
}
private static RefObjectMap checkLogicalSource(RefObjectMap refObjectMap, LogicalSource logicalSource,
TriplesMap triplesMap) {
if (LOG.isDebugEnabled()) {
LOG.debug("Checking if logicalSource for parent triples map {} is equal", refObjectMap.getParentTriplesMap()
.getResourceName());
}
LogicalSource parentLogicalSource = refObjectMap.getParentTriplesMap()
.getLogicalSource();
if (parentLogicalSource == null) {
throw new TriplesMapperException(String.format(
"Could not determine logical source of parent TriplesMap on RefObjectMap %s%nPossibly the parent triples "
+ "map does not exist, or the reference to it is misspelled?",
exception(triplesMap, refObjectMap)));
}
if (!logicalSource.equals(parentLogicalSource)) {
throw new TriplesMapperException(String.format(
"Logical sources are not equal.%n%nParent logical source: %s%n%nChild logical source: %s%n%nNot equal in "
+ "RefObjectMap %s",
log(refObjectMap.getParentTriplesMap(), parentLogicalSource), log(triplesMap, logicalSource),
exception(triplesMap, refObjectMap)));
}
return refObjectMap;
}
@SuppressWarnings("java:S3864")
private static Stream> createJoinlessRefObjectMapGenerators(
Set objectMaps, TriplesMap triplesMap, RdfTermGeneratorFactory termGeneratorFactory) {
LogicalSource logicalSource = triplesMap.getLogicalSource();
return objectMaps.stream()
.filter(RefObjectMap.class::isInstance)
.peek(objectMap -> LOG.debug("Creating mapper for RefObjectMap {}", objectMap.getResourceName()))
.map(RefObjectMap.class::cast)
.filter(refObjMap -> refObjMap.getJoinConditions()
.isEmpty())
// ref object maps without joins MUST have an identical logical source.
.map(refObjMap -> checkLogicalSource(refObjMap, logicalSource, triplesMap))
.flatMap(refObjMap -> createRefObjectJoinlessMapper(refObjMap, triplesMap, termGeneratorFactory));
}
private static Stream> createRefObjectJoinlessMapper(RefObjectMap refObjectMap,
TriplesMap triplesMap, RdfTermGeneratorFactory termGeneratorFactory) {
try {
return refObjectMap.getParentTriplesMap()
.getSubjectMaps()
.stream()
.map(termGeneratorFactory::getSubjectGenerator);
} catch (RuntimeException ex) {
throw new TriplesMapperException(String.format("Exception occurred for %s", exception(triplesMap, refObjectMap)),
ex);
}
}
public Flux map(ExpressionEvaluation expressionEvaluation,
Map, Set> subjectsAndSubjectGraphs) {
Set predicates = predicateGenerators.stream()
.map(g -> g.apply(expressionEvaluation))
.flatMap(List::stream)
.collect(Collectors.toUnmodifiableSet());
if (predicates.isEmpty()) {
return Flux.empty();
}
Set objects = objectGenerators.stream()
.map(g -> g.apply(expressionEvaluation))
.flatMap(List::stream)
.collect(Collectors.toUnmodifiableSet());
Set pomGraphs = graphGenerators.stream()
.flatMap(graphGenerator -> graphGenerator.apply(expressionEvaluation)
.stream())
.collect(Collectors.toUnmodifiableSet());
Map, Set> subjectsAndAllGraphs =
addPomGraphsToSubjectsAndSubjectGraphs(subjectsAndSubjectGraphs, pomGraphs);
// process RefObjectMaps for resolving later
rdfRefObjectMappers
.forEach(rdfRefObjectMapper -> rdfRefObjectMapper.map(subjectsAndAllGraphs, predicates, expressionEvaluation));
if (objects.isEmpty()) {
return Flux.empty();
}
Set> statementsPerGraphSet = subjectsAndAllGraphs.entrySet()
.stream()
.map(subjectsAndAllGraphsEntry -> Flux.fromStream(Models.streamCartesianProductStatements(
subjectsAndAllGraphsEntry.getKey(), predicates, objects, subjectsAndAllGraphsEntry.getValue(),
RdfTriplesMapper.defaultGraphModifier, valueFactory, RdfTriplesMapper.logAddStatements)))
.collect(Collectors.toUnmodifiableSet());
return Flux.merge(statementsPerGraphSet);
}
private Map, Set> addPomGraphsToSubjectsAndSubjectGraphs(
Map, Set> subjectsAndSubjectGraphs, Set pomGraphs) {
return subjectsAndSubjectGraphs.entrySet()
.stream()
.collect(Collectors.toUnmodifiableMap(Map.Entry::getKey,
subjectsAndSubjectGraphsEntry -> Stream.concat(subjectsAndSubjectGraphsEntry.getValue()
.stream(), pomGraphs.stream())
.collect(Collectors.toUnmodifiableSet())));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy