// Path: src/main/java/nl/vu/jena/graph/FilteredTriple.java
// public class FilteredTriple extends Triple {
// 	
// 	private Expr simpleFilter;
// 
// 	public FilteredTriple(Node s, Node p, Node o, Expr simpleFilter) {
// 		super(s, p, o);
// 		this.simpleFilter = simpleFilter;
// 	}
// 	
// 	public FilteredTriple(Triple t, Expr simpleFilter){
// 		super(t.getSubject(), t.getPredicate(), t.getMatchObject());
// 		this.simpleFilter = simpleFilter;
// 	}
// 
// 	public Expr getSimpleFilter() {
// 		return simpleFilter;
// 	}
// 
// 	public void setSimpleFilter(Expr simpleFilter) {
// 		this.simpleFilter = simpleFilter;
// 	}
// 	
// }


import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import nl.vu.jena.graph.FilteredTriple;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Node_Variable;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.sparql.algebra.Op;
import com.hp.hpl.jena.sparql.algebra.OpVars;
import com.hp.hpl.jena.sparql.algebra.TransformCopy;
import com.hp.hpl.jena.sparql.algebra.op.OpBGP;
import com.hp.hpl.jena.sparql.algebra.op.OpConditional;
import com.hp.hpl.jena.sparql.algebra.op.OpFilter;
import com.hp.hpl.jena.sparql.algebra.op.OpQuadPattern;
import com.hp.hpl.jena.sparql.algebra.op.OpSequence;
import com.hp.hpl.jena.sparql.algebra.op.OpTable;
import com.hp.hpl.jena.sparql.core.BasicPattern;
import com.hp.hpl.jena.sparql.core.Var;
import com.hp.hpl.jena.sparql.expr.E_Equals;
import com.hp.hpl.jena.sparql.expr.E_GreaterThan;
import com.hp.hpl.jena.sparql.expr.E_GreaterThanOrEqual;
import com.hp.hpl.jena.sparql.expr.E_LessThan;
import com.hp.hpl.jena.sparql.expr.E_LessThanOrEqual;
import com.hp.hpl.jena.sparql.expr.E_NotEquals;
import com.hp.hpl.jena.sparql.expr.E_NotExists;
import com.hp.hpl.jena.sparql.expr.Expr;
import com.hp.hpl.jena.sparql.expr.ExprFunction2;
import com.hp.hpl.jena.sparql.expr.ExprList;
import com.hp.hpl.jena.sparql.expr.NodeValue;
import com.hp.hpl.jena.sparql.util.VarUtils;
			varName = expr.getArg1().getExprVar().getVarName();
		}
		else{
			throw new RuntimeException("bindConstantInTriple: this shouldn't happen");
		}
		
		Triple newTriple;
		if (triple.getSubject() instanceof Node_Variable && triple.getSubject().getName().equals(varName)){
			newTriple = new Triple(val.asNode(), triple.getPredicate(), triple.getObject());
		}
		else if (triple.getPredicate() instanceof Node_Variable && triple.getPredicate().getName().equals(varName)){
			newTriple = new Triple(triple.getSubject(), val.asNode(), triple.getObject());
		}
		else if (triple.getObject() instanceof Node_Variable && triple.getObject().getName().equals(varName)){
			newTriple = new Triple(triple.getSubject(), triple.getPredicate(), val.asNode());
		}
		else{
			throw new RuntimeException("bindConstantInTriple: No triple position bound by expression value");
		}
		
		return newTriple;
	}

	private static Op transformFilterBGP(ExprList exprs, Set<Var> patternVarsScope, BasicPattern pattern)
    {
		List<Triple> triplePatterns = pattern.getList();
		for (Iterator<Expr> exprIt = exprs.iterator(); exprIt.hasNext();) {
			Expr expr = (Expr) exprIt.next();
			if (isSimpleFilter(expr)){
				List<Triple> modifiedTriplePatterns = transformSimpleFilterBGP(expr, triplePatterns);
// Path: src/main/java/nl/vu/jena/graph/FilteredTriple.java
// public class FilteredTriple extends Triple {
// 	
// 	private Expr simpleFilter;
// 
// 	public FilteredTriple(Node s, Node p, Node o, Expr simpleFilter) {
// 		super(s, p, o);
// 		this.simpleFilter = simpleFilter;
// 	}
// 	
// 	public FilteredTriple(Triple t, Expr simpleFilter){
// 		super(t.getSubject(), t.getPredicate(), t.getMatchObject());
// 		this.simpleFilter = simpleFilter;
// 	}
// 
// 	public Expr getSimpleFilter() {
// 		return simpleFilter;
// 	}
// 
// 	public void setSimpleFilter(Expr simpleFilter) {
// 		this.simpleFilter = simpleFilter;
// 	}
// 	
// }


// Path: src/main/java/nl/vu/jena/sparql/engine/optimizer/HBaseTransformFilterPlacement.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import nl.vu.jena.graph.FilteredTriple;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Node_Variable;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.sparql.algebra.Op;
import com.hp.hpl.jena.sparql.algebra.OpVars;
import com.hp.hpl.jena.sparql.algebra.TransformCopy;
import com.hp.hpl.jena.sparql.algebra.op.OpBGP;
import com.hp.hpl.jena.sparql.algebra.op.OpConditional;
import com.hp.hpl.jena.sparql.algebra.op.OpFilter;
import com.hp.hpl.jena.sparql.algebra.op.OpQuadPattern;
import com.hp.hpl.jena.sparql.algebra.op.OpSequence;
import com.hp.hpl.jena.sparql.algebra.op.OpTable;
import com.hp.hpl.jena.sparql.core.BasicPattern;
import com.hp.hpl.jena.sparql.core.Var;
import com.hp.hpl.jena.sparql.expr.E_Equals;
import com.hp.hpl.jena.sparql.expr.E_GreaterThan;
import com.hp.hpl.jena.sparql.expr.E_GreaterThanOrEqual;
import com.hp.hpl.jena.sparql.expr.E_LessThan;
import com.hp.hpl.jena.sparql.expr.E_LessThanOrEqual;
import com.hp.hpl.jena.sparql.expr.E_NotEquals;
import com.hp.hpl.jena.sparql.expr.E_NotExists;
import com.hp.hpl.jena.sparql.expr.Expr;
import com.hp.hpl.jena.sparql.expr.ExprFunction2;
import com.hp.hpl.jena.sparql.expr.ExprList;
import com.hp.hpl.jena.sparql.expr.NodeValue;
import com.hp.hpl.jena.sparql.util.VarUtils;

			varName = expr.getArg1().getExprVar().getVarName();
		}
		else{
			throw new RuntimeException("bindConstantInTriple: this shouldn't happen");
		}
		
		Triple newTriple;
		if (triple.getSubject() instanceof Node_Variable && triple.getSubject().getName().equals(varName)){
			newTriple = new Triple(val.asNode(), triple.getPredicate(), triple.getObject());
		}
		else if (triple.getPredicate() instanceof Node_Variable && triple.getPredicate().getName().equals(varName)){
			newTriple = new Triple(triple.getSubject(), val.asNode(), triple.getObject());
		}
		else if (triple.getObject() instanceof Node_Variable && triple.getObject().getName().equals(varName)){
			newTriple = new Triple(triple.getSubject(), triple.getPredicate(), val.asNode());
		}
		else{
			throw new RuntimeException("bindConstantInTriple: No triple position bound by expression value");
		}
		
		return newTriple;
	}

	private static Op transformFilterBGP(ExprList exprs, Set<Var> patternVarsScope, BasicPattern pattern)
    {
		List<Triple> triplePatterns = pattern.getList();
		for (Iterator<Expr> exprIt = exprs.iterator(); exprIt.hasNext();) {
			Expr expr = (Expr) exprIt.next();
			if (isSimpleFilter(expr)){
				List<Triple> modifiedTriplePatterns = transformSimpleFilterBGP(expr, triplePatterns);
				if (modifiedTriplePatterns != triplePatterns){