package org.aksw.jena_sparql_api.sparql_path2;
import java.util.Set;
import java.util.function.Function;
import org.aksw.jena_sparql_api.concepts.Concept;
import org.aksw.jena_sparql_api.core.QueryExecutionFactory;
import org.aksw.jena_sparql_api.jgrapht.LabeledEdge;
import org.aksw.jena_sparql_api.jgrapht.LabeledEdgeImpl;
import org.aksw.jena_sparql_api.lookup.ListService;
import org.aksw.jena_sparql_api.lookup.ListServiceUtils;
import org.aksw.jena_sparql_api.lookup.LookupService;
import org.aksw.jena_sparql_api.lookup.LookupServiceFilterKey;
import org.aksw.jena_sparql_api.lookup.LookupServiceListService;
import org.aksw.jena_sparql_api.mapper.MappedConcept;
import org.aksw.jena_sparql_api.shape.ResourceShape;
import org.aksw.jena_sparql_api.shape.ResourceShapeBuilder;
import org.aksw.jena_sparql_api.utils.Pair;
import org.aksw.jena_sparql_api.utils.model.Triplet;
import org.aksw.jena_sparql_api.utils.model.TripletImpl;
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.Node;
import org.apache.jena.sparql.path.Path;
public class PathExecutionUtils {
/**
* A function that creates a lookup service for a given qef and predicate class
*
*/
public static <S, T> LookupService<Node, Set<Triplet<Node, Node>>> createLookupService(QueryExecutionFactory qef, Pair<ValueSet<Node>> predicateClass) {
ResourceShapeBuilder rsb = new ResourceShapeBuilder();
PathVisitorResourceShapeBuilder.apply(rsb, predicateClass, false);
//MappedConcept<Graph> mc = ResourceShape.createMappedConcept(rsb.getResourceShape(), filter);
MappedConcept<Graph> mc = ResourceShape.createMappedConcept(rsb.getResourceShape(), null, false);
ListService<Concept, Node, Graph> ls = ListServiceUtils.createListServiceAcc(qef, mc, false);
//Map<Node, Graph> nodeToGraph = ls.fetchData(null, null, null);
// TODO Add a default fluent API
LookupService<Node, Graph> lsls = LookupServiceListService.create(ls);
lsls = new LookupServiceFilterKey<Node, Graph>(lsls, k -> k.isURI());
//lsls.partition(100);
//lsls = LookupServicePartition.create(lsls, 100);
LookupService<Node, Set<Triplet<Node, Node>>> s = lsls.mapValues(e -> {
// Map<Node, Set<Triplet<Node, Node>>> r =
// map.entrySet().stream()
// .collect(Collectors.toMap(Entry::getKey, e -> graphToTriplets(e.getValue())));
Set<Triplet<Node, Node>> r = graphToTriplets(e);
return r;
});
return s;
};
public static Set<Triplet<Node, Node>> graphToTriplets(Graph graph) {
Set<Triplet<Node, Node>> result = graph
.find(Node.ANY, Node.ANY, Node.ANY)
.mapWith(t -> (Triplet<Node, Node>)new TripletImpl<Node, Node>(t.getSubject(), t.getPredicate(), t.getObject()))
.toSet();
return result;
}
public static void executePath(Path path, Node startNode, Node targetNode, QueryExecutionFactory qef, Function<NestedPath<Node, Node>, Boolean> pathCallback) {
Nfa<Integer, LabeledEdge<Integer, PredicateClass>> nfa = PathCompiler.compileToNfa(path);
System.out.println("NFA");
System.out.println(nfa);
for(LabeledEdge<Integer, PredicateClass> edge : nfa.getGraph().edgeSet()) {
System.out.println(edge);
}
// PartialNfa<Integer, Path> peek = nfaCompiler.peek();
//QueryExecutionFactory qef = FluentQueryExecutionFactory.http("http://dbpedia.org/sparql", "http://dbpedia.org").config().selectOnly().end().create();
//NfaExecution<Integer, LabeledEdge<Integer, Path>, Node, Node> exec = new NfaExecution<>(nfa, qef, false, p -> targetNode == null || p.getEnd().equals(targetNode) ? pathCallback.apply(p) : false);
//Function<LabeledEdge<Integer, Path>, Path> edgeToPath = e -> e.getLabel();
NfaFrontier<Integer, Node, Node, Node> frontier = new NfaFrontier<>();
Function<NestedPath<Node, Node>, Node> nodeGrouper = nestedPath -> nestedPath.getCurrent();
NfaFrontier.addAll(frontier, nfa.getStartStates(), nodeGrouper, startNode);
// TODO: How to wrap a LookupService, such that we can chain transformations?
// Ok, java8 supports this natively
// In essence, a lookupservice is a Function<K, Map<K, V>>
//
// Function<Collection<Node>, Map<Node, Graphlet<Node, Node>>> nodeToGraphlets = (LabeledEdge<Integer, Path> transition, boolean assumeReversed) -> {
//
// //Path path = transitionToPath.apply(transition);
//
//
//
// //Map<Node, Graph> nodeToGraph = lsls.apply(nodes);
// };
while(!frontier.isEmpty()) {
boolean abort = NfaExecutionUtils.collectPaths(nfa, frontier, LabeledEdgeImpl::isEpsilon, pathCallback);
if(abort) {
break;
}
if(true) {
throw new RuntimeException("Adjust the code");
}
//NfaFrontier<Integer, Node, Node, Node> nextFrontier = null; //
// NfaFrontier<Integer, Node, Node, Node> nextFrontier = NfaExecutionUtils.advanceFrontier(
// frontier,
// nfa,
// LabeledEdgeImpl::isEpsilon,
// createLookupService, // getTriplets
// nestedPath -> nestedPath.getCurrent(),
// false
// );
// //System.out.println("advancing...");
// frontier = nextFrontier;
}
}
/**
* Generic nfa execution
*
* BiFunction<Set<V>, T, Map<V, Set<Triplet<V, E>>>> getMatchingTriplets
*
* This function resolves a single transition of the nfa to a set of triplets
* The Directed<T> is used to execute the automaton in reverse direction
*
*
* @param nfa
* @param vertices
*/
// public static <S, T, V, E> void execNfa(
// Nfa<S, T> nfa,
// Predicate<T> isEpsilon,
// Set<V> startVertices,
// BiFunction<T, NestedPath<V, E>, Map<V, Set<Triplet<V, E>>>> getMatchingTriplets,
// Function<NestedPath<V, E>, Boolean> pathCallback) {
// execNfa(
// nfa,
// nfa.getStartStates(),
// isEpsilon,
// startVertices,
// //getMatchingTriplets,
// (trans, vToNestedPaths) ->
// vToNestedPaths.values().stream()
// .map(nestedPath -> getMatchingTriplets.apply(trans, nestedPath))
// .collect(Collectors.toSet()),
// pathCallback);
// }
}