package org.aksw.jena_sparql_api.utils;
import java.util.ArrayList;
import java.util.List;
import org.aksw.commons.util.reflect.MultiMethod;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.sdb.core.Generator;
import org.apache.jena.sdb.core.Gensym;
import org.apache.jena.sparql.algebra.Op;
import org.apache.jena.sparql.algebra.op.OpAssign;
import org.apache.jena.sparql.algebra.op.OpConditional;
import org.apache.jena.sparql.algebra.op.OpDisjunction;
import org.apache.jena.sparql.algebra.op.OpDistinct;
import org.apache.jena.sparql.algebra.op.OpExtend;
import org.apache.jena.sparql.algebra.op.OpFilter;
import org.apache.jena.sparql.algebra.op.OpGroup;
import org.apache.jena.sparql.algebra.op.OpJoin;
import org.apache.jena.sparql.algebra.op.OpLeftJoin;
import org.apache.jena.sparql.algebra.op.OpOrder;
import org.apache.jena.sparql.algebra.op.OpProject;
import org.apache.jena.sparql.algebra.op.OpQuadBlock;
import org.apache.jena.sparql.algebra.op.OpQuadPattern;
import org.apache.jena.sparql.algebra.op.OpSequence;
import org.apache.jena.sparql.algebra.op.OpSlice;
import org.apache.jena.sparql.algebra.op.OpTable;
import org.apache.jena.sparql.algebra.op.OpTopN;
import org.apache.jena.sparql.algebra.op.OpUnion;
import org.apache.jena.sparql.core.BasicPattern;
import org.apache.jena.sparql.core.Quad;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.expr.E_Equals;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.expr.ExprList;
import org.apache.jena.sparql.expr.ExprVar;
import org.apache.jena.sparql.expr.NodeValue;
/**
* Replaces constants with variables and filter conditions.
*
* Example:
* {?s a ?t .}
*
* becomes:
*
* {
* ?s ?var ?t .
* Filter(?var = rdf:type) .
* }
*
*
* @author raven
*
*/
@Deprecated // "Use TransformReplaceConstants instead"
public class ReplaceConstants {
private static Generator generator = Gensym.create("var", 0);
public static Triple listToTriple(List<Node> nodes) {
return new Triple(nodes.get(0), nodes.get(1), nodes.get(2));
}
public static List<Node> tripleToList(Triple triple)
{
List<Node> result = new ArrayList<Node>();
result.add(triple.getSubject());
result.add(triple.getPredicate());
result.add(triple.getObject());
return result;
}
public static Op replace(Op op)
{
System.out.println("TODO Get rid of reflection for replacement - its slow!");
return MultiMethod.invokeStatic(ReplaceConstants.class, "_replace", op);
}
public static Node transform(Node node, boolean isGraphNode, Generator generator, ExprList filters) {
if(node.isConcrete()) {
Var var = Var.alloc(generator.next());
// Use of the constant Quad.defaultGraphNodeGenerated in the graph position results in a free variable.
if(!(isGraphNode && node.equals(Quad.defaultGraphNodeGenerated))) {
Expr condition = new E_Equals(new ExprVar(var), NodeValue.makeNode(node));
filters.add(condition);
}
return var;
}
return node;
}
public static Op _replace(OpGroup op) {
return new OpGroup(replace(op.getSubOp()), op.getGroupVars(), op.getAggregators());
}
public static Op _replace(OpTable op) {
return null;
}
public static Op _replace(OpExtend op) {
return OpExtend.extend(replace(op.getSubOp()), op.getVarExprList());
}
public static Op _replace(OpAssign op) {
Op newSubOp = replace(op.getSubOp());
Op result = OpExtend.extend(newSubOp, op.getVarExprList());
return result;
}
public static Op _replace(OpSlice op)
{
return new OpSlice(replace(op.getSubOp()), op.getStart(), op.getLength());
}
public static Op _replace(OpOrder op) {
return new OpOrder(replace(op.getSubOp()), op.getConditions());
}
public static Op _replace(OpProject op) {
return new OpProject(replace(op.getSubOp()), op.getVars());
}
public static Op _replace(OpTopN op) {
return new OpTopN(replace(op.getSubOp()), op.getLimit(), op.getConditions());
}
public static Op _replace(OpDistinct op) {
return new OpDistinct(replace(op.getSubOp()));
}
public static Op _replace(OpLeftJoin op) {
return OpLeftJoin.create(replace(op.getLeft()), replace(op.getRight()), op.getExprs());
}
public static Op _replace(OpSequence op) {
List<Op> members = op.getElements();
List<Op> newMembers = new ArrayList<Op>(members.size());
for(Op member : members) {
Op newMember = replace(member);
newMembers.add(newMember);
}
Op result = OpSequence.create().copy(newMembers);
return result;
}
public static Op _replace(OpConditional op) {
Op newLeft = replace(op.getLeft());
Op newRight = replace(op.getRight());
Op result = new OpConditional(newLeft, newRight);
return result;
}
public static Op _replace(OpJoin op) {
return OpJoin.create(replace(op.getLeft()), replace(op.getRight()));
}
public static Op _replace(OpUnion op) {
return OpUnion.create(replace(op.getLeft()), replace(op.getRight()));
}
public static Op _replace(OpDisjunction op) {
OpDisjunction result = OpDisjunction.create();
for(Op member : op.getElements()) {
Op newMember = replace(member);
result.add(newMember);
}
return result;
}
public static Op _replace(OpFilter op) {
return OpFilter.filter(op.getExprs(), replace(op.getSubOp()));
}
// public static Op _replace(OpQuadPattern op) {
//
// ExprList filters = new ExprList();
//
// BasicPattern triples = new BasicPattern();
//
// Node graphNode = transform(op.getGraphNode(), true, generator, filters);
//
//
// List<Node> nodes = new ArrayList<Node>();
// for(Triple triple : op.getBasicPattern().getList()) {
//
//
// for(Node node : tripleToList(triple)) {
// Node n = transform(node, false, generator, filters);
// nodes.add(n);
// }
//
// Triple t = listToTriple(nodes);
//
// triples.add(t);
//
// nodes.clear();
// }
//
// Op result = new OpQuadPattern(graphNode, triples);
//
// if(!filters.isEmpty()) {
// result = OpFilter.filter(filters, result);
// }
//
// return result;
// }
public static Op _replace(OpQuadPattern op) {
ExprList filters = new ExprList();
BasicPattern triples = new BasicPattern();
Node graphNode = transform(op.getGraphNode(), true, generator, filters);
List<Node> nodes = new ArrayList<Node>();
for(Triple triple : op.getBasicPattern().getList()) {
for(Node node : tripleToList(triple)) {
Node n = transform(node, false, generator, filters);
nodes.add(n);
}
Triple t = listToTriple(nodes);
triples.add(t);
nodes.clear();
}
Op result = new OpQuadPattern(graphNode, triples);
if(!filters.isEmpty()) {
result = OpFilter.filter(filters, result);
}
return result;
}
public static Op _replace(OpQuadBlock op) {
throw new RuntimeException("Not implemented yet");
// ExprList filters = new ExprList();
//
//
// //BasicPattern triples = new BasicPattern();
// QuadPattern quadPattern = new QuadPattern();
//
// //Node rawGraphNode = op.getGraphNode();
//
//// Node commonGraphNode = null;
//// if(rawGraphNode.isConcrete()) {
//// // If the graph node is a concrete value - except for the default graph,
//// // replace it with a variable that is constrained to that value
//// if(!rawGraphNode.equals(Quad.defaultGraphNodeGenerated)) {
//// commonGraphNode = transform(rawGraphNode, false, generator, filters);
//// }
//// }
//// else {
//// // If the graph node is a variable, use it.
//// commonGraphNode = rawGraphNode;
//// }
//
//
// List<Node> nodes = new ArrayList<Node>(4);
// for(Quad quad : op.getPattern()) {
//
// Node graphNode;
// if(commonGraphNode != null) {
// graphNode = commonGraphNode;
// } else {
// graphNode = Var.alloc(generator.next());
// }
// nodes.add(graphNode);
//
//
// for(Node node : tripleToList(triple)) {
//
// Node n = transform(node, generator, filters);
// nodes.add(n);
// }
//
// //Triple t = listToTriple(nodes);
//
// //triples.add(t);
// Quad q = QuadUtils.listToQuad(nodes);
// quadPattern.add(q);
// nodes.clear();
// }
//
// Op result = new OpQuadBlock(quadPattern);
//
// if(!filters.isEmpty()) {
// result = OpFilter.filter(filters, result);
// }
//
// return result;
}
}