blob: 71dd5e30471ecb05586fd215238593eef2f8ad86 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.arq.querybuilder.rewriters;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.jena.graph.Node ;
import org.apache.jena.graph.Triple;
import org.apache.jena.query.SortCondition ;
import org.apache.jena.shared.JenaException;
import org.apache.jena.sparql.algebra.Op ;
import org.apache.jena.sparql.algebra.OpVisitor ;
import org.apache.jena.sparql.algebra.Table ;
import org.apache.jena.sparql.algebra.op.* ;
import org.apache.jena.sparql.algebra.table.TableN ;
import org.apache.jena.sparql.core.* ;
import org.apache.jena.sparql.engine.binding.Binding ;
import org.apache.jena.sparql.expr.ExprAggregator ;
import org.apache.jena.sparql.expr.ExprList ;
import org.apache.jena.sparql.pfunction.PropFuncArg ;
/**
* A rewriter that implements OpVisitor.
*
*/
class OpRewriter extends AbstractRewriter<Op> implements OpVisitor {
/**
* Constructor.
* @param values The values to replace.
*/
OpRewriter(Map<Var, Node> values) {
super(values);
}
private Quad rewrite(Quad q) {
return new Quad(changeNode(q.getGraph()), changeNode(q.getSubject()),
changeNode(q.getPredicate()), changeNode(q.getObject()));
}
private QuadPattern rewrite(QuadPattern pattern) {
QuadPattern qp = new QuadPattern();
for (Quad q : pattern.getList()) {
qp.add(rewrite(q));
}
return qp;
}
private List<Op> rewriteOpList(List<Op> lst) {
List<Op> retval = new ArrayList<>();
for (Op o : lst) {
o.visit(this);
retval.add(pop());
}
return retval;
}
private BasicPattern rewrite(BasicPattern pattern) {
return BasicPattern.wrap(rewrite(pattern.getList()));
}
@Override
public void visit(OpBGP opBGP) {
push(new OpBGP(rewrite(opBGP.getPattern())));
}
@Override
public void visit(OpQuadPattern quadPattern) {
push(new OpQuadPattern(changeNode(quadPattern.getGraphNode()),
rewrite(quadPattern.getBasicPattern())));
}
@Override
public void visit(OpQuadBlock quadBlock) {
push(new OpQuadBlock(rewrite(quadBlock.getPattern())));
}
@Override
public void visit(OpTriple opTriple) {
push(new OpTriple(rewrite(opTriple.getTriple())));
}
@Override
public void visit(OpQuad opQuad) {
push(new OpQuad(rewrite(opQuad.getQuad())));
}
@Override
public void visit(OpPath opPath) {
push(new OpPath(rewrite(opPath.getTriplePath())));
}
@Override
public void visit(OpFind opFind) {
Var var = opFind.getVar();
Triple triple = opFind.getTriple();
Node n2 = changeNode(var);
if ( ! Var.isVar(n2) )
throw new JenaException("OpFind: Write if not a variable");
Var var2 = Var.alloc(n2);
Triple triple2 = rewrite(triple);
push(new OpFind(triple2, var2));
}
@Override
public void visit(OpTable opTable) {
Table tbl = opTable.getTable();
boolean process = false;
for (Var v : tbl.getVars()) {
process = process | values.keySet().contains(v);
}
if (!process) {
push(opTable);
} else {
TableN retTbl = new TableN(tbl.getVars());
Iterator<Binding> iter = tbl.rows();
while (iter.hasNext()) {
retTbl.addBinding(rewrite(iter.next()));
}
push(OpTable.create(retTbl));
}
}
@Override
public void visit(OpNull opNull) {
push(opNull);
}
@Override
public void visit(OpProcedure opProc) {
opProc.getSubOp().visit(this);
Op op = pop();
ExprList args = new ExprRewriter(values).rewrite(opProc.getArgs());
Node procId = changeNode(opProc.getProcId());
push(new OpProcedure(procId, args, op));
}
private PropFuncArg rewrite(PropFuncArg arg) {
if (arg.isList()) {
List<Node> lst = changeNodes(arg.getArgList());
return new PropFuncArg(lst, null);
}
return new PropFuncArg(changeNode(arg.getArg()));
}
@Override
public void visit(OpPropFunc opPropFunc) {
opPropFunc.getSubOp().visit(this);
Op op = pop();
Node uri = changeNode(opPropFunc.getProperty());
PropFuncArg args1 = rewrite(opPropFunc.getSubjectArgs());
PropFuncArg args2 = rewrite(opPropFunc.getObjectArgs());
push(new OpPropFunc(uri, args1, args2, op));
}
@Override
public void visit(OpFilter opFilter) {
opFilter.getSubOp().visit(this);
push(OpFilter.filterBy(
new ExprRewriter(values).rewrite(opFilter.getExprs()), pop()));
}
@Override
public void visit(OpGraph opGraph) {
opGraph.getSubOp().visit(this);
push(new OpGraph(changeNode(opGraph.getNode()), pop()));
}
@Override
public void visit(OpService opService) {
opService.getSubOp().visit(this);
push(new OpService(changeNode(opService.getService()), pop(),
opService.getSilent()));
}
@Override
public void visit(OpDatasetNames dsNames) {
push(new OpDatasetNames(changeNode(dsNames.getGraphNode())));
}
@Override
public void visit(OpLabel opLabel) {
if (opLabel.hasSubOp()) {
opLabel.getSubOp().visit(this);
push(OpLabel.create(opLabel.getObject(), pop()));
} else {
push(opLabel);
}
}
@Override
public void visit(OpAssign opAssign) {
opAssign.getSubOp().visit(this);
push(OpAssign.assign(pop(), rewrite(opAssign.getVarExprList())));
}
@Override
public void visit(OpExtend opExtend) {
opExtend.getSubOp().visit(this);
push(OpExtend.extend(pop(), rewrite(opExtend.getVarExprList())));
}
@Override
public void visit(OpJoin opJoin) {
opJoin.getRight().visit(this);
opJoin.getLeft().visit(this);
push(OpJoin.create(pop(), pop()));
}
@Override
public void visit(OpLeftJoin opLeftJoin) {
opLeftJoin.getRight().visit(this);
opLeftJoin.getLeft().visit(this);
push(OpLeftJoin.create(pop(), pop(),
new ExprRewriter(values).rewrite(opLeftJoin.getExprs())));
}
@Override
public void visit(OpUnion opUnion) {
opUnion.getRight().visit(this);
opUnion.getLeft().visit(this);
push(OpUnion.create(pop(), pop()));
}
@Override
public void visit(OpDiff opDiff) {
opDiff.getRight().visit(this);
opDiff.getLeft().visit(this);
push(OpDiff.create(pop(), pop()));
}
@Override
public void visit(OpMinus opMinus) {
opMinus.getRight().visit(this);
opMinus.getLeft().visit(this);
push(OpMinus.create(pop(), pop()));
}
@Override
public void visit(OpConditional opCondition) {
opCondition.getRight().visit(this);
opCondition.getLeft().visit(this);
push(new OpConditional(pop(), pop()));
}
@Override
public void visit(OpSequence opSequence) {
List<Op> lst = rewriteOpList(opSequence.getElements());
push(opSequence.copy(lst));
}
@Override
public void visit(OpDisjunction opDisjunction) {
List<Op> lst = rewriteOpList(opDisjunction.getElements());
push(opDisjunction.copy(lst));
}
@Override
public void visit(OpExt opExt) {
push(opExt);
}
@Override
public void visit(OpList opList) {
opList.getSubOp().visit(this);
push(new OpList(pop()));
}
@Override
public void visit(OpOrder opOrder) {
List<SortCondition> lst = new ExprRewriter(values)
.rewriteSortConditionList(opOrder.getConditions());
opOrder.getSubOp().visit(this);
push(new OpOrder(pop(), lst));
}
@Override
public void visit(OpProject opProject) {
opProject.getSubOp().visit(this);
List<Var> vars = new ArrayList<>();
for (Var v : opProject.getVars()) {
Node n = changeNode(v);
vars.add(Var.alloc(n));
}
push(new OpProject(pop(), vars));
}
@Override
public void visit(OpReduced opReduced) {
opReduced.getSubOp().visit(this);
push(opReduced.copy(pop()));
}
@Override
public void visit(OpDistinct opDistinct) {
opDistinct.getSubOp().visit(this);
push(opDistinct.copy(pop()));
}
@Override
public void visit(OpSlice opSlice) {
opSlice.getSubOp().visit(this);
push(opSlice.copy(pop()));
}
@Override
public void visit(OpGroup opGroup) {
opGroup.getSubOp().visit(this);
ExprRewriter expRewriter = new ExprRewriter(values);
VarExprList groupVars = rewrite(opGroup.getGroupVars());
List<ExprAggregator> aggregators = new ArrayList<>();
for (ExprAggregator ea : opGroup.getAggregators()) {
ea.visit(expRewriter);
aggregators.add((ExprAggregator) expRewriter.pop());
}
push(new OpGroup(pop(), groupVars, aggregators));
}
@Override
public void visit(OpTopN opTop) {
opTop.getSubOp().visit(this);
ExprRewriter expRewriter = new ExprRewriter(values);
expRewriter.rewriteSortConditionList(opTop.getConditions());
push(new OpTopN(pop(), opTop.getLimit(),
expRewriter.rewriteSortConditionList(opTop.getConditions())));
}
}