blob: 18845c10a863949f89316995c3e162c435de3cf6 [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.optimize;
import org.apache.jena.sparql.algebra.Op ;
import org.apache.jena.sparql.algebra.OpVisitorByTypeBase ;
import org.apache.jena.sparql.algebra.TransformCopy ;
import org.apache.jena.sparql.algebra.Transformer ;
import org.apache.jena.sparql.algebra.op.OpModifier ;
import org.apache.jena.sparql.algebra.op.OpProject ;
import org.apache.jena.sparql.engine.Rename ;
/** Rename variables so that names can be treated globally.
* (project) and (group) can hide variables, but we only
* need to account for OpProject because group is never
* executed linearly.
*/
public class TransformScopeRename
{
// Is there an OpProject before any pattern algebra operators?
// We don't need to rename through this one.
// Track OpProject
public static Op transform(Op op)
{
return new TransformScopeRename$(op).work() ;
}
private static class TransformScopeRename$
{
private boolean outerMostOpProject = false ;
private int projectRenameDepth = 0 ;
private int projectCount = 0 ;
private Op op ;
public TransformScopeRename$(Op op)
{
this.op = op ;
{
Op op2 = op ;
while( op2 instanceof OpModifier )
{
// If already true ...
if ( op2 instanceof OpProject )
{
outerMostOpProject = true ;
break ;
}
op2 = ((OpModifier)op2).getSubOp() ;
}
}
// Set the project counter: renaming begins when this hits one.
// Set 2 to there is a project in the top-most OpModifers.
// This does not cause a rename so start renaming at depth .
// otherwise rename from depth 1.
if ( outerMostOpProject )
projectRenameDepth = 2 ;
else
projectRenameDepth = 1;
}
public Op work()
{
return Transformer.transform(new RenameByScope(), op, new BeforeWalk(), new AfterWalk()) ;
}
private class BeforeWalk extends OpVisitorByTypeBase
{
@Override
public void visit(OpProject opProject)
{
projectCount++ ;
}
}
private class AfterWalk extends OpVisitorByTypeBase
{
@Override
public void visit(OpProject opProject)
{
--projectCount ;
}
}
private class RenameByScope extends TransformCopy
{
@Override
public Op transform(OpProject opProject, Op subOp)
{
// Need to find the right project
// We already stripped outer modifier.
if ( projectCount >= projectRenameDepth )
// Inner ones already done.
subOp = Rename.renameVars(subOp, opProject.getVars()) ;
return super.transform(opProject, subOp) ;
}
}
}
}