package org.aksw.jena_sparql_api.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.aksw.commons.collections.MapUtils;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.sparql.core.Quad;
import org.apache.jena.sparql.core.QuadPattern;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.engine.binding.BindingHashMap;
import org.apache.jena.sparql.graph.NodeTransform;
import org.apache.jena.sparql.graph.NodeTransformLib;
import org.apache.jena.sparql.syntax.Element;
import org.apache.jena.sparql.syntax.ElementGroup;
import org.apache.jena.sparql.syntax.ElementNamedGraph;
import org.apache.jena.sparql.syntax.ElementTriplesBlock;
public class QuadUtils {
/**
* Replace all variable names with the same variable (?a in this case).
* Useful for checking whether two expressions are structurally equivalent.
*
* @param expr
*/
// public static QuadPattern signaturize(Quad quad) {
// NodeTransform nodeTransform = new NodeTransformSignaturize();
// QuadPattern result = NodeTransformLib.transform(nodeTransform, quad);
// return result;
// }
//
// public static QuadPattern signaturize(QuadPattern quadPattern, Map<? extends Node, ? extends Node> nodeMap) {
// NodeTransform baseTransform = new NodeTransformRenameMap(nodeMap);
// NodeTransform nodeTransform = new NodeTransformSignaturize(baseTransform);
// QuadPattern result = NodeTransformLib.transform(nodeTransform, quadPattern);
// return result;
// }
public static Map<Node, Set<Quad>> partitionByGraph(Iterable<Quad> quads) {
Map<Node, Set<Quad>> result = new HashMap<Node, Set<Quad>>();
for (Quad quad : quads) {
Node g = quad.getGraph();
Set<Quad> qs = result.get(g);
if (qs == null) {
qs = new HashSet<Quad>();
result.put(g, qs);
}
qs.add(quad);
}
return result;
}
public static Map<Node, Set<Triple>> partitionByGraphTriples(Iterable<Quad> quads) {
Map<Node, Set<Triple>> result = new HashMap<Node, Set<Triple>>();
for (Quad quad : quads) {
Node g = quad.getGraph();
Set<Triple> ts = result.get(g);
if (ts == null) {
ts = new HashSet<Triple>();
result.put(g, ts);
}
Triple t = quad.asTriple();
ts.add(t);
}
return result;
}
public static Element toElement(Iterable<Quad> quads) {
Map<Node, Set<Quad>> map = partitionByGraph(quads);
Element result = toElement(map);
return result;
}
public static Element toElement(Map<Node, Set<Quad>> graphToQuads) {
ElementGroup es = new ElementGroup();
for(Entry<Node, Set<Quad>> entry : graphToQuads.entrySet()) {
ElementTriplesBlock e = new ElementTriplesBlock();
for(Quad quad : entry.getValue()) {
Triple triple = quad.asTriple();
e.addTriple(triple);
}
Node graph = entry.getKey();
Element f = graph == null || graph.equals(Quad.defaultGraphNodeGenerated)
? e
: new ElementNamedGraph(graph, e);
es.addElement(f);
}
Element result = es.getElements().size() == 1
? es.getElements().get(0)
: es;
return result;
}
public static final String ng = "g";
public static final String ns = "s";
public static final String np = "p";
public static final String no = "o";
public static final List<String> quadVarNames = Arrays.asList(ng, ns, np,
no);
public static final Var vg = Var.alloc(ng);
public static final Var vs = Var.alloc(ns);
public static final Var vp = Var.alloc(np);
public static final Var vo = Var.alloc(no);
public static final List<Var> quadVars = Arrays.asList(vg, vs, vp, vo);
public static Binding quadToBinding(Quad quad) {
BindingHashMap result = new BindingHashMap();
result.add(vg, quad.getGraph());
result.add(vs, quad.getSubject());
result.add(vp, quad.getPredicate());
result.add(vo, quad.getObject());
return result;
}
/**
* Substitutes the keys in the map
*
* @param <K>
* @param <V>
* @param original
* @param map
* @return
*/
public static <K, V> Map<K, V> copySubstitute(Map<K, V> original,
Map<K, K> map) {
Map<K, V> result = new HashMap<K, V>();
for (Map.Entry<K, V> entry : original.entrySet()) {
result.put(MapUtils.getOrElse(map, entry.getKey(), entry.getKey()),
entry.getValue());
}
return result;
}
public static Set<Quad> applyNodeTransform(Set<Quad> quads,
NodeTransform nodeTransform) {
Set<Quad> result = new HashSet<Quad>();
for (Quad quad : quads) {
Quad newQuad = applyNodeTransform(quad, nodeTransform);
result.add(newQuad);
}
return result;
}
public static Quad applyNodeTransform(Quad quad,
NodeTransform nodeTransform) {
Node g = nodeTransform.apply(quad.getGraph());
Node s = nodeTransform.apply(quad.getSubject());
Node p = nodeTransform.apply(quad.getPredicate());
Node o = nodeTransform.apply(quad.getObject());
g = g != null ? g : quad.getGraph();
s = s != null ? s : quad.getSubject();
p = p != null ? p : quad.getPredicate();
o = o != null ? o : quad.getObject();
Quad result = new Quad(g, s, p, o);
return result;
}
public static Quad copySubstitute(Quad quad,
Map<? extends Node, ? extends Node> map) {
return new Quad(
MapUtils.getOrElse(map, quad.getGraph(), quad.getGraph()),
MapUtils.getOrElse(map, quad.getSubject(), quad.getSubject()),
MapUtils.getOrElse(map, quad.getPredicate(),
quad.getPredicate()),
MapUtils.getOrElse(map, quad.getObject(), quad.getObject()));
}
/**
* Create a quad from an array
*
* @param nodes
* @return
*/
public static Quad create(Node[] nodes) {
return new Quad(nodes[0], nodes[1], nodes[2], nodes[3]);
}
public static Node getNode(Quad quad, int index) {
switch (index) {
case 0:
return quad.getGraph();
case 1:
return quad.getSubject();
case 2:
return quad.getPredicate();
case 3:
return quad.getObject();
default:
throw new IndexOutOfBoundsException(
"Index: " + index + " Size: " + 4);
}
}
public static Node substitute(Node node, Binding binding) {
Node result = node;
if (node.isVariable()) {
result = binding.get((Var) node);
if (result == null) {
throw new RuntimeException("Variable " + node + "not bound");
}
}
return result;
}
public static Quad copySubstitute(Quad quad, Binding binding) {
return new Quad(substitute(quad.getGraph(), binding),
substitute(quad.getSubject(), binding),
substitute(quad.getPredicate(), binding),
substitute(quad.getObject(), binding));
}
/*
* public static QuadPattern copySubstitute(QuadPattern quadPattern, Binding
* map) { map.ge }
*/
public static QuadPattern copySubstitute(QuadPattern quadPattern,
Map<? extends Node, ? extends Node> map) {
QuadPattern result = new QuadPattern();
for (Quad quad : quadPattern) {
result.add(copySubstitute(quad, map));
}
return result;
}
public static Quad listToQuad(List<Node> nodes) {
return new Quad(nodes.get(0), nodes.get(1), nodes.get(2), nodes.get(3));
}
public static Quad arrayToQuad(Node[] nodes) {
return new Quad(nodes[0], nodes[1], nodes[2], nodes[3]);
}
public static Node[] quadToArray(Quad quad) {
return new Node[] { quad.getGraph(), quad.getSubject(), quad.getPredicate(), quad.getObject() };
}
public static List<Node> quadToList(Quad quad) {
List<Node> result = new ArrayList<Node>();
result.add(quad.getGraph());
result.add(quad.getSubject());
result.add(quad.getPredicate());
result.add(quad.getObject());
return result;
}
public static Set<Var> getVarsMentioned(Quad quad) {
return NodeUtils.getVarsMentioned(quadToList(quad));
}
public static Map<Node, Node> getVarMapping(Quad a, Quad b) {
List<Node> nAs = quadToList(a);
List<Node> nBs = quadToList(b);
Map<Node, Node> result = new HashMap<Node, Node>();
for (int i = 0; i < 4; ++i) {
Node nA = nAs.get(i);
Node nB = nBs.get(i);
if (nA.isVariable()) {
Map<Node, Node> newEntry = Collections.singletonMap(nA, nB);
// MapUtils.isCompatible(result, newEntry);
result.putAll(newEntry);
} else {
if (!nA.equals(nB)) {
return null;
}
}
}
return result;
}
}