/**
* Copyright (C) 2010-14 diirt developers. See COPYRIGHT.TXT
* All rights reserved. Use is subject to license terms. See LICENSE.TXT
*/
package org.diirt.datasource.formula;
import java.util.Arrays;
import java.util.List;
import org.diirt.datasource.util.NullUtils;
import org.diirt.vtype.VNumber;
import static org.diirt.vtype.ValueFactory.*;
import org.diirt.vtype.ValueUtil;
/**
* Abstract class for formula functions that take two integer {@link VNumber} as arguments
* and return an integer {@code VNumber}.
* <p>
* This class takes care of:
* <ul>
* <li>extracting int value from the {@code VNumber}</li>
* <li>null handling - returns null if one argument is null</li>
* <li>alarm handling - returns highest alarm</li>
* <li>time handling - returns latest time, or now if no time is available</li>
* <li>display handling - returns display none</li>
* </ul>
*
* @author shroffk
*/
public abstract class AbstractVIntNumberVIntNumberToVIntNumberFormulaFunction implements FormulaFunction {
private final String name;
private final String description;
private final List<Class<?>> argumentTypes;
private final List<String> argumentNames;
/**
* Creates a new function.
*
* @param name function name; can't be null
* @param description function description; can't be null
* @param arg1Name first argument name; can't be null
* @param arg2Name second argument name; can't be null
*/
public AbstractVIntNumberVIntNumberToVIntNumberFormulaFunction(String name, String description, String arg1Name, String arg2Name) {
// Validate parameters
if (name == null) {
throw new NullPointerException("Function name can't be null");
}
if (description == null) {
throw new NullPointerException("Function description can't be null");
}
if (arg1Name == null) {
throw new NullPointerException("First argument name can't be null");
}
if (arg2Name == null) {
throw new NullPointerException("Second argument name can't be null");
}
this.name = name;
this.description = description;
this.argumentTypes = Arrays.<Class<?>>asList(VNumber.class, VNumber.class);
this.argumentNames = Arrays.asList(arg1Name, arg2Name);
}
@Override
public final String getName() {
return name;
}
@Override
public final String getDescription() {
return description;
}
@Override
public final boolean isPure() {
return true;
}
@Override
public final boolean isVarArgs() {
return false;
}
@Override
public final List<Class<?>> getArgumentTypes() {
return argumentTypes;
}
@Override
public final List<String> getArgumentNames() {
return argumentNames;
}
@Override
public final Class<?> getReturnType() {
return VNumber.class;
}
@Override
public final Object calculate(List<Object> args) {
if (NullUtils.containsNull(args)) {
return null;
}
Number arg1 = ((VNumber) args.get(0)).getValue();
Number arg2 = ((VNumber) args.get(1)).getValue();
if (arg1 instanceof Float || arg2 instanceof Float ||
arg1 instanceof Double || arg2 instanceof Double) {
throw new IllegalArgumentException("Operator '" + getName() + "' only works with integers");
}
return newVInt(
calculate(arg1.intValue(), arg2.intValue()),
ValueUtil.highestSeverityOf(args, false),
ValueUtil.latestValidTimeOrNowOf(args),
displayNone());
}
/**
* Calculates the result based on the two arguments. This is the only
* method one has to implement.
*
* @param arg1 the first argument
* @param arg2 the second argument
* @return the result
*/
public abstract int calculate(int arg1, int arg2);
}