/*
* Licensed to Crate under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership. Crate licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial
* agreement.
*/
package io.crate.operation.scalar.arithmetic;
import io.crate.analyze.symbol.Function;
import io.crate.analyze.symbol.Symbol;
import io.crate.metadata.*;
import io.crate.data.Input;
import io.crate.operation.scalar.ScalarFunctionModule;
import io.crate.types.*;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public abstract class NegateFunction<TOut, TIn> extends Scalar<TOut, TIn> {
private final FunctionInfo info;
private final static String NAME = "_negate";
private NegateFunction(FunctionInfo info) {
this.info = info;
}
@Override
public FunctionInfo info() {
return info;
}
private static final FunctionResolver RESOLVER = new FunctionResolver() {
@Override
public FunctionImplementation getForTypes(List<DataType> dataTypes) throws IllegalArgumentException {
DataType dataType = dataTypes.get(0);
switch (dataType.id()) {
case DoubleType.ID:
return new NegateDouble();
case FloatType.ID:
return new NegateFloat();
case ShortType.ID:
return new NegateShort();
case IntegerType.ID:
return new NegateInteger();
case LongType.ID:
return new NegateLong();
}
throw new IllegalArgumentException("Cannot negate values of type " + dataType.getName());
}
@Nullable
@Override
public List<DataType> getSignature(List<DataType> dataTypes) {
return Signature.SIGNATURES_SINGLE_NUMERIC.apply(dataTypes);
}
};
public static void register(ScalarFunctionModule module) {
module.register(NAME, RESOLVER);
}
public static Function createFunction(Symbol argument) {
FunctionInfo info;
switch (argument.valueType().id()) {
case DoubleType.ID:
info = NegateDouble.INFO;
break;
case FloatType.ID:
info = NegateFloat.INFO;
break;
case ShortType.ID:
info = NegateShort.INFO;
break;
case IntegerType.ID:
info = NegateInteger.INFO;
break;
case LongType.ID:
info = NegateLong.INFO;
break;
default:
throw new IllegalArgumentException("Cannot negate values of type " + argument.valueType().getName());
}
//noinspection ArraysAsListWithZeroOrOneArgument # must use mutable list for arguments
return new Function(info, Arrays.asList(argument));
}
private static class NegateLong extends NegateFunction<Long, Long> {
private static final FunctionInfo INFO = new FunctionInfo(
new FunctionIdent(NAME, Collections.<DataType>singletonList(DataTypes.LONG)), DataTypes.LONG);
NegateLong() {
super(INFO);
}
@SafeVarargs
@Override
public final Long evaluate(Input<Long>... args) {
Long value = args[0].value();
if (value == null) {
return null;
}
return value * -1;
}
}
private static class NegateDouble extends NegateFunction<Double, Double> {
private static final FunctionInfo INFO = new FunctionInfo(
new FunctionIdent(NAME, Collections.<DataType>singletonList(DataTypes.DOUBLE)), DataTypes.DOUBLE);
NegateDouble() {
super(INFO);
}
@SafeVarargs
@Override
public final Double evaluate(Input<Double>... args) {
Double value = args[0].value();
if (value == null) {
return null;
}
return value * -1;
}
}
private static class NegateFloat extends NegateFunction<Float, Float> {
private static final FunctionInfo INFO = new FunctionInfo(
new FunctionIdent(NAME, Collections.<DataType>singletonList(DataTypes.FLOAT)), DataTypes.FLOAT);
NegateFloat() {
super(INFO);
}
@SafeVarargs
@Override
public final Float evaluate(Input<Float>... args) {
Float value = args[0].value();
if (value == null) {
return null;
}
return value * -1;
}
}
private static class NegateShort extends NegateFunction<Short, Short> {
private static final FunctionInfo INFO = new FunctionInfo(
new FunctionIdent(NAME, Collections.<DataType>singletonList(DataTypes.SHORT)), DataTypes.SHORT);
NegateShort() {
super(INFO);
}
@SafeVarargs
@Override
public final Short evaluate(Input<Short>... args) {
Short value = args[0].value();
if (value == null) {
return null;
}
return (short)(value * -1);
}
}
private static class NegateInteger extends NegateFunction<Integer, Integer> {
private static final FunctionInfo INFO = new FunctionInfo(
new FunctionIdent(NAME, Collections.<DataType>singletonList(DataTypes.INTEGER)), DataTypes.INTEGER);
NegateInteger() {
super(INFO);
}
@SafeVarargs
@Override
public final Integer evaluate(Input<Integer>... args) {
Integer value = args[0].value();
if (value == null) {
return null;
}
return value * -1;
}
}
}