{@code
+ * CustomFunction fooFunc = new CustomFunction("foo") {
+ * public double applyFunction(double value) {
+ * return value*Math.E;
+ * }
+ * };
+ * double varX=12d;
+ * Calculable calc = new ExpressionBuilder("foo(x)").withCustomFunction(fooFunc).withVariable("x",varX).build();
+ * assertTrue(calc.calculate() == Math.E * varX);
+ * }
+ *
+ * @author ruckus
+ *
+ */
+public abstract class CustomFunction extends CalculationToken {
+ private int argc=1;
+
+ /**
+ * create a new single value input CustomFunction with a set name
+ *
+ * @param value
+ * the name of the function (e.g. foo)
+ */
+ protected CustomFunction(String value) throws InvalidCustomFunctionException{
+ super(value);
+ for (Function f:Function.values()) {
+ if (value.equalsIgnoreCase(f.toString())){
+ throw new InvalidCustomFunctionException(value + " is already reserved as a function name");
+ }
+ }
+ }
+
+ /**
+ * create a new single value input CustomFunction with a set name
+ *
+ * @param value
+ * the name of the function (e.g. foo)
+ */
+ protected CustomFunction(String value,int argumentCount) throws InvalidCustomFunctionException{
+ super(value);
+ this.argc=argumentCount;
+ for (Function f:Function.values()) {
+ if (value.equalsIgnoreCase(f.toString())){
+ throw new InvalidCustomFunctionException(value + " is already reserved as a function name");
+ }
+ }
+ }
+
+ /**
+ * apply the function to a value
+ *
+ * @param values
+ * the values to which the function should be applied.
+ * @return the function value
+ */
+ public abstract Variable applyFunction(List