blob: 6616342dcd73a0fbbcdfcd590352ab5a5b7eba71 [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.sparql.algebra;
import java.util.Deque ;
import org.apache.jena.graph.Node ;
import org.apache.jena.sparql.algebra.AlgebraQuad.QuadSlot ;
import org.apache.jena.sparql.algebra.op.* ;
import org.apache.jena.sparql.core.Quad;
import org.apache.jena.sparql.core.Var ;
import org.apache.jena.sparql.expr.ExprVar ;
/**
* Transform that rewrites an algebra into quad form
*
*/
public class TransformQuadGraph extends TransformCopy
{
private Deque<QuadSlot> tracker ;
private OpVisitor beforeVisitor ;
private OpVisitor afterVisitor ;
public TransformQuadGraph(Deque<QuadSlot> tracker, OpVisitor before, OpVisitor after) {
this.tracker = tracker ;
this.beforeVisitor = before ;
this.afterVisitor = after ;
}
protected Node getNode() { return tracker.peek().rewriteGraphName ; }
@Override
public Op transform(OpGraph opGraph, Op op) {
// ?? Could just leave the (graph) in place always - just rewrite BGPs.
boolean noPattern = false ;
/* One case to consider is when the pattern for the GRAPH
* statement includes uses the variable inside the GRAPH clause.
* In this case, we must rename away the inner variable
* to allow stream execution via index joins,
* and then put back the value via an assign.
* (This is what QueryIterGraph does using a streaming join
* for triples)
*/
// Note: op is already quads by this point.
// Must test scoping by the subOp of GRAPH
QuadSlot qSlot = tracker.peek() ;
Node actualName= qSlot.actualGraphName ;
Node rewriteName= qSlot.rewriteGraphName ;
if ( OpBGP.isBGP(op) )
{
// Empty BGP
if ( ((OpBGP)op).getPattern().isEmpty() )
noPattern = true ;
}
else if ( op instanceof OpTable )
{
// Empty BGP compiled to a unit table
if ( ((OpTable)op).isJoinIdentity() )
noPattern = true ;
}
if ( noPattern )
{
// The case of something like:
// GRAPH ?g {} or GRAPH <v> {}
// which are ways of accessing the names in the dataset.
return new OpDatasetNames(opGraph.getNode()) ;
}
if ( actualName != rewriteName )
op = OpAssign.assign(op, Var.alloc(actualName), new ExprVar(rewriteName)) ;
// Drop (graph...) because inside nodes
// have been converted to quads.
return op ;
}
@Override
public Op transform(OpPropFunc opPropFunc, Op subOp) {
if ( opPropFunc.getSubOp() != subOp )
opPropFunc = new OpPropFunc(opPropFunc.getProperty(), opPropFunc.getSubjectArgs(), opPropFunc.getObjectArgs(), subOp) ;
// Put the (graph) back round it so the property function works on the named graph.
return new OpGraph(getNode() , opPropFunc) ;
}
@Override
public Op transform(OpFind opFind) {
// Put the (graph) back round it so FIND works on the named graph.
return new OpGraph(getNode() , opFind) ;
}
@Override
public Op transform(OpPath opPath) {
return new OpGraph(getNode() , opPath) ;
// Does not get removed by transform above because this is
// not the OpGraph that gets walked by the transform.
}
@Override
public Op transform(OpBGP opBGP) {
return new OpQuadPattern(getNode(), opBGP.getPattern()) ;
}
@Override
public Op transform(OpTriple opTriple) {
return new OpQuad(Quad.create(getNode(), opTriple.getTriple()));
}
@Override
public Op transform(OpExt opExt) {
return opExt.apply(this, beforeVisitor, afterVisitor) ;
}
}