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 - UDS/Centre de DonnĂ©es astronomiques de Strasbourg (CDS) */ import adql.db.DBColumn; import adql.query.from.ADQLTable; import adql.query.operand.ADQLColumn; /** * Represents a reference to a selected column either by an index or by a non-qualified column name/alias. * * @author Grégory Mantelet (CDS) * @version 01/2012 * * @see ADQLOrder */ public class ColumnReference implements ADQLObject { /** Position in the original ADQL query string. */ private TextPosition position = null; /** Index of a selected column. */ private int columnIndex = -1; /** Name or alias of a selected column. */ private String columnName = null; /** The corresponding column in the "database". By default, this field is automatically filled by {@link adql.db.DBChecker}. */ private DBColumn dbLink = null; /** The {@link ADQLTable} which is supposed to contain this column. By default, this field is automatically filled by {@link adql.db.DBChecker}. */ private ADQLTable adqlTable = null; /** Indicates whether the column name/alias is case sensitive. */ private boolean caseSensitive = false; /** * Builds a column reference with an index of a selected column. * * @param index Index of a selected column (from 1). * * @throws ArrayIndexOutOfBoundsException If the given index is less or equal 0. */ public ColumnReference(int index) throws ArrayIndexOutOfBoundsException{ if (index <= 0) throw new IndexOutOfBoundsException("Impossible to make a reference to the " + index + "th column: a column index must be greater or equal 1 !"); columnIndex = index; columnName = null; } /** * Builds a column reference with a name/alias of a selected column. * * @param colName A column name/alias. * * @throws NullPointerException If the given name is <i>null</i> or is an empty string. */ public ColumnReference(String colName) throws NullPointerException{ if (!setColumnName(colName)) throw new NullPointerException("Impossible to make a reference: the given column name is null or is an empty string !"); } /** * Builds a column reference by copying the given one. * * @param toCopy The column reference to copy. */ public ColumnReference(ColumnReference toCopy){ columnName = toCopy.columnName; caseSensitive = toCopy.caseSensitive; columnIndex = toCopy.columnIndex; } /** * Gets the position in the original ADQL query string. * * @return The position of this {@link ColumnReference}. */ @Override public final TextPosition getPosition(){ return position; } /** * Sets the position at which this {@link ColumnReference} has been found in the original ADQL query string. * * @param pos Position of this {@link ColumnReference}. */ public void setPosition(final TextPosition pos){ position = pos; } /** * Gets the index of the referenced column. * * @return The index of the referenced column or <i>-1</i> if this column reference has been made with a column name/alias. */ public final int getColumnIndex(){ return columnIndex; } /** * Sets the index of the referenced column. * * @param index The index of the referenced column (must be > 0). * @return <i>true</i> if the column referenced has been updated, <i>false</i> otherwise (if index <= 0). */ public final boolean setColumnIndex(int index){ if (index > 0){ columnName = null; columnIndex = index; return true; } return false; } /** * Tells whether the column is referenced by its index or by its name/alias. * * @return <i>true</i> if by index, <i>false</i> if by name/alias. */ public final boolean isIndex(){ return columnName == null; } /** * Gets the name/alias of the referenced column. * * @return The referenced column's name/alias or <i>null</i> if this column reference has been made with a column index. */ public final String getColumnName(){ return columnName; } /** * Sets the name/alias of the referenced column. * * @param name The referenced column's name/alias (must be different from <i>null</i> and from an empty string). * @return <i>true</i> if the column reference has been updated, <i>false</i> otherwise (if name is <i>null</i> or is an empty string). */ public final boolean setColumnName(String name){ if (name == null) return false; StringBuffer n = new StringBuffer(name); n.trimToSize(); if (n.length() > 1 && n.charAt(0) == '\"' && n.charAt(name.length() - 1) == '\"'){ n.deleteCharAt(0); n.deleteCharAt(n.length() - 1); n.trimToSize(); if (n.length() > 0) caseSensitive = true; } if (n.length() == 0) return false; else{ columnIndex = -1; columnName = n.toString(); return true; } } /** * Tells whether the column reference on a column name/alias is case sensitive. * * @return <i>true</i> if the column name/alias is case sensitive, <i>false</i> otherwise. */ public final boolean isCaseSensitive(){ return caseSensitive; } /** * Sets the case sensitivity on the column name/alias. * * @param sensitive <i>true</i> to make case sensitive the column name/alias, <i>false</i> otherwise. */ public final void setCaseSensitive(boolean sensitive){ caseSensitive = sensitive; } /** * Gets the corresponding {@link DBColumn}. * * @return The corresponding {@link DBColumn} if {@link #getColumnName()} is a column name (not an alias), <i>null</i> otherwise. */ public final DBColumn getDBLink(){ return dbLink; } /** * <p>Sets the {@link DBColumn} corresponding to this {@link ADQLColumn}.</p> * * <p>By default, this field is automatically filled by {@link adql.db.DBChecker}.</p> * * @param dbLink Its corresponding {@link DBColumn} if {@link #getColumnName()} is a column name (not an alias), <i>null</i> otherwise. */ public final void setDBLink(DBColumn dbLink){ this.dbLink = dbLink; } /** * Gets the {@link ADQLTable} from which this column is supposed to come. * * @return Its source table if {@link #getColumnName()} is a column name (not an alias), otherwise <i>null</i>. */ public final ADQLTable getAdqlTable(){ return adqlTable; } /** * <p>Sets the {@link ADQLTable} from which this column is supposed to come.</p> * * <p>By default, this field is automatically filled by {@link adql.db.DBChecker} when {@link adql.db.DBChecker#check(adql.query.ADQLQuery)} is called.</p> * * @param adqlTable Its source table if {@link #getColumnName()} is a column name (not an alias), <i>null</i> otherwise. */ public final void setAdqlTable(ADQLTable adqlTable){ this.adqlTable = adqlTable; } @Override public ADQLObject getCopy() throws Exception{ return new ColumnReference(this); } @Override public String getName(){ return isIndex() ? (columnIndex + "") : columnName; } @Override public final ADQLIterator adqlIterator(){ return new NullADQLIterator(); } @Override public String toADQL(){ return isIndex() ? ("" + columnIndex) : (isCaseSensitive() ? ("\"" + columnName + "\"") : columnName); } }