// Path: src/main/java/org/deri/cqels/data/Mapping.java
// public interface Mapping extends Map<Var, Long>{
// 	
// 
// 	public long get(Var var); 
// 	
// 	public void from(OpRouter router);
// 	
// 	public OpRouter from();
// 	
// 	public ExecContext getCtx();
// 	
// 	public Iterator<Var> vars();
// 	
// 	public void addParent(Mapping parent);
// 	
// 	public boolean hasParent();
// 	
// 	public boolean isCompatible(Mapping mapping);
// }
// 
// Path: src/main/java/org/deri/cqels/lang/cqels/ElementStreamGraph.java
// public class ElementStreamGraph extends ElementNamedGraph {
// 	private Window window;
// 	public ElementStreamGraph(Node n, Window w, Element el) {
// 		super(n, el);
// 		window = w;
// 	}
// 	
// 	public Window getWindow() {	return window; }
// }
// 
// Path: src/main/java/org/deri/cqels/lang/cqels/OpStream.java
// public class OpStream extends OpQuadPattern {
// 	Window window;
// 	public OpStream(Node node,BasicPattern pattern, Window window) {
// 		super(node, pattern);
// 		this.window=window;
// 	}
// 	
// 	public OpStream(Node node, Triple triple, Window window) {
// 		this(node, BasicPattern.wrap(Arrays.asList(triple)), window);
// 	}
// 	public Window getWindow() {
// 		return window;
// 	}
// 	/*
// 	public void vars(Set<Var> acc){
// 		addVar(acc,getGraphNode());
// 		addVarsFromTriple(acc, ((OpTriple)getSubOp()).getTriple());
// 	}
// 	
// 	private static void addVarsFromTriple(Collection<Var> acc, Triple t)
// 	{
// 	        addVar(acc, t.getSubject()) ;
// 	        addVar(acc, t.getPredicate()) ;
// 	        addVar(acc, t.getObject()) ;
// 	}
// 	private static void addVar(Collection<Var> acc, Node n)
//     {
//         if ( n == null )
//             return ;
//         
//         if ( n.isVariable() )
//             acc.add(Var.alloc(n)) ;
//     }*/
// 
// }


import com.espertech.esper.client.EPStatement;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.sparql.algebra.Op;
import com.hp.hpl.jena.sparql.algebra.OpVars;
import com.hp.hpl.jena.sparql.algebra.op.OpDistinct;
import com.hp.hpl.jena.sparql.algebra.op.OpExtend;
import com.hp.hpl.jena.sparql.algebra.op.OpFilter;
import com.hp.hpl.jena.sparql.algebra.op.OpJoin;
import com.hp.hpl.jena.sparql.algebra.op.OpProject;
import com.hp.hpl.jena.sparql.core.Quad;
import com.hp.hpl.jena.sparql.core.TriplePath;
import com.hp.hpl.jena.sparql.core.Var;
import com.hp.hpl.jena.sparql.expr.Expr;
import com.hp.hpl.jena.sparql.expr.ExprAggregator;
import com.hp.hpl.jena.sparql.syntax.Element;
import com.hp.hpl.jena.sparql.syntax.ElementBind;
import com.hp.hpl.jena.sparql.syntax.ElementFilter;
import com.hp.hpl.jena.sparql.syntax.ElementGroup;
import com.hp.hpl.jena.sparql.syntax.ElementNamedGraph;
import com.hp.hpl.jena.sparql.syntax.ElementPathBlock;
import com.hp.hpl.jena.sparql.syntax.ElementTriplesBlock;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.jena.atlas.lib.SetUtils;
import org.deri.cqels.data.Mapping;
import org.deri.cqels.lang.cqels.ElementStreamGraph;
import org.deri.cqels.lang.cqels.OpStream;
package org.deri.cqels.engine;


/**
 * This class uses heuristic approach to build an execution plan
 *
 * @author	Danh Le Phuoc
 * @author Chan Le Van
 * @organization DERI Galway, NUIG, Ireland www.deri.ie
 * @email danh.lephuoc@deri.org
 * @email chan.levan@deri.org
 */
public class HeuristicRoutingPolicy extends RoutingPolicyBase {

    public HeuristicRoutingPolicy(ExecContext context) {
        super(context);
        this.compiler = new LogicCompiler();
        this.compiler.set(this);
    }

