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

io.carml.engine.rdf.RdfRefObjectMapper Maven / Gradle / Ivy

There is a newer version: 0.4.11
Show newest version
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