package org.aksw.jena_sparql_api.utils.transform; import java.util.Collection; import java.util.Stack; import org.aksw.jena_sparql_api.backports.syntaxtransform.ElementTransform; import org.aksw.jena_sparql_api.backports.syntaxtransform.ElementTransformCopyBase; import org.aksw.jena_sparql_api.backports.syntaxtransform.ElementTransformer; import org.aksw.jena_sparql_api.utils.ExprListUtils; import org.aksw.jena_sparql_api.utils.Generator; import org.aksw.jena_sparql_api.utils.VarGeneratorBlacklist; import org.apache.jena.graph.Node; import org.apache.jena.query.Query; import org.apache.jena.query.QueryFactory; import org.apache.jena.sparql.algebra.Algebra; import org.apache.jena.sparql.algebra.Op; import org.apache.jena.sparql.algebra.OpAsQuery; import org.apache.jena.sparql.algebra.Transformer; import org.apache.jena.sparql.algebra.optimize.TransformFilterPlacement; import org.apache.jena.sparql.core.DatasetDescription; import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.expr.E_OneOf; import org.apache.jena.sparql.expr.ExprList; import org.apache.jena.sparql.expr.ExprTransform; import org.apache.jena.sparql.expr.ExprTransformCopy; import org.apache.jena.sparql.expr.ExprVar; import org.apache.jena.sparql.expr.NodeValue; import org.apache.jena.sparql.syntax.Element; import org.apache.jena.sparql.syntax.ElementFilter; import org.apache.jena.sparql.syntax.ElementGroup; import org.apache.jena.sparql.syntax.ElementNamedGraph; import org.apache.jena.sparql.syntax.ElementPathBlock; import org.apache.jena.sparql.syntax.ElementTriplesBlock; import org.apache.jena.sparql.syntax.ElementVisitor; import org.apache.jena.sparql.syntax.ElementVisitorBase; import org.apache.jena.sparql.syntax.PatternVars; /** * Rewrites a query's dataset description so that it becomes part of the query pattern. * * @author raven * */ public class ElementTransformDatasetDescription extends ElementTransformCopyBase { protected ExprList defaultGraphExprs; protected ExprList namedGraphExprs; protected Stack<Node> graphs; protected Generator<Var> varGen; public ElementTransformDatasetDescription(Stack<Node> graphs, Generator<Var> varGen, ExprList defaultGraphExprs, ExprList namedGraphExprs) { this.graphs = graphs; this.varGen = varGen; this.defaultGraphExprs = defaultGraphExprs; this.namedGraphExprs = namedGraphExprs; } public static ElementTransformDatasetDescription create(Stack<Node> graphs, Element e, DatasetDescription dd) { Collection<Var> vars = PatternVars.vars(e); Generator<Var> varGen = VarGeneratorBlacklist.create("v", vars); ExprList defaultGraphExprs = ExprListUtils.fromUris(dd.getDefaultGraphURIs()); ExprList namedGraphExprs = ExprListUtils.fromUris(dd.getNamedGraphURIs()); ElementTransformDatasetDescription result = new ElementTransformDatasetDescription(graphs, varGen, defaultGraphExprs, namedGraphExprs); return result; } @Override public Element transform(ElementTriplesBlock el) { Element result = applyDefaultGraphs(el); return result; } @Override public Element transform(ElementPathBlock el) { Element result = applyDefaultGraphs(el); return result; } public Element applyDefaultGraphs(Element el) { Element result; // If there are no graphs, inject a graph block constrained to // the default graphs if(graphs.isEmpty() && !defaultGraphExprs.isEmpty()) { Var v = varGen.next(); result = applyGraphs(varGen, v, el, defaultGraphExprs); } else { result = el; } return result; } public static Element applyGraphs(Generator<Var> varGen, Node gn, Element elt1, ExprList exprs) { //System.out.println("apply " + gn); Element result; if(!exprs.isEmpty()) { Var v; ExprList tmp; if(gn.isURI() || gn.isLiteral()) { v = varGen.next(); tmp = new ExprList(); tmp.add(NodeValue.makeNode(gn)); tmp.addAll(exprs); } else if(gn.isVariable()) { v = (Var)gn; tmp = exprs; } else if(gn.isBlank()) { v = varGen.next(); tmp = exprs; } else { throw new RuntimeException("Unexpected case"); } ExprVar ev = new ExprVar(v); Element el = new ElementNamedGraph(v, elt1); ElementFilter filter = new ElementFilter(new E_OneOf(ev, exprs)); ElementGroup group = new ElementGroup(); group.addElement(el); group.addElement(filter); result = group; } else { result = new ElementNamedGraph(gn, elt1); } return result; } @Override public Element transform(ElementNamedGraph el, Node gn, Element elt1) { Element result = applyGraphs(varGen, gn, elt1, namedGraphExprs); return result; } public static Query rewrite(Query query) { DatasetDescription dd = query.getDatasetDescription(); Query result; if(dd != null) { result = query.cloneQuery(); Element before = result.getQueryPattern(); Element after = rewrite(before, dd); result.setQueryPattern(after); } else { result = query; } return result; } public static Element rewrite(Element element, DatasetDescription dd) { final Stack<Node> graphs = new Stack<Node>(); ExprTransform exprTransform = new ExprTransformCopy(); ElementTransform elementTransform = ElementTransformDatasetDescription.create(graphs, element, dd); ElementVisitor beforeVisitor = new ElementVisitorBase() { @Override public void visit(ElementNamedGraph el) { graphs.push(el.getGraphNameNode()); //System.out.println("push " + el.getGraphNameNode()); } }; ElementVisitor afterVisitor = new ElementVisitorBase() { @Override public void visit(ElementNamedGraph el) { graphs.pop(); //System.out.println("pop " + el.getGraphNameNode()); } }; Element result = ElementTransformer.transform(element, elementTransform, exprTransform, beforeVisitor, afterVisitor); return result; } public static void main(String[] args) { //Query query = QueryFactory.create("SELECT * { { ?s ?p ?o } Union { Graph ?g { ?s ?p ?o } } }"); //Query query = QueryFactory.create("SELECT * { { { Select * { ?s ?p ?o . Filter(?p = <p>) } } } Union { Graph ?g { ?s ?p ?o } } }"); Query query = QueryFactory.create("SELECT * { { ?s ?p ?o . Graph ?x { ?a ?b ?c } } Union { Graph ?g { ?s ?p ?o } } }"); query.addGraphURI("dg1"); query.addGraphURI("dg2"); query.addNamedGraphURI("ng1"); query.addNamedGraphURI("ng2"); Query tmp = rewrite(query); Op op = Algebra.compile(tmp); Op op2 = Transformer.transformSkipService(new TransformFilterPlacement(), op) ; tmp = OpAsQuery.asQuery(op2); System.out.println(tmp); } }