/*
* Copyright 2009 Ralf Joachim, Ahmad Hassan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.castor.cpa.persistence.sql.query;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.castor.cpa.persistence.sql.query.condition.Condition;
import org.castor.cpa.persistence.sql.query.expression.Column;
import org.castor.cpa.persistence.sql.query.expression.Expression;
/**
* Class to generate SQL select query statements.
* <br/>
* Note: Be aware that the SQL statement will be invalid for empty compound conditions.
*
* @author <a href="mailto:ahmad DOT hassan AT gmail DOT com">Ahmad Hassan</a>
* @author <a href="mailto:ralf DOT joachim AT syscon DOT eu">Ralf Joachim</a>
* @version $Revision$ $Date: 2009-07-13 17:22:43 (Mon, 27 Jul 2009) $
*/
public final class Select implements QueryObject {
//-----------------------------------------------------------------------------------
/** List of expressions to be returned by select statement. */
private final List<Expression> _select = new ArrayList<Expression>();
/** List of qualifiers to be used in from-clause. */
private final List<Qualifier> _from = new ArrayList<Qualifier>();
/** Condition that specifies which records to select. */
private Condition _condition;
/** Flag to determine if statement should be executed with or without lock. */
private boolean _locked = false;
//-----------------------------------------------------------------------------------
/**
* Construct a SQL select statement that selects records of the table provided.
*
* @param name Name of the table to select records of.
*/
public Select(final String name) {
this(new Table(name));
}
/**
* Construct a SQL select statement that selects records of the table provided.
*
* @param qualifier Qualifier to select records of.
*/
public Select(final Qualifier qualifier) {
if (qualifier == null) { throw new NullPointerException(); }
_from.add(qualifier);
}
//-----------------------------------------------------------------------------------
/**
* Appends the provided field to the list of fields to be fetched from table.
*
* @param name Column object representing a column to be fetched.
*/
public void addSelect(final Column name) {
_select.add(name);
}
/**
* Appends the provided qualifier to the list of qualifiers to be used to build from-clause.
*
* @param qualifier Qualifier to be added to from-clause.
*/
public void addFrom(final Qualifier qualifier) {
_from.add(qualifier);
}
//-----------------------------------------------------------------------------------
/**
* Getter returning list of Expressions currently set.
*
* @return List of current expressions.
*/
public List<Expression> getSelect() { return _select; }
/**
* Getter returning from-list currently set.
*
* @return From-list currently set.
*/
public List<Qualifier> getFrom() { return _from; }
/**
* Get condition that specifies which records to select.
*
* @return Condition that specifies which records to select.
*/
public Condition getCondition() {
return _condition;
}
/**
* Set condition that specifies which records to select.
*
* @param condition Condition that specifies which records to select.
*/
public void setCondition(final Condition condition) {
_condition = condition;
}
/**
* Get locked-flag that specifies if query has to be executed in locked mode or not.
*
* @return True: execute query in locked mode, False: execute without lock.
*/
public boolean isLocked() {
return _locked;
}
/**
* Set locked-flag that specifies if query has to be executed in locked mode or not.
*
* @param locked True: execute query in locked mode, False: execute without lock.
*/
public void setLocked(final boolean locked) {
_locked = locked;
}
/**
* Method to check if qualifiers exist to add to from-clause.
*
* @return True: List of froms is not empty. False: List of froms is empty.
*/
public boolean hasFrom() {
return !_from.isEmpty();
}
//-----------------------------------------------------------------------------------
/**
* Method constructing query string.
*
* @return Constructed query string.
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(QueryConstants.SELECT);
sb.append(QueryConstants.SPACE);
if (_select.isEmpty()) {
sb.append(QueryConstants.STAR);
} else {
for (Iterator<Expression> iter = _select.iterator(); iter.hasNext(); ) {
sb.append(iter.next().toString());
if (iter.hasNext()) {
sb.append(QueryConstants.SEPERATOR);
sb.append(QueryConstants.SPACE);
}
}
}
sb.append(QueryConstants.SPACE);
sb.append(QueryConstants.FROM);
sb.append(QueryConstants.SPACE);
for (Iterator<Qualifier> iter = _from.iterator(); iter.hasNext(); ) {
Qualifier qualifier = iter.next();
if (!qualifier.hasJoin()) {
if (qualifier instanceof TableAlias) {
sb.append(((TableAlias) qualifier).getTable().toString());
sb.append(QueryConstants.SPACE);
}
sb.append(qualifier.toString());
} else {
// Open all necessary parentheses before starting any joins.
for (int i = 0; i < qualifier.getJoins().size(); i++) {
sb.append(QueryConstants.LPAREN);
}
for (int i = 0; i < qualifier.getJoins().size(); i++) {
Join join = qualifier.getJoins().get(i);
if (i == 0) {
if (qualifier instanceof TableAlias) {
sb.append(((TableAlias) qualifier).getTable().toString());
sb.append(QueryConstants.SPACE);
}
sb.append(qualifier.toString());
}
sb.append(QueryConstants.SPACE);
sb.append(join.toString());
// Close opened parentheses after every JOIN-expression in the query.
sb.append(QueryConstants.RPAREN);
}
}
if (iter.hasNext()) {
sb.append(QueryConstants.SEPERATOR);
sb.append(QueryConstants.SPACE);
}
}
if (_condition != null) {
sb.append(QueryConstants.SPACE);
sb.append(QueryConstants.WHERE);
sb.append(QueryConstants.SPACE);
sb.append(_condition.toString());
}
return sb.toString();
}
/**
* {@inheritDoc}
*/
public void accept (final Visitor visitor) { visitor.visit(this); }
//-----------------------------------------------------------------------------------
}