package com.redspr.redquerybuilder.core.client.table;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.redspr.redquerybuilder.core.client.command.dml.Select;
import com.redspr.redquerybuilder.core.client.engine.Session;
import com.redspr.redquerybuilder.core.client.expression.ConditionAndOr;
import com.redspr.redquerybuilder.core.client.expression.Expression;
import com.redspr.redquerybuilder.core.client.util.StringUtils;
import com.redspr.redquerybuilder.core.shared.meta.Table;
public class TableFilter {
private Table table = null;
private final String alias;
private Expression joinCondition;
private Expression filterCondition;
private TableFilter join;
private boolean outerJoin;
private static Set<String> usedAliases = new HashSet<String>();
private final Session session;
public TableFilter(Session session2, Table table2, String alias2, Select select) {
this.session = session2;
this.table = table2;
this.alias = alias2;
if (table == null) {
throw new RuntimeException("Table must not be null");
}
if (alias != null) {
usedAliases.add(alias.toUpperCase());
}
}
public static String newAlias() {
int i = usedAliases.size();
while (usedAliases.contains("X" + i)) {
i++;
}
return "x" + i;
}
public static void resetAlias() {
usedAliases.clear();
}
public Table getTable() {
return table;
}
public void setTable(Table p) {
if (p == null) {
throw new RuntimeException("Table must not be null");
}
this.table = p;
}
public String getAlias() {
// if (alias == null) alias = newAlias(); // XXX not just do early?
return alias;
}
public String getTableAlias() {
if (alias != null) {
return alias;
}
return table.getName();
}
public void addJoin(TableFilter filter, boolean outer, Expression on) {
if (filter == this) {
throw new IllegalArgumentException("Reference to self");
}
if (join == null) {
this.join = filter;
filter.outerJoin = outer;
if (outer) {
// convert all inner joins on the right hand side to outer joins
TableFilter f = filter.join;
while (f != null) {
f.outerJoin = true;
f = f.join;
}
}
if (on != null) {
filter.mapAndAddFilter(on);
}
} else {
join.addJoin(filter, outer, on);
}
}
public void mapAndAddFilter(Expression on) {
// don't know what this is for on.mapColumns(this, 0);
addFilterCondition(on, true);
// on.createIndexConditions(session, this);
if (join != null) {
join.mapAndAddFilter(on);
}
}
public TableFilter getJoin() {
return join;
}
public String getSQL(boolean isJoin, List args) {
StringBuilder buff = new StringBuilder();
if (isJoin) {
if (outerJoin) {
buff.append("LEFT OUTER JOIN ");
} else {
buff.append("INNER JOIN ");
}
}
buff.append(table.getSQL());
if (alias != null) {
buff.append(' ').append(Session.quoteIdentifier(alias));
}
if (isJoin) {
buff.append(" ON ");
if (joinCondition == null) {
// need to have a ON expression, otherwise the nesting is
// unclear
buff.append("1=1");
} else {
buff.append(StringUtils.unEnclose(joinCondition.getSQL(args)));
}
}
return buff.toString();
}
public void addFilterCondition(Expression condition, boolean isJoin) {
if (isJoin) {
if (joinCondition == null) {
joinCondition = condition;
} else {
joinCondition = new ConditionAndOr(session, ConditionAndOr.AND,
joinCondition, condition);
}
} else {
if (filterCondition == null) {
filterCondition = condition;
} else {
filterCondition = new ConditionAndOr(session,
ConditionAndOr.AND, filterCondition, condition);
}
}
}
public Expression getJoinCondition() {
return joinCondition;
}
public void removeJoinCondition() {
this.joinCondition = null;
}
public void removeJoin() {
this.join = null;
}
public Session getSession() {
return session;
}
public boolean isJoinOuter() {
return outerJoin; // XXX
}
// XXX not sure about this
public void setJoin(TableFilter p) {
this.join = p;
}
@Override
public String toString() {
return table.getName() + " " + this.alias;
}
}