package org.activityinfo.model.expr.functions; import com.google.common.base.Preconditions; import org.activityinfo.model.type.FieldType; import org.activityinfo.model.type.FieldValue; import org.activityinfo.model.type.number.Quantity; import org.activityinfo.model.type.number.QuantityType; import java.util.List; public abstract class RealValuedBinaryFunction extends ExprFunction { private String name; protected RealValuedBinaryFunction(String name) { this.name = name; } @Override public FieldValue apply(List<FieldValue> arguments) { Preconditions.checkState(arguments.size() == 2); Quantity qa = Casting.toQuantity(arguments.get(0)); Quantity qb = Casting.toQuantity(arguments.get(1)); double value = apply(qa.getValue(), qb.getValue()); if(Double.isNaN(value)) { return new Quantity(Double.NaN); } else { if(qa.hasUnits() && qb.hasUnits()) { return new Quantity(value); } else { return new Quantity(value, applyUnits(qa.getUnits(), qb.getUnits())); } } } protected abstract double apply(double a, double b); protected abstract String applyUnits(String a, String b); @Override public final String getId() { return name; } @Override public final String getLabel() { return name; } @Override public FieldType resolveResultType(List<FieldType> argumentTypes) { Preconditions.checkArgument(argumentTypes.size() == 2); if(argumentTypes.get(0) instanceof QuantityType && argumentTypes.get(1) instanceof QuantityType) { QuantityType t1 = (QuantityType) argumentTypes.get(0); QuantityType t2 = (QuantityType) argumentTypes.get(1); return new QuantityType().setUnits(applyUnits(t1.getUnits(), t2.getUnits())); } else { throw new UnsupportedOperationException("todo"); } } }