    /**
     * Creating the policy to route the mapping data
     *
     * @param query
     * @return a router representing a tree of operators
     */
    @Override
    public OpRouter generateRoutingPolicy(Query query) {
        ElementGroup group = (ElementGroup) query.getQueryPattern();

        /* devide operators into three groups */
        ArrayList<ElementFilter> filters = new ArrayList<ElementFilter>();
        ArrayList<ElementBind> binds = new ArrayList<ElementBind>();
// Path: src/main/java/org/deri/cqels/data/Mapping.java
// public interface Mapping extends Map<Var, Long>{
// 	
// 
// 	public long get(Var var); 
// 	
// 	public void from(OpRouter router);
// 	
// 	public OpRouter from();
// 	
// 	public ExecContext getCtx();
// 	
// 	public Iterator<Var> vars();
// 	
// 	public void addParent(Mapping parent);
// 	
// 	public boolean hasParent();
// 	
// 	public boolean isCompatible(Mapping mapping);
// }
// 
// Path: src/main/java/org/deri/cqels/lang/cqels/ElementStreamGraph.java
// public class ElementStreamGraph extends ElementNamedGraph {
// 	private Window window;
// 	public ElementStreamGraph(Node n, Window w, Element el) {
// 		super(n, el);
// 		window = w;
// 	}
// 	
// 	public Window getWindow() {	return window; }
// }
// 
// Path: src/main/java/org/deri/cqels/lang/cqels/OpStream.java
// public class OpStream extends OpQuadPattern {
// 	Window window;
// 	public OpStream(Node node,BasicPattern pattern, Window window) {
// 		super(node, pattern);
// 		this.window=window;
// 	}
// 	
// 	public OpStream(Node node, Triple triple, Window window) {
// 		this(node, BasicPattern.wrap(Arrays.asList(triple)), window);
// 	}
// 	public Window getWindow() {
// 		return window;
// 	}
// 	/*
// 	public void vars(Set<Var> acc){
// 		addVar(acc,getGraphNode());
// 		addVarsFromTriple(acc, ((OpTriple)getSubOp()).getTriple());
// 	}
// 	
// 	private static void addVarsFromTriple(Collection<Var> acc, Triple t)
// 	{
// 	        addVar(acc, t.getSubject()) ;
// 	        addVar(acc, t.getPredicate()) ;
// 	        addVar(acc, t.getObject()) ;
// 	}
// 	private static void addVar(Collection<Var> acc, Node n)
//     {
//         if ( n == null )
//             return ;
//         
//         if ( n.isVariable() )
//             acc.add(Var.alloc(n)) ;
//     }*/
// 
// }


// Path: src/main/java/org/deri/cqels/engine/HeuristicRoutingPolicy.java
import com.espertech.esper.client.EPStatement;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.sparql.algebra.Op;
import com.hp.hpl.jena.sparql.algebra.OpVars;
import com.hp.hpl.jena.sparql.algebra.op.OpDistinct;
import com.hp.hpl.jena.sparql.algebra.op.OpExtend;
import com.hp.hpl.jena.sparql.algebra.op.OpFilter;
import com.hp.hpl.jena.sparql.algebra.op.OpJoin;
import com.hp.hpl.jena.sparql.algebra.op.OpProject;
import com.hp.hpl.jena.sparql.core.Quad;
import com.hp.hpl.jena.sparql.core.TriplePath;
import com.hp.hpl.jena.sparql.core.Var;
import com.hp.hpl.jena.sparql.expr.Expr;
import com.hp.hpl.jena.sparql.expr.ExprAggregator;
import com.hp.hpl.jena.sparql.syntax.Element;
import com.hp.hpl.jena.sparql.syntax.ElementBind;
import com.hp.hpl.jena.sparql.syntax.ElementFilter;
import com.hp.hpl.jena.sparql.syntax.ElementGroup;
import com.hp.hpl.jena.sparql.syntax.ElementNamedGraph;
import com.hp.hpl.jena.sparql.syntax.ElementPathBlock;
import com.hp.hpl.jena.sparql.syntax.ElementTriplesBlock;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.jena.atlas.lib.SetUtils;
import org.deri.cqels.data.Mapping;
import org.deri.cqels.lang.cqels.ElementStreamGraph;
import org.deri.cqels.lang.cqels.OpStream;

package org.deri.cqels.engine;


/**
 * This class uses heuristic approach to build an execution plan
 *
 * @author	Danh Le Phuoc
 * @author Chan Le Van
 * @organization DERI Galway, NUIG, Ireland www.deri.ie
 * @email danh.lephuoc@deri.org
 * @email chan.levan@deri.org
 */
public class HeuristicRoutingPolicy extends RoutingPolicyBase {

    public HeuristicRoutingPolicy(ExecContext context) {
        super(context);
        this.compiler = new LogicCompiler();
        this.compiler.set(this);
    }

    /**
     * Creating the policy to route the mapping data
     *
     * @param query
     * @return a router representing a tree of operators
     */
    @Override
    public OpRouter generateRoutingPolicy(Query query) {
        ElementGroup group = (ElementGroup) query.getQueryPattern();

        /* devide operators into three groups */
        ArrayList<ElementFilter> filters = new ArrayList<ElementFilter>();
        ArrayList<ElementBind> binds = new ArrayList<ElementBind>();
        ArrayList<OpStream> streamOps = new ArrayList<OpStream>();