
dk.eobjects.metamodel.query.FromItem Maven / Gradle / Ivy
/**
* This file is part of MetaModel.
*
* MetaModel is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MetaModel is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MetaModel. If not, see .
*/
package dk.eobjects.metamodel.query;
import org.apache.commons.lang.builder.EqualsBuilder;
import dk.eobjects.metamodel.schema.Column;
import dk.eobjects.metamodel.schema.Table;
import dk.eobjects.metamodel.schema.Relationship;
/**
* Represents a FROM item. FROM items can take different forms:
*
* - table FROMs (eg. "FROM products p")
* - join FROMs with an ON clause (eg. "FROM products p INNER JOIN orders o ON
* p.id = o.product_id")
*
- subquery FROMs (eg. "FROM (SELECT * FROM products) p")
*
*
* @see FromClause
*/
public class FromItem implements IQueryItem, Cloneable {
private static final long serialVersionUID = -6559220014058975193L;
private Table _table;
private String _alias;
private Query _subQuery;
private JoinType _join;
private FromItem _leftSide;
private FromItem _rightSide;
private SelectItem[] _leftOn;
private SelectItem[] _rightOn;
private Query _query;
private String _expression;
/**
* Private constructor, used for cloning
*/
private FromItem() {
}
/**
* Constructor for table FROM clauses
*/
public FromItem(Table table) {
_table = table;
}
/**
* Constructor for sub-query FROM clauses
*
* @param subQuery
* the subquery to use
*/
public FromItem(Query subQuery) {
_subQuery = subQuery;
}
/**
* Constructor for join FROM clauses that join two tables using their
* relationship. The primary table of the relationship will be the left side
* of the join and the foreign table of the relationship will be the right
* side of the join.
*
* @param join
* the join type to use
* @param relationship
* the relationship to use for joining the tables
*/
public FromItem(JoinType join, Relationship relationship) {
_join = join;
_leftSide = new FromItem(relationship.getPrimaryTable());
Column[] columns = relationship.getPrimaryColumns();
_leftOn = new SelectItem[columns.length];
for (int i = 0; i < columns.length; i++) {
_leftOn[i] = new SelectItem(columns[i]);
}
_rightSide = new FromItem(relationship.getForeignTable());
columns = relationship.getForeignColumns();
_rightOn = new SelectItem[columns.length];
for (int i = 0; i < columns.length; i++) {
_rightOn[i] = new SelectItem(columns[i]);
}
}
/**
* Constructor for advanced join types with custom relationships
*
* @param join
* the join type to use
* @param leftSide
* the left side of the join
* @param rightSide
* the right side of the join
* @param leftOn
* what left-side select items to use for the ON clause
* @param rightOn
* what right-side select items to use for the ON clause
*/
public FromItem(JoinType join, FromItem leftSide, FromItem rightSide,
SelectItem[] leftOn, SelectItem[] rightOn) {
_join = join;
_leftSide = leftSide;
_rightSide = rightSide;
_leftOn = leftOn;
_rightOn = rightOn;
}
/**
* Creates a single unvalidated from item based on a expression.
* Expression based from items are typically NOT datastore-neutral but are
* available for special "hacking" needs.
*
* Expression based from items can only be used for JDBC based datastores since
* they are translated directly into SQL.
*
* @param expression
* An expression to use for the from item, for example
* "MYTABLE".
*/
public FromItem(String expression) {
if (expression == null) {
throw new IllegalArgumentException("Expression cannot be null");
}
_expression = expression;
}
public String getAlias() {
return _alias;
}
public String getSameQueryAlias() {
if (_alias != null) {
return _alias;
}
if (_table != null) {
return _table.getQuotedName();
}
return null;
}
public FromItem setAlias(String alias) {
_alias = alias;
return this;
}
public Table getTable() {
return _table;
}
public Query getSubQuery() {
return _subQuery;
}
public JoinType getJoin() {
return _join;
}
public FromItem getLeftSide() {
return _leftSide;
}
public FromItem getRightSide() {
return _rightSide;
}
public SelectItem[] getLeftOn() {
return _leftOn;
}
public SelectItem[] getRightOn() {
return _rightOn;
}
public String getExpression() {
return _expression;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(toStringNoAlias());
if (_join != null && _alias != null) {
sb.insert(0, '(');
sb.append(')');
}
if (_alias != null) {
sb.append(' ');
sb.append(_alias);
}
return sb.toString();
}
public String toStringNoAlias() {
if (_expression != null) {
return _expression;
}
StringBuilder sb = new StringBuilder();
if (_table != null) {
if (_table.getSchema() != null
&& _table.getSchema().getName() != null) {
sb.append(_table.getSchema().getName() + '.');
}
sb.append(_table.getQuotedName());
} else if (_subQuery != null) {
sb.append('(' + _subQuery.toString() + ')');
} else if (_join != null) {
String leftSideAlias = _leftSide.getSameQueryAlias();
String rightSideAlias = _rightSide.getSameQueryAlias();
sb.append(_leftSide.toString() + ' ' + _join + " JOIN "
+ _rightSide.toString());
for (int i = 0; i < _leftOn.length; i++) {
if (i == 0) {
sb.append(" ON");
} else {
sb.append(" AND ");
}
SelectItem primary = _leftOn[i];
SelectItem foreign = _rightOn[i];
sb.append(' ');
if (leftSideAlias != null) {
sb.append(leftSideAlias + '.');
}
sb.append(primary.getSuperQueryAlias());
sb.append(" = ");
if (rightSideAlias != null) {
sb.append(rightSideAlias + '.');
}
sb.append(foreign.getSuperQueryAlias());
}
}
return sb.toString();
}
/**
* Gets the alias of a table, if it is registered (and visible, ie. not part
* of a sub-query) in the FromItem
*
* @param table
* the table to get the alias for
* @return the alias or null if none is found
*/
public String getAlias(Table table) {
String result = null;
if (table != null) {
// Search recursively through left and right side, unless they
// are sub-query FromItems
if (table.equals(_table)) {
result = _alias;
} else if (_join != null) {
result = _rightSide.getAlias(table);
if (result == null) {
result = _leftSide.getAlias(table);
}
}
}
return result;
}
public Query getQuery() {
return _query;
}
public IQueryItem setQuery(Query query) {
_query = query;
return this;
}
@Override
protected FromItem clone() {
FromItem f = new FromItem();
f._alias = _alias;
f._join = _join;
f._table = _table;
f._expression = _expression;
if (_subQuery != null) {
f._subQuery = _subQuery.clone();
}
if (_leftOn != null && _leftSide != null && _rightOn != null
&& _rightSide != null) {
f._leftSide = _leftSide.clone();
f._leftOn = _leftOn.clone();
f._rightSide = _rightSide.clone();
f._rightOn = _rightOn.clone();
}
return f;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof FromItem) {
FromItem that = (FromItem) obj;
EqualsBuilder eb = new EqualsBuilder();
eb.append(this.getTable(), that.getTable());
eb.append(this.getJoin(), that.getJoin());
eb.append(this.getExpression(), that.getExpression());
eb.append(this.getLeftOn(), that.getLeftOn());
eb.append(this.getLeftSide(), that.getLeftSide());
eb.append(this.getRightOn(), that.getRightOn());
eb.append(this.getRightSide(), that.getRightSide());
eb.append(this.getSubQuery(), that.getSubQuery());
eb.append(this.getAlias(), that.getAlias());
return eb.isEquals();
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy