package adql.query; /* * This file is part of ADQLLibrary. * * ADQLLibrary 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 3 of the License, or * (at your option) any later version. * * ADQLLibrary 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 ADQLLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2012-2016 - UDS/Centre de DonnĂ©es astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institute (ARI) */ import java.util.NoSuchElementException; import adql.query.operand.ADQLOperand; import adql.query.operand.Concatenation; /** * <p>Represents an item of a SELECT clause.</p> * * <p>It merely encapsulates an operand and allows to associate to it an alias (according to the following syntax: "SELECT operand AS alias").</p> * * @author Grégory Mantelet (CDS;ARI) * @version 1.4 (03/2016) * * @see ClauseSelect */ public class SelectItem implements ADQLObject { /** The corresponding operand. */ private ADQLOperand operand; /** Alias of the operand (ADQL syntax: "AS alias"). */ private String alias = null; /** Indicates whether the alias is case sensitive (if yes, the alias is written between double-quotes). */ private boolean caseSensitive = false; /** Position of this Select item in the ADQL query string. * @since 1.4 */ private TextPosition position = null; /** * Builds a SELECT item just with an operand. * * @param operand Corresponding operand. */ public SelectItem(ADQLOperand operand){ this(operand, null); } /** * Builds a SELECT item with an operand and its alias. * * @param operand Corresponding operand. * @param alias Operand alias. */ public SelectItem(ADQLOperand operand, String alias){ this.operand = operand; setAlias(alias); } /** * Builds a SELECT item by copying the given one. * * @param toCopy The SELECT item to copy. * @throws Exception If there is an error during the copy. */ public SelectItem(SelectItem toCopy) throws Exception{ if (toCopy.getOperand() != null) operand = (ADQLOperand)toCopy.getOperand().getCopy(); else operand = null; alias = toCopy.getAlias(); caseSensitive = toCopy.caseSensitive; position = (toCopy.position == null) ? null : new TextPosition(toCopy.position); } /** * Gets the corresponding operand. * * @return The corresponding operand. */ public final ADQLOperand getOperand(){ return operand; } /** * Indicates whether the corresponding operand has an alias. * * @return <i>true</i> if there is an alias, <i>false</i> otherwise. */ public final boolean hasAlias(){ return alias != null; } /** * Gets the alias of the corresponding operand. * * @return Alias of the operand. */ public final String getAlias(){ return alias; } /** * Changes the alias of the corresponding operand. * * @param newAlias The new alias of the operand. */ public final void setAlias(String newAlias){ if (alias == null && newAlias != null || alias != null && newAlias == null || alias != null && !alias.equals(newAlias)) position = null; alias = newAlias; caseSensitive = false; if (alias != null){ StringBuffer a = new StringBuffer(alias); a.trimToSize(); if (a.length() == 0){ alias = null; position = null; return; }else if (a.length() > 1 && a.charAt(0) == '\"' && a.charAt(a.length() - 1) == '\"'){ a.deleteCharAt(0); a.deleteCharAt(a.length() - 1); a.trimToSize(); if (a.length() == 0){ alias = null; position = null; return; } caseSensitive = true; } alias = a.toString(); } } /** * Tells whether the alias is case sensitive. * * @return <i>true</i> if the alias is case sensitive, <i>false</i> otherwise. */ public final boolean isCaseSensitive(){ return caseSensitive; } /** * Sets the case sensitivity on the alias. * * @param sensitive <i>true</i> to make case sensitive the alias, <i>false</i> otherwise. */ public final void setCaseSensitive(boolean sensitive){ caseSensitive = sensitive; } @Override public final TextPosition getPosition(){ return position; } /** * Set the position of this {@link SelectItem} in the given ADQL query string. * * @param position New position of this {@link SelectItem}. * @since 1.4 */ public final void setPosition(final TextPosition position){ this.position = position; } @Override public ADQLObject getCopy() throws Exception{ return new SelectItem(this); } @Override public String getName(){ if (hasAlias()) return alias; else if (operand instanceof Concatenation) return "concat"; else return operand.getName(); } @Override public ADQLIterator adqlIterator(){ return new ADQLIterator(){ private boolean operandGot = (operand == null); @Override public ADQLObject next() throws NoSuchElementException{ if (operandGot) throw new NoSuchElementException(); operandGot = true; return operand; } @Override public boolean hasNext(){ return !operandGot; } @Override public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{ if (replacer == null) remove(); else if (!operandGot) throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !"); else if (!(replacer instanceof ADQLOperand)) throw new IllegalStateException("Impossible to replace an ADQLOperand by a " + replacer.getClass().getName() + " !"); else{ operand = (ADQLOperand)replacer; position = null; } } @Override public void remove(){ if (!operandGot) throw new IllegalStateException("remove() impossible: next() has not yet been called !"); else throw new UnsupportedOperationException("Impossible to remove the only operand (" + operand.toADQL() + ") from a SelectItem (" + toADQL() + ") !"); } }; } @Override public String toADQL(){ StringBuffer adql = new StringBuffer(operand.toADQL()); if (hasAlias()){ adql.append(" AS "); if (isCaseSensitive()) adql.append('\"').append(alias).append('\"'); else adql.append(alias); } return adql.toString(); } }