/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.query.sql.lang; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.teiid.core.util.EquivalenceUtil; import org.teiid.core.util.HashCodeUtil; import org.teiid.query.sql.LanguageObject; import org.teiid.query.sql.LanguageVisitor; import org.teiid.query.sql.symbol.ElementSymbol; import org.teiid.query.sql.symbol.Expression; import org.teiid.query.sql.symbol.ExpressionSymbol; import org.teiid.query.sql.symbol.MultipleElementSymbol; import org.teiid.query.sql.symbol.Symbol; import org.teiid.query.sql.visitor.SQLStringVisitor; /** * This class represents the SELECT clause of a query, which defines what elements * or expressions are returned from the query. */ public class Select implements LanguageObject { /** The set of symbols for the data elements to be selected. */ private List<Expression> symbols = new ArrayList<Expression>(); /** Flag for whether duplicate removal should be performed on the results */ private boolean distinct; // ========================================================================= // C O N S T R U C T O R S // ========================================================================= /** * Constructs a default instance of this class. */ public Select() { } /** * Constructs an instance of this class from an ordered set of symbols. * @param symbols The ordered list of symbols */ public Select( List<? extends Expression> symbols ) { this.addSymbols(symbols); } // ========================================================================= // M E T H O D S // ========================================================================= /** * Returns the number of symbols in select. * @return Get count of number of symbols in select */ public int getCount() { return symbols.size(); } /** * Checks for a Select * clause * @return True if Select * is used */ public boolean isStar() { return (symbols.size() == 1 && symbols.get(0) instanceof MultipleElementSymbol && ((MultipleElementSymbol)symbols.get(0)).getGroup() == null); } /** * Returns an ordered list of the symbols in the select. * @param Get list of SelectSymbol in SELECT */ public List<Expression> getSymbols() { return symbols; } /** * Sets an ordered list of the symbols in the select. Reuses the current symbol list. * @param symbols list of SelectSymbol in SELECT */ public void setSymbols(Collection<? extends Expression> symbols) { this.symbols.clear(); this.addSymbols(symbols); } /** * Returns the select symbol at the specified index. * @param index Index to get * @return The variable identifier at the index */ public Expression getSymbol( int index ) { return symbols.get(index); } /** * @param symbol New symbol */ public void addSymbol( Expression symbol ) { if (!(symbol instanceof Symbol) && !(symbol instanceof MultipleElementSymbol)) { symbol = new ExpressionSymbol("expr" + (this.symbols.size() + 1), symbol); //$NON-NLS-1$ } this.symbols.add(symbol); } public void addSymbols( Collection<? extends Expression> toAdd) { if (toAdd != null) { for (Expression expression : toAdd) { this.addSymbol(expression); } } } /** * Remove all current symbols */ public void clearSymbols() { symbols.clear(); } /** * Checks if a symbol is in the Select. * @param symbol Symbol to check for * @return True if the Select contains the symbol */ public boolean containsSymbol( Expression symbol ) { return symbols.contains(symbol); } /** * Set whether select is distinct. * @param isDistinct True if SELECT is distinct */ public void setDistinct(boolean isDistinct) { this.distinct = isDistinct; } /** * Checks whether the select is distinct * @return True if select is distinct */ public boolean isDistinct() { return this.distinct; } public void acceptVisitor(LanguageVisitor visitor) { visitor.visit(this); } /** * Get the ordered list of all elements returned by this select. These elements * may be ElementSymbols or ExpressionSymbols but in all cases each represents a * single column. * @return Ordered list of SingleElementSymbol */ public List<Expression> getProjectedSymbols() { ArrayList<Expression> projectedSymbols = new ArrayList<Expression>(); for (Expression symbol : symbols) { if(symbol instanceof MultipleElementSymbol) { List<ElementSymbol> multiSymbols = ((MultipleElementSymbol)symbol).getElementSymbols(); if(multiSymbols != null) { projectedSymbols.addAll(multiSymbols); } } else { projectedSymbols.add(symbol); } } return projectedSymbols; } // ========================================================================= // O V E R R I D D E N O B J E C T M E T H O D S // ========================================================================= /** * Return a deep copy of this Select. * @return Deep clone */ public Select clone() { Select copy = new Select(LanguageObject.Util.deepClone(this.symbols, Expression.class)); copy.setDistinct( isDistinct() ); return copy; } /** * Compare two Selects for equality. Order is important in the select (for * determining the order of the returned columns), so this is a compare * with order, not just a set comparison. * @param obj Other object * @return True if equal */ public boolean equals(Object obj) { if(obj == this) { return true; } if(!(obj instanceof Select)) { return false; } Select other = (Select) obj; return other.isDistinct() == isDistinct() && EquivalenceUtil.areEqual(getSymbols(), other.getSymbols()); } /** * Get hashcode for Select. WARNING: The hash code relies on the variables * in the select, so changing the variables will change the hash code, causing * a select to be lost in a hash structure. Do not hash a Select if you plan * to change it. * @return Hash code */ public int hashCode() { return HashCodeUtil.hashCode(0, getSymbols()); } /** * Returns a string representation of an instance of this class. * @return String representation of object */ public String toString() { return SQLStringVisitor.getSQLString(this); } } // END CLASS