// Path: src/de/uni_koblenz/west/splendid/helpers/FilterConditionCollector.java
// public class FilterConditionCollector extends QueryModelVisitorBase<RuntimeException> {
// 
// 	public static List<ValueExpr> process(QueryModelNode node) {
// 		FilterConditionCollector collector = new FilterConditionCollector();
// 		node.visit(collector);
// 		return collector.conditions;
// 	}
// 
// 	private List<ValueExpr> conditions = new ArrayList<ValueExpr>();
// 
// 	@Override
// 	public void meet(Filter node)
// 	{
// 		node.getArg().visit(this);
// 		conditions.add(node.getCondition());
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/helpers/Format.java
// public class Format {
// 
// 	private static final StringBuffer b = new StringBuffer();
// 	private static final Formatter f = new Formatter(b, Locale.US);
// 
// 	public static synchronized String d(double value, int length) {
// 		String style = "%." + length + "f";
// 		b.setLength(0);
// 		return f.format(style, value).toString();
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/model/BindJoin.java
// public class BindJoin extends Join {
// 	
// 	public BindJoin(TupleExpr leftArg, TupleExpr rightArg) {
// 		super(leftArg, rightArg);
// 	}
// 	
// 	@Override
// 	public boolean equals(Object other) {
// 		return other instanceof BindJoin && super.equals(other);
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return super.hashCode() ^ "BindJoin".hashCode();
// 	}
// 
// 	@Override
// 	public BindJoin clone() {
// 		return (BindJoin)super.clone();
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/model/HashJoin.java
// public class HashJoin extends Join {
// 	
// 	public HashJoin(TupleExpr leftArg, TupleExpr rightArg) {
// 		super(leftArg, rightArg);
// 	}
// 	
// 	@Override
// 	public boolean equals(Object other) {
// 		return other instanceof HashJoin && super.equals(other);
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return super.hashCode() ^ "HashJoin".hashCode();
// 	}
// 
// 	@Override
// 	public HashJoin clone() {
// 		return (HashJoin)super.clone();
// 	}
// 
// }


import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openrdf.query.algebra.Filter;
import org.openrdf.query.algebra.Join;
import org.openrdf.query.algebra.StatementPattern;
import org.openrdf.query.algebra.TupleExpr;
import org.openrdf.query.algebra.ValueExpr;
import org.openrdf.query.algebra.helpers.StatementPatternCollector;
import org.openrdf.query.algebra.helpers.VarNameCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.uni_koblenz.west.splendid.helpers.FilterConditionCollector;
import de.uni_koblenz.west.splendid.helpers.Format;
import de.uni_koblenz.west.splendid.model.BindJoin;
import de.uni_koblenz.west.splendid.model.HashJoin;
			// avoid joins with cross products (without a common join variable)
			if (vars.size() == 0) continue;
			
			// create all physical join variations
			for (TupleExpr join : createPhysicalJoins(leftArg, plan)) {
				join = applyFilters(join, filters);
				newPlans.add(join);
			}
		}
		
		// only cross products possible
		if (newPlans.size() == 0) {
			for (TupleExpr plan : rightArgs) {
				// create all physical join variations
				for (TupleExpr join : createPhysicalJoins(leftArg, plan)) {
					join = applyFilters(join, filters);
					newPlans.add(join);
				}
			}
		}
		
		return newPlans;
	}
	
	private List<Join> createPhysicalJoins(TupleExpr leftArg, TupleExpr rightArg) {
		List<Join> joins = new ArrayList<Join>();
		if (bindJoin) {
			// need to clone the argument to maintain the proper parent reference
			TupleExpr left = leftArg.clone();
			TupleExpr right = rightArg.clone();
// Path: src/de/uni_koblenz/west/splendid/helpers/FilterConditionCollector.java
// public class FilterConditionCollector extends QueryModelVisitorBase<RuntimeException> {
// 
// 	public static List<ValueExpr> process(QueryModelNode node) {
// 		FilterConditionCollector collector = new FilterConditionCollector();
// 		node.visit(collector);
// 		return collector.conditions;
// 	}
// 
// 	private List<ValueExpr> conditions = new ArrayList<ValueExpr>();
// 
// 	@Override
// 	public void meet(Filter node)
// 	{
// 		node.getArg().visit(this);
// 		conditions.add(node.getCondition());
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/helpers/Format.java
// public class Format {
// 
// 	private static final StringBuffer b = new StringBuffer();
// 	private static final Formatter f = new Formatter(b, Locale.US);
// 
// 	public static synchronized String d(double value, int length) {
// 		String style = "%." + length + "f";
// 		b.setLength(0);
// 		return f.format(style, value).toString();
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/model/BindJoin.java
// public class BindJoin extends Join {
// 	
// 	public BindJoin(TupleExpr leftArg, TupleExpr rightArg) {
// 		super(leftArg, rightArg);
// 	}
// 	
// 	@Override
// 	public boolean equals(Object other) {
// 		return other instanceof BindJoin && super.equals(other);
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return super.hashCode() ^ "BindJoin".hashCode();
// 	}
// 
// 	@Override
// 	public BindJoin clone() {
// 		return (BindJoin)super.clone();
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/model/HashJoin.java
// public class HashJoin extends Join {
// 	
// 	public HashJoin(TupleExpr leftArg, TupleExpr rightArg) {
// 		super(leftArg, rightArg);
// 	}
// 	
// 	@Override
// 	public boolean equals(Object other) {
// 		return other instanceof HashJoin && super.equals(other);
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return super.hashCode() ^ "HashJoin".hashCode();
// 	}
// 
// 	@Override
// 	public HashJoin clone() {
// 		return (HashJoin)super.clone();
// 	}
// 
// }


// Path: src/de/uni_koblenz/west/splendid/optimizer/DynamicProgrammingOptimizer.java
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openrdf.query.algebra.Filter;
import org.openrdf.query.algebra.Join;
import org.openrdf.query.algebra.StatementPattern;
import org.openrdf.query.algebra.TupleExpr;
import org.openrdf.query.algebra.ValueExpr;
import org.openrdf.query.algebra.helpers.StatementPatternCollector;
import org.openrdf.query.algebra.helpers.VarNameCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.uni_koblenz.west.splendid.helpers.FilterConditionCollector;
import de.uni_koblenz.west.splendid.helpers.Format;
import de.uni_koblenz.west.splendid.model.BindJoin;
import de.uni_koblenz.west.splendid.model.HashJoin;

			// avoid joins with cross products (without a common join variable)
			if (vars.size() == 0) continue;
			
			// create all physical join variations
			for (TupleExpr join : createPhysicalJoins(leftArg, plan)) {
				join = applyFilters(join, filters);
				newPlans.add(join);
			}
		}
		
		// only cross products possible
		if (newPlans.size() == 0) {
			for (TupleExpr plan : rightArgs) {
				// create all physical join variations
				for (TupleExpr join : createPhysicalJoins(leftArg, plan)) {
					join = applyFilters(join, filters);
					newPlans.add(join);
				}
			}
		}
		
		return newPlans;
	}
	
	private List<Join> createPhysicalJoins(TupleExpr leftArg, TupleExpr rightArg) {
		List<Join> joins = new ArrayList<Join>();
		if (bindJoin) {
			// need to clone the argument to maintain the proper parent reference
			TupleExpr left = leftArg.clone();
			TupleExpr right = rightArg.clone();
			Join join = new BindJoin(left, right);