package org.xenei.jdbc4sparql.sparql.parser.jsqlparser.functions;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.Arrays;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import org.xenei.jdbc4sparql.iface.name.ColumnName;
import org.xenei.jdbc4sparql.impl.virtual.VirtualCatalog;
import org.xenei.jdbc4sparql.impl.virtual.VirtualSchema;
import org.xenei.jdbc4sparql.impl.virtual.VirtualTable;
import org.xenei.jdbc4sparql.sparql.SparqlQueryBuilder;
import org.xenei.jdbc4sparql.sparql.parser.jsqlparser.SparqlExprVisitor.AliasInfo;
import org.xenei.jdbc4sparql.sparql.parser.jsqlparser.proxies.ExprInfoFactory;
import com.hp.hpl.jena.sparql.expr.E_NumAbs;
import com.hp.hpl.jena.sparql.expr.E_NumCeiling;
import com.hp.hpl.jena.sparql.expr.E_NumFloor;
import com.hp.hpl.jena.sparql.expr.E_NumRound;
import com.hp.hpl.jena.sparql.expr.E_Random;
import com.hp.hpl.jena.sparql.expr.Expr;
import com.hp.hpl.jena.sparql.expr.ExprAggregator;
import com.hp.hpl.jena.sparql.expr.aggregate.AggCount;
import com.hp.hpl.jena.sparql.expr.aggregate.AggCountDistinct;
import com.hp.hpl.jena.sparql.expr.aggregate.AggCountVar;
import com.hp.hpl.jena.sparql.expr.aggregate.AggCountVarDistinct;
import com.hp.hpl.jena.sparql.expr.aggregate.AggMax;
import com.hp.hpl.jena.sparql.expr.aggregate.AggMaxDistinct;
import com.hp.hpl.jena.sparql.expr.aggregate.AggMin;
import com.hp.hpl.jena.sparql.expr.aggregate.AggMinDistinct;
import com.hp.hpl.jena.sparql.expr.aggregate.AggSum;
import com.hp.hpl.jena.sparql.expr.aggregate.AggSumDistinct;
import com.hp.hpl.jena.sparql.expr.aggregate.Aggregator;
import com.hp.hpl.jena.sparql.expr.aggregate.AggregatorBase;
public class NumericFunctionHandler extends AbstractFunctionHandler {
public static final String[] NUMERIC_FUNCTIONS = {
"MAX", "MIN", "COUNT", "SUM", "ABS", "ROUND", "CEIL", "FLOOR",
"RAND"
};
private static final int MAX = 0;
private static final int MIN = 1;
private static final int COUNT = 2;
private static final int SUM = 3;
private static final int ABS = 4;
private static final int ROUND = 5;
private static final int CEIL = 6;
private static final int FLOOR = 7;
private static final int RAND = 8;
public NumericFunctionHandler(final SparqlQueryBuilder builder) {
super(builder);
}
@Override
public Expr handle(final Function func, final AliasInfo alias)
throws SQLException {
final int i = Arrays.asList(NumericFunctionHandler.NUMERIC_FUNCTIONS)
.indexOf(func.getName().toUpperCase());
switch (i) {
case MAX:
return handleAggregate(AggMaxDistinct.class, AggMax.class,
func, alias);
case MIN:
return handleAggregate(AggMinDistinct.class, AggMin.class,
func, alias);
case COUNT:
return handleAggregate(AggCountDistinct.class, AggCount.class,
AggCountVarDistinct.class, AggCountVar.class, func,
alias);
case SUM:
return handleAggregate(AggSumDistinct.class, AggSum.class,
func, alias);
case ABS:
return handleExpr1(E_NumAbs.class, func,
java.sql.Types.NUMERIC, alias);
case ROUND:
return handleExpr1(E_NumRound.class, func,
java.sql.Types.INTEGER, alias);
case CEIL:
return handleExpr1(E_NumCeiling.class, func,
java.sql.Types.INTEGER, alias);
case FLOOR:
return handleExpr1(E_NumFloor.class, func,
java.sql.Types.INTEGER, alias);
case RAND:
return handleExpr0(E_Random.class, func,
java.sql.Types.NUMERIC, alias);
default:
return null;
}
}
private Expr handleAggregate(
final Class<? extends AggregatorBase> allDistinct,
final Class<? extends AggregatorBase> all,
final Class<? extends AggregatorBase> varDistinct,
final Class<? extends AggregatorBase> var, final Function func,
final AliasInfo alias) throws SQLException {
Aggregator agg = null;
final ExpressionList l = func.getParameters();
if (l == null) {
if (func.isAllColumns()) {
try {
agg = func.isDistinct() ? allDistinct.newInstance() : all
.newInstance();
} catch (final InstantiationException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (final IllegalAccessException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
else {
throw getNoArgumentEx(func, "one");
}
}
else if (l.getExpressions().size() > 1) {
throw getToManyArgumentEx(func, "one");
}
else {
final Expression expression = (Expression) l.getExpressions()
.get(0);
expression.accept(exprVisitor);
try {
final Constructor<? extends AggregatorBase> c = func
.isDistinct() ? varDistinct.getConstructor(Expr.class)
: var.getConstructor(Expr.class);
agg = c.newInstance(exprVisitor.getResult());
} catch (final NoSuchMethodException e) {
throw new IllegalArgumentException(e.getMessage(), e);
} catch (final SecurityException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (final InstantiationException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (final IllegalAccessException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (final InvocationTargetException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
final String aliasStr = alias.getAlias();
final ExprAggregator expr = builder.register(agg,
java.sql.Types.NUMERIC, aliasStr);
final ColumnName columnName = ColumnName.getNameInstance(
VirtualCatalog.NAME, VirtualSchema.NAME, VirtualTable.NAME,
aliasStr);
return ExprInfoFactory.getInstance(expr, exprVisitor.getColumns(),
columnName);
}
private Expr handleAggregate(
final Class<? extends AggregatorBase> varDistinct,
final Class<? extends AggregatorBase> var, final Function func,
final AliasInfo alias) throws SQLException {
Aggregator agg = null;
final ExpressionList l = func.getParameters();
if (l == null) {
throw getNoArgumentEx(func, "one");
}
if (l.getExpressions().size() > 1) {
throw getToManyArgumentEx(func, "one");
}
else {
final Expression expression = (Expression) l.getExpressions()
.get(0);
expression.accept(exprVisitor);
try {
final Constructor<? extends AggregatorBase> c = func
.isDistinct() ? varDistinct.getConstructor(Expr.class)
: var.getConstructor(Expr.class);
agg = c.newInstance(exprVisitor.getResult());
} catch (final NoSuchMethodException e) {
throw new IllegalArgumentException(e.getMessage(), e);
} catch (final SecurityException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (final InstantiationException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (final IllegalAccessException e) {
throw new IllegalStateException(e.getMessage(), e);
} catch (final InvocationTargetException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
final String aliasStr = alias.getAlias();
final ExprAggregator expr = builder.register(agg,
java.sql.Types.NUMERIC, aliasStr);
final ColumnName columnName = ColumnName.getNameInstance(
VirtualCatalog.NAME, VirtualSchema.NAME, VirtualTable.NAME,
aliasStr);
return ExprInfoFactory.getInstance(expr, exprVisitor.getColumns(),
columnName);
}
}