aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/com/healthmarketscience/jackcess/impl/expr
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2018-08-24 04:11:43 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2018-08-24 04:11:43 +0000
commit5dbcd361698afc6da7e88a7186ee459a658fcf6d (patch)
tree73a180197bb853594d424e2da3b7da0cf8ff8aa1 /src/main/java/com/healthmarketscience/jackcess/impl/expr
parentf0db074605d1614a1204641607d7dbdc27d5c774 (diff)
downloadjackcess-5dbcd361698afc6da7e88a7186ee459a658fcf6d.tar.gz
jackcess-5dbcd361698afc6da7e88a7186ee459a658fcf6d.zip
minor refactor of function support; start adding top level docs for evaluation support
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1190 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src/main/java/com/healthmarketscience/jackcess/impl/expr')
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java1
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFinancialFunctions.java110
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java210
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java3
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java1
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/FunctionSupport.java241
6 files changed, 301 insertions, 265 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java
index ac5313c..83c6ee8 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java
@@ -28,6 +28,7 @@ import com.healthmarketscience.jackcess.expr.Function;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.ColumnImpl;
import static com.healthmarketscience.jackcess.impl.expr.DefaultFunctions.*;
+import static com.healthmarketscience.jackcess.impl.expr.FunctionSupport.*;
/**
*
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFinancialFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFinancialFunctions.java
index 4fe59ec..df397b0 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFinancialFunctions.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFinancialFunctions.java
@@ -21,12 +21,13 @@ import com.healthmarketscience.jackcess.expr.EvalContext;
import com.healthmarketscience.jackcess.expr.Function;
import com.healthmarketscience.jackcess.expr.Value;
import static com.healthmarketscience.jackcess.impl.expr.DefaultFunctions.*;
+import static com.healthmarketscience.jackcess.impl.expr.FunctionSupport.*;
/**
*
* @author James Ahlborn
*/
-public class DefaultFinancialFunctions
+public class DefaultFinancialFunctions
{
/** 0 - payment end of month (default) */
private static final int PMT_END_MNTH = 0;
@@ -39,14 +40,14 @@ public class DefaultFinancialFunctions
static void init() {
// dummy method to ensure this class is loaded
}
-
+
public static final Function NPER = registerFunc(new FuncVar("NPer", 3, 5) {
@Override
protected Value evalVar(EvalContext ctx, Value[] params) {
- double rate = params[0].getAsDouble();
- double pmt = params[1].getAsDouble();
- double pv = params[2].getAsDouble();
+ double rate = params[0].getAsDouble();
+ double pmt = params[1].getAsDouble();
+ double pv = params[2].getAsDouble();
double fv = 0d;
if(params.length > 3) {
@@ -71,9 +72,9 @@ public class DefaultFinancialFunctions
public static final Function FV = registerFunc(new FuncVar("FV", 3, 5) {
@Override
protected Value evalVar(EvalContext ctx, Value[] params) {
- double rate = params[0].getAsDouble();
- double nper = params[1].getAsDouble();
- double pmt = params[2].getAsDouble();
+ double rate = params[0].getAsDouble();
+ double nper = params[1].getAsDouble();
+ double pmt = params[2].getAsDouble();
double pv = 0d;
if(params.length > 3) {
@@ -98,9 +99,9 @@ public class DefaultFinancialFunctions
public static final Function PV = registerFunc(new FuncVar("PV", 3, 5) {
@Override
protected Value evalVar(EvalContext ctx, Value[] params) {
- double rate = params[0].getAsDouble();
- double nper = params[1].getAsDouble();
- double pmt = params[2].getAsDouble();
+ double rate = params[0].getAsDouble();
+ double nper = params[1].getAsDouble();
+ double pmt = params[2].getAsDouble();
double fv = 0d;
if(params.length > 3) {
@@ -125,9 +126,9 @@ public class DefaultFinancialFunctions
public static final Function PMT = registerFunc(new FuncVar("Pmt", 3, 5) {
@Override
protected Value evalVar(EvalContext ctx, Value[] params) {
- double rate = params[0].getAsDouble();
- double nper = params[1].getAsDouble();
- double pv = params[2].getAsDouble();
+ double rate = params[0].getAsDouble();
+ double nper = params[1].getAsDouble();
+ double pv = params[2].getAsDouble();
double fv = 0d;
if(params.length > 3) {
@@ -153,10 +154,10 @@ public class DefaultFinancialFunctions
// public static final Function IPMT = registerFunc(new FuncVar("IPmt", 4, 6) {
// @Override
// protected Value evalVar(EvalContext ctx, Value[] params) {
- // double rate = params[0].getAsDouble();
- // double per = params[1].getAsDouble();
- // double nper = params[2].getAsDouble();
- // double pv = params[3].getAsDouble();
+ // double rate = params[0].getAsDouble();
+ // double per = params[1].getAsDouble();
+ // double nper = params[2].getAsDouble();
+ // double pv = params[3].getAsDouble();
// double fv = 0d;
// if(params.length > 4) {
@@ -184,10 +185,10 @@ public class DefaultFinancialFunctions
// public static final Function PPMT = registerFunc(new FuncVar("PPmt", 4, 6) {
// @Override
// protected Value evalVar(EvalContext ctx, Value[] params) {
- // double rate = params[0].getAsDouble();
- // double per = params[1].getAsDouble();
- // double nper = params[2].getAsDouble();
- // double pv = params[3].getAsDouble();
+ // double rate = params[0].getAsDouble();
+ // double per = params[1].getAsDouble();
+ // double nper = params[2].getAsDouble();
+ // double pv = params[3].getAsDouble();
// double fv = 0d;
// if(params.length > 4) {
@@ -216,10 +217,10 @@ public class DefaultFinancialFunctions
// public static final Function DDB = registerFunc(new FuncVar("DDB", 4, 5) {
// @Override
// protected Value evalVar(EvalContext ctx, Value[] params) {
- // double cost = params[0].getAsDouble();
- // double salvage = params[1].getAsDouble();
- // double life = params[2].getAsDouble();
- // double period = params[3].getAsDouble();
+ // double cost = params[0].getAsDouble();
+ // double salvage = params[1].getAsDouble();
+ // double life = params[2].getAsDouble();
+ // double period = params[3].getAsDouble();
// double factor = 2d;
// if(params.length > 4) {
@@ -259,34 +260,34 @@ public class DefaultFinancialFunctions
// });
// FIXME, untested
- public static final Function SLN = registerFunc(new FuncVar("SLN", 3, 3) {
- @Override
- protected Value evalVar(EvalContext ctx, Value[] params) {
- double cost = params[0].getAsDouble();
- double salvage = params[1].getAsDouble();
- double life = params[2].getAsDouble();
+ // public static final Function SLN = registerFunc(new FuncVar("SLN", 3, 3) {
+ // @Override
+ // protected Value evalVar(EvalContext ctx, Value[] params) {
+ // double cost = params[0].getAsDouble();
+ // double salvage = params[1].getAsDouble();
+ // double life = params[2].getAsDouble();
- double result = calculateStraightLineDepreciation(cost, salvage, life);
+ // double result = calculateStraightLineDepreciation(cost, salvage, life);
- return BuiltinOperators.toValue(result);
- }
- });
+ // return BuiltinOperators.toValue(result);
+ // }
+ // });
// FIXME, untested
- public static final Function SYD = registerFunc(new FuncVar("SYD", 4, 4) {
- @Override
- protected Value evalVar(EvalContext ctx, Value[] params) {
- double cost = params[0].getAsDouble();
- double salvage = params[1].getAsDouble();
- double life = params[2].getAsDouble();
- double period = params[3].getAsDouble();
+ // public static final Function SYD = registerFunc(new FuncVar("SYD", 4, 4) {
+ // @Override
+ // protected Value evalVar(EvalContext ctx, Value[] params) {
+ // double cost = params[0].getAsDouble();
+ // double salvage = params[1].getAsDouble();
+ // double life = params[2].getAsDouble();
+ // double period = params[3].getAsDouble();
- double result = calculateSumOfYearsDepreciation(
- cost, salvage, life, period);
+ // double result = calculateSumOfYearsDepreciation(
+ // cost, salvage, life, period);
- return BuiltinOperators.toValue(result);
- }
- });
+ // return BuiltinOperators.toValue(result);
+ // }
+ // });
private static double calculateLoanPaymentPeriods(
@@ -300,9 +301,9 @@ public class DefaultFinancialFunctions
}
double v1 = Math.log(1d + (rate * pv / pmt));
-
+
double v2 = Math.log(1d + rate);
-
+
double result = -v1 / v2;
if(pmtType == PMT_BEG_MNTH) {
@@ -326,7 +327,7 @@ public class DefaultFinancialFunctions
double v1 = Math.log(1d - (rate * fv / pmt));
double v2 = Math.log(1d + rate);
-
+
double result = v1 / v2;
if(pmtType == PMT_BEG_MNTH) {
@@ -374,7 +375,7 @@ public class DefaultFinancialFunctions
}
return result;
- }
+ }
private static double calculateAnnuityPayment(
double rate, double nper, double fv, int pmtType) {
@@ -386,7 +387,7 @@ public class DefaultFinancialFunctions
}
return result;
- }
+ }
private static double calculateInterestPayment(
double pmt, double rate, double per, double pv, int pmtType) {
@@ -404,7 +405,7 @@ public class DefaultFinancialFunctions
fvPer -= 1d;
}
- double remBalance = (pv * Math.pow((1d + rate), pvPer)) -
+ double remBalance = (pv * Math.pow((1d + rate), pvPer)) -
// FIXME, always use pmtType of 0?
calculateFutureValue(rate, fvPer, pmt, PMT_END_MNTH);
@@ -437,4 +438,3 @@ public class DefaultFinancialFunctions
}
}
-
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java
index f77e0a3..bfbf105 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java
@@ -17,7 +17,6 @@ limitations under the License.
package com.healthmarketscience.jackcess.impl.expr;
import java.math.BigDecimal;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -28,6 +27,7 @@ import com.healthmarketscience.jackcess.expr.FunctionLookup;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.DatabaseImpl;
import com.healthmarketscience.jackcess.impl.NumberFormatter;
+import static com.healthmarketscience.jackcess.impl.expr.FunctionSupport.*;
/**
*
@@ -38,8 +38,6 @@ public class DefaultFunctions
private static final Map<String,Function> FUNCS =
new HashMap<String,Function>();
- private static final char NON_VAR_SUFFIX = '$';
-
static {
// load all default functions
DefaultTextFunctions.init();
@@ -57,212 +55,6 @@ public class DefaultFunctions
private DefaultFunctions() {}
- public static abstract class BaseFunction implements Function
- {
- private final String _name;
- private final int _minParams;
- private final int _maxParams;
-
- protected BaseFunction(String name, int minParams, int maxParams)
- {
- _name = name;
- _minParams = minParams;
- _maxParams = maxParams;
- }
-
- public String getName() {
- return _name;
- }
-
- public boolean isPure() {
- // most functions are probably pure, so make this the default
- return true;
- }
-
- protected void validateNumParams(Value[] params) {
- int num = params.length;
- if((num < _minParams) || (num > _maxParams)) {
- String range = ((_minParams == _maxParams) ? "" + _minParams :
- _minParams + " to " + _maxParams);
- throw new EvalException(
- "Invalid number of parameters " +
- num + " passed, expected " + range);
- }
- }
-
- protected EvalException invalidFunctionCall(
- Throwable t, Value[] params)
- {
- String paramStr = Arrays.toString(params);
- String msg = "Invalid function call {" + _name + "(" +
- paramStr.substring(1, paramStr.length() - 1) + ")}";
- return new EvalException(msg, t);
- }
-
- @Override
- public String toString() {
- return getName() + "()";
- }
- }
-
- public static abstract class Func0 extends BaseFunction
- {
- protected Func0(String name) {
- super(name, 0, 0);
- }
-
- @Override
- public boolean isPure() {
- // 0-arg functions are usually not pure
- return false;
- }
-
- public final Value eval(EvalContext ctx, Value... params) {
- try {
- validateNumParams(params);
- return eval0(ctx);
- } catch(Exception e) {
- throw invalidFunctionCall(e, params);
- }
- }
-
- protected abstract Value eval0(EvalContext ctx);
- }
-
- public static abstract class Func1 extends BaseFunction
- {
- protected Func1(String name) {
- super(name, 1, 1);
- }
-
- public final Value eval(EvalContext ctx, Value... params) {
- try {
- validateNumParams(params);
- return eval1(ctx, params[0]);
- } catch(Exception e) {
- throw invalidFunctionCall(e, params);
- }
- }
-
- protected abstract Value eval1(EvalContext ctx, Value param);
- }
-
- public static abstract class Func1NullIsNull extends BaseFunction
- {
- protected Func1NullIsNull(String name) {
- super(name, 1, 1);
- }
-
- public final Value eval(EvalContext ctx, Value... params) {
- try {
- validateNumParams(params);
- Value param1 = params[0];
- if(param1.isNull()) {
- return param1;
- }
- return eval1(ctx, param1);
- } catch(Exception e) {
- throw invalidFunctionCall(e, params);
- }
- }
-
- protected abstract Value eval1(EvalContext ctx, Value param);
- }
-
- public static abstract class Func2 extends BaseFunction
- {
- protected Func2(String name) {
- super(name, 2, 2);
- }
-
- public final Value eval(EvalContext ctx, Value... params) {
- try {
- validateNumParams(params);
- return eval2(ctx, params[0], params[1]);
- } catch(Exception e) {
- throw invalidFunctionCall(e, params);
- }
- }
-
- protected abstract Value eval2(EvalContext ctx, Value param1, Value param2);
- }
-
- public static abstract class Func3 extends BaseFunction
- {
- protected Func3(String name) {
- super(name, 3, 3);
- }
-
- public final Value eval(EvalContext ctx, Value... params) {
- try {
- validateNumParams(params);
- return eval3(ctx, params[0], params[1], params[2]);
- } catch(Exception e) {
- throw invalidFunctionCall(e, params);
- }
- }
-
- protected abstract Value eval3(EvalContext ctx,
- Value param1, Value param2, Value param3);
- }
-
- public static abstract class FuncVar extends BaseFunction
- {
- protected FuncVar(String name) {
- super(name, 0, Integer.MAX_VALUE);
- }
-
- protected FuncVar(String name, int minParams, int maxParams) {
- super(name, minParams, maxParams);
- }
-
- public final Value eval(EvalContext ctx, Value... params) {
- try {
- validateNumParams(params);
- return evalVar(ctx, params);
- } catch(Exception e) {
- throw invalidFunctionCall(e, params);
- }
- }
-
- protected abstract Value evalVar(EvalContext ctx, Value[] params);
- }
-
- public static class StringFuncWrapper implements Function
- {
- private final String _name;
- private final Function _delegate;
-
- public StringFuncWrapper(Function delegate) {
- _delegate = delegate;
- _name = _delegate.getName() + NON_VAR_SUFFIX;
- }
-
- public String getName() {
- return _name;
- }
-
- public boolean isPure() {
- return _delegate.isPure();
- }
-
- public Value eval(EvalContext ctx, Value... params) {
- Value result = _delegate.eval(ctx, params);
- if(result.isNull()) {
- // non-variant version does not do null-propagation, so force
- // exception to be thrown here
- result.getAsString();
- }
- return result;
- }
-
- @Override
- public String toString() {
- return getName() + "()";
- }
- }
-
-
public static final Function IIF = registerFunc(new Func3("IIf") {
@Override
protected Value eval3(EvalContext ctx,
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java
index d93463f..aeca27d 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java
@@ -24,6 +24,7 @@ import com.healthmarketscience.jackcess.expr.Function;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.NumberFormatter;
import static com.healthmarketscience.jackcess.impl.expr.DefaultFunctions.*;
+import static com.healthmarketscience.jackcess.impl.expr.FunctionSupport.*;
/**
*
@@ -185,7 +186,7 @@ public class DefaultNumberFunctions
});
- // public static final Function Val = registerFunc(new Func1("Val") {
+ // public static final Function VAL = registerFunc(new Func1("Val") {
// @Override
// protected Value eval1(EvalContext ctx, Value param1) {
// // FIXME, maybe leverage ExpressionTokenizer.maybeParseNumberLiteral (note, leading - or + is valid, exponent form is valid)
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java
index de1159a..18f7c1f 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java
@@ -23,6 +23,7 @@ import com.healthmarketscience.jackcess.expr.EvalException;
import com.healthmarketscience.jackcess.expr.Function;
import com.healthmarketscience.jackcess.expr.Value;
import static com.healthmarketscience.jackcess.impl.expr.DefaultFunctions.*;
+import static com.healthmarketscience.jackcess.impl.expr.FunctionSupport.*;
/**
*
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/FunctionSupport.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/FunctionSupport.java
new file mode 100644
index 0000000..bc87f59
--- /dev/null
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/FunctionSupport.java
@@ -0,0 +1,241 @@
+/*
+Copyright (c) 2018 James Ahlborn
+
+Licensed 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.
+*/
+
+package com.healthmarketscience.jackcess.impl.expr;
+
+import java.util.Arrays;
+
+import com.healthmarketscience.jackcess.expr.EvalContext;
+import com.healthmarketscience.jackcess.expr.EvalException;
+import com.healthmarketscience.jackcess.expr.Function;
+import com.healthmarketscience.jackcess.expr.Value;
+
+/**
+ *
+ * @author James Ahlborn
+ */
+public class FunctionSupport
+{
+ private static final char NON_VAR_SUFFIX = '$';
+
+ private FunctionSupport() {}
+
+ public static abstract class BaseFunction implements Function
+ {
+ private final String _name;
+ private final int _minParams;
+ private final int _maxParams;
+
+ protected BaseFunction(String name, int minParams, int maxParams)
+ {
+ _name = name;
+ _minParams = minParams;
+ _maxParams = maxParams;
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public boolean isPure() {
+ // most functions are probably pure, so make this the default
+ return true;
+ }
+
+ protected void validateNumParams(Value[] params) {
+ int num = params.length;
+ if((num < _minParams) || (num > _maxParams)) {
+ String range = ((_minParams == _maxParams) ? "" + _minParams :
+ _minParams + " to " + _maxParams);
+ throw new EvalException(
+ "Invalid number of parameters " +
+ num + " passed, expected " + range);
+ }
+ }
+
+ protected EvalException invalidFunctionCall(
+ Throwable t, Value[] params)
+ {
+ String paramStr = Arrays.toString(params);
+ String msg = "Invalid function call {" + _name + "(" +
+ paramStr.substring(1, paramStr.length() - 1) + ")}";
+ return new EvalException(msg, t);
+ }
+
+ @Override
+ public String toString() {
+ return getName() + "()";
+ }
+ }
+
+ public static abstract class Func0 extends BaseFunction
+ {
+ protected Func0(String name) {
+ super(name, 0, 0);
+ }
+
+ @Override
+ public boolean isPure() {
+ // 0-arg functions are usually not pure
+ return false;
+ }
+
+ public final Value eval(EvalContext ctx, Value... params) {
+ try {
+ validateNumParams(params);
+ return eval0(ctx);
+ } catch(Exception e) {
+ throw invalidFunctionCall(e, params);
+ }
+ }
+
+ protected abstract Value eval0(EvalContext ctx);
+ }
+
+ public static abstract class Func1 extends BaseFunction
+ {
+ protected Func1(String name) {
+ super(name, 1, 1);
+ }
+
+ public final Value eval(EvalContext ctx, Value... params) {
+ try {
+ validateNumParams(params);
+ return eval1(ctx, params[0]);
+ } catch(Exception e) {
+ throw invalidFunctionCall(e, params);
+ }
+ }
+
+ protected abstract Value eval1(EvalContext ctx, Value param);
+ }
+
+ public static abstract class Func1NullIsNull extends BaseFunction
+ {
+ protected Func1NullIsNull(String name) {
+ super(name, 1, 1);
+ }
+
+ public final Value eval(EvalContext ctx, Value... params) {
+ try {
+ validateNumParams(params);
+ Value param1 = params[0];
+ if(param1.isNull()) {
+ return param1;
+ }
+ return eval1(ctx, param1);
+ } catch(Exception e) {
+ throw invalidFunctionCall(e, params);
+ }
+ }
+
+ protected abstract Value eval1(EvalContext ctx, Value param);
+ }
+
+ public static abstract class Func2 extends BaseFunction
+ {
+ protected Func2(String name) {
+ super(name, 2, 2);
+ }
+
+ public final Value eval(EvalContext ctx, Value... params) {
+ try {
+ validateNumParams(params);
+ return eval2(ctx, params[0], params[1]);
+ } catch(Exception e) {
+ throw invalidFunctionCall(e, params);
+ }
+ }
+
+ protected abstract Value eval2(EvalContext ctx, Value param1, Value param2);
+ }
+
+ public static abstract class Func3 extends BaseFunction
+ {
+ protected Func3(String name) {
+ super(name, 3, 3);
+ }
+
+ public final Value eval(EvalContext ctx, Value... params) {
+ try {
+ validateNumParams(params);
+ return eval3(ctx, params[0], params[1], params[2]);
+ } catch(Exception e) {
+ throw invalidFunctionCall(e, params);
+ }
+ }
+
+ protected abstract Value eval3(EvalContext ctx,
+ Value param1, Value param2, Value param3);
+ }
+
+ public static abstract class FuncVar extends BaseFunction
+ {
+ protected FuncVar(String name) {
+ super(name, 0, Integer.MAX_VALUE);
+ }
+
+ protected FuncVar(String name, int minParams, int maxParams) {
+ super(name, minParams, maxParams);
+ }
+
+ public final Value eval(EvalContext ctx, Value... params) {
+ try {
+ validateNumParams(params);
+ return evalVar(ctx, params);
+ } catch(Exception e) {
+ throw invalidFunctionCall(e, params);
+ }
+ }
+
+ protected abstract Value evalVar(EvalContext ctx, Value[] params);
+ }
+
+ public static class StringFuncWrapper implements Function
+ {
+ private final String _name;
+ private final Function _delegate;
+
+ public StringFuncWrapper(Function delegate) {
+ _delegate = delegate;
+ _name = _delegate.getName() + NON_VAR_SUFFIX;
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public boolean isPure() {
+ return _delegate.isPure();
+ }
+
+ public Value eval(EvalContext ctx, Value... params) {
+ Value result = _delegate.eval(ctx, params);
+ if(result.isNull()) {
+ // non-variant version does not do null-propagation, so force
+ // exception to be thrown here
+ result.getAsString();
+ }
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return getName() + "()";
+ }
+ }
+
+}