package adql.query.operand.function;
/*
* 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 2011-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institute (ARI)
*/
import adql.query.ADQLObject;
import adql.query.TextPosition;
import adql.query.operand.ADQLOperand;
/**
* It represents any SQL function (COUNT, MAX, MIN, AVG, SUM, etc...).
*
* @author Grégory Mantelet (CDS;ARI)
* @version 1.4 (06/2015)
*
* @see SQLFunctionType
*/
public class SQLFunction extends ADQLFunction {
/** Type of this SQL function. */
private final SQLFunctionType type;
/** The only parameter of this function (may be null). */
private ADQLOperand param = null;
/** Distinct values of the parameter ? */
private boolean distinct = false;
/**
* Creates a SQL function with one parameter.
*
* @param t Type of the function.
* @param operand The only parameter of this function.
* @throws NullPointerException If the given is <i>null</i> or if the given operand is <i>null</i> EXCEPT when the given type is {@link SQLFunctionType#COUNT_ALL}.
*/
public SQLFunction(SQLFunctionType t, ADQLOperand operand) throws NullPointerException{
this(t, operand, false);
}
/**
* Creates a SQL function with one parameter.
*
* @param t Type of the function.
* @param operand The only parameter of this function.
* @param distinctValues <i>true</i> if the quantifier DISTINCT must be used, <i>false</i> otherwise (ALL).
* @throws NullPointerException If the given is <i>null</i> or if the given operand is <i>null</i> EXCEPT when the given type is {@link SQLFunctionType#COUNT_ALL}.
*/
public SQLFunction(SQLFunctionType t, ADQLOperand operand, boolean distinctValues) throws NullPointerException{
if (t == null)
throw new NullPointerException("Impossible to build a SQLFunction without its type (COUNT, SUM, AVG, ...) !");
else
type = t;
if (type == SQLFunctionType.COUNT_ALL)
param = null;
else if (operand == null)
throw new NullPointerException("Impossible to build the SQL function \"" + type.name() + "\" without the operand on which it must apply !");
else
param = operand;
distinct = distinctValues;
}
/**
* Builds a SQL function by copying the given one.
*
* @param toCopy The SQL function to copy.
* @throws Exception If there is an error during the copy.
*/
public SQLFunction(SQLFunction toCopy) throws Exception{
type = toCopy.type;
param = (ADQLOperand)toCopy.param.getCopy();
distinct = toCopy.distinct;
setPosition((toCopy.getPosition() == null) ? null : new TextPosition(toCopy.getPosition()));;
}
/**
* Indicates whether values of the parameter must be distinct or not.
*
* @return <i>true</i> means distinct values, <i>false</i> else.
*/
public final boolean isDistinct(){
return distinct;
}
/**
* Tells if distinct values of the given parameter must be taken.
*
* @param distinctValues <i>true</i> means distinct values, <i>false</i> else.
*/
public void setDistinct(boolean distinctValues){
distinct = distinctValues;
setPosition(null);
}
/**
* Gets the type (COUNT, SUM, AVG, ...) of this function.
*
* @return Its type.
*/
public final SQLFunctionType getType(){
return type;
}
@Override
public ADQLObject getCopy() throws Exception{
return new SQLFunction(this);
}
@Override
public String getName(){
return type.name();
}
@Override
public final boolean isNumeric(){
return true;
}
@Override
public final boolean isString(){
return false;
}
@Override
public final boolean isGeometry(){
return false;
}
@Override
public ADQLOperand[] getParameters(){
if (param != null)
return new ADQLOperand[]{param};
else
return new ADQLOperand[0];
}
@Override
public int getNbParameters(){
return (type == SQLFunctionType.COUNT_ALL) ? 0 : 1;
}
@Override
public ADQLOperand getParameter(int index) throws ArrayIndexOutOfBoundsException{
if (index < 0 || index >= getNbParameters())
throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + type.name() + "\" !");
else
return param;
}
@Override
public ADQLOperand setParameter(int index, ADQLOperand replacer) throws ArrayIndexOutOfBoundsException, NullPointerException, Exception{
if (index < 0 || index >= getNbParameters())
throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + type.name() + "\" !");
if (replacer == null)
throw new NullPointerException("Impossible to remove the only required parameter of the function \"" + type.name() + "\" !");
ADQLOperand replaced = param;
param = replacer;
setPosition(null);
return replaced;
}
@Override
public String toADQL(){
if (type == SQLFunctionType.COUNT_ALL)
return "COUNT(" + (distinct ? "DISTINCT " : "") + "*)";
else
return getName() + "(" + (distinct ? "DISTINCT " : "") + param.toADQL() + ")";
}
}