package com.redspr.redquerybuilder.core.client.table; import java.util.ArrayList; import java.util.List; import com.redspr.redquerybuilder.core.client.engine.Session; import com.redspr.redquerybuilder.core.client.expression.Comparison; import com.redspr.redquerybuilder.core.client.expression.Expression; import com.redspr.redquerybuilder.core.client.expression.ExpressionColumn; import com.redspr.redquerybuilder.core.shared.meta.Column; import com.redspr.redquerybuilder.core.shared.meta.Constraint; import com.redspr.redquerybuilder.core.shared.meta.ConstraintReferential; import com.redspr.redquerybuilder.core.shared.meta.Operator; import com.redspr.redquerybuilder.core.shared.meta.Table; // XXX dodgy name public class JoinHelper { // private final Session session; private TableFilter parent; private final TableFilter child; private Constraint constraint; private final Expression joinCondition; // XXX not valid till isSimple called public TableFilter getParent() { return parent; } // XXX not valid till isSimple called public Constraint getConstraint() { return constraint; } public JoinHelper(TableFilter child2, Expression joinCondition2) { this.child = child2; this.joinCondition = joinCondition2; } private static boolean match(ConstraintReferential a, ConstraintReferential b) { if (match(a, b.getTable(), b.getColumns(), b.getRefTable(), b.getRefColumns())) { return true; } if (match(a, b.getRefTable(), b.getRefColumns(), b.getTable(), b.getColumns())) { return true; } return false; } private static boolean match(ConstraintReferential a, Table btl, Column[] bc, Table btr, Column[] bcr) { if (a.getTable() != btl) { return false; } if (a.getRefTable() != btr) { return false; } if (a.getColumns().length != bc.length) { return false; } // TODO 90 dont want to care about order for (int i = 0; i < bc.length; i++) { if (a.getColumns()[i] != bc[i]) { return false; } if (a.getRefColumns()[i] != bcr[i]) { return false; } } return true; } public static TableFilter getOrCreateFor(Session session, ConstraintReferential ref) { for (TableFilter tf : session.getFilters()) { // XXX not very efficient as know the ref wanted? JoinHelper jh = new JoinHelper(tf, tf.getJoinCondition()); if ((jh.isCartesian() && tf.getTable() == ref.getRefTable()) || (jh.isSimple() && jh.getConstraint() == ref)) { return tf; } } TableFilter tableFilter = session .getTableFilter(ref.getTable()); TableFilter refTableFilter = session.createTableFilter(ref .getRefTable()); Comparison joinCond = new Comparison(session, Operator.EQUAL, new ExpressionColumn(session, null, tableFilter.getAlias(), ref .getColumns()[0].getName()), new ExpressionColumn( session, null, refTableFilter.getAlias(), ref .getRefColumns()[0].getName())); tableFilter.addJoin(refTableFilter, true, joinCond); return refTableFilter; } // XXX better name "forChild" public static JoinHelper getParent(TableFilter tf) { // for (TableFilter tf2 : tf.getSession().getFilters()) { // TableFilter child2 = tf2.getJoin(); Expression joinCondition = tf.getJoinCondition(); JoinHelper thing = new JoinHelper(tf, joinCondition); if (thing.isSimple()) { return thing; } // } return null; } private boolean foo(Expression exp, List<Column> parentCols, List<Column> childCols) { if (exp instanceof Comparison) { return foo((Comparison) exp, parentCols, childCols); } return false; } private boolean foo(Comparison c, List<Column> parentCols, List<Column> childCols) { if (!Operator.EQUAL.equals(c.getOperatorName())) { return false; } if (!(c.getLeft() instanceof ExpressionColumn)) { return false; } if (!(c.getRight() instanceof ExpressionColumn)) { return false; } ExpressionColumn left = (ExpressionColumn) c.getLeft(); ExpressionColumn right = (ExpressionColumn) c.getRight(); if (left.getTableFilter() == child) { foo(right.getTableFilter()); childCols.add(left.getColumn()); parentCols.add(right.getColumn()); } else if (right.getTableFilter() == child) { foo(left.getTableFilter()); childCols.add(right.getColumn()); parentCols.add(left.getColumn()); } else { return false; } return true; } private boolean foo(TableFilter parent2) { if (parent == null) { parent = parent2; } else { if (parent != parent2) { return false; } } return true; } private boolean isCartesian() { isSimple(); return getParent() == null; } private boolean isSimple() { List<Column> parentCols = new ArrayList<Column>(); List<Column> childCols = new ArrayList<Column>(); if ( !foo(joinCondition, parentCols, childCols)) { return false; } ConstraintReferential cand = new ConstraintReferential("test", child .getTable()); cand.setRefTable(parent.getTable()); cand.setColumns(childCols.toArray(new Column[0])); cand.setRefColumns(parentCols.toArray(new Column[0])); for (Constraint c : parent.getTable().getConstraints()) { if (c instanceof ConstraintReferential) { ConstraintReferential cr = (ConstraintReferential) c; if (match(cand, cr)) { this.constraint = cr; return true; } } } return false; } }