use of org.javarosa.core.model.condition.IFunctionHandler in project javarosa by opendatakit.
the class FormDef method initEvalContext.
/**
* @param ec The new Evaluation Context
*/
private void initEvalContext(EvaluationContext ec) {
if (!ec.getFunctionHandlers().containsKey("jr:itext")) {
final FormDef f = this;
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "jr:itext";
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
String textID = (String) args[0];
try {
// SUUUUPER HACKY
String form = ec.getOutputTextForm();
if (form != null) {
textID = textID + ";" + form;
String result = f.getLocalizer().getRawText(f.getLocalizer().getLocale(), textID);
return result == null ? "" : result;
} else {
String text = f.getLocalizer().getText(textID);
return text == null ? "[itext:" + textID + "]" : text;
}
} catch (NoSuchElementException nsee) {
return "[nolocale]";
}
}
@Override
public List<Class[]> getPrototypes() {
Class[] proto = { String.class };
List<Class[]> v = new ArrayList<Class[]>(1);
v.add(proto);
return v;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
});
}
/*
* function to reverse a select value into the display label for that
* choice in the question it came from
*
* arg 1: select value arg 2: string xpath referring to origin question;
* must be absolute path
*
* this won't work at all if the original label needed to be
* processed/calculated in some way (<output>s, etc.) (is this even
* allowed?) likely won't work with multi-media labels _might_ work for
* itemsets, but probably not very well or at all; could potentially work
* better if we had some context info DOES work with localization
*
* it's mainly intended for the simple case of reversing a question with
* compile-time-static fields, for use inside an <output>
*/
if (!ec.getFunctionHandlers().containsKey("jr:choice-name")) {
final FormDef f = this;
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "jr:choice-name";
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
try {
String value = (String) args[0];
String questionXpath = (String) args[1];
TreeReference ref = RestoreUtils.xfFact.ref(questionXpath);
QuestionDef q = findQuestionByRef(ref, f);
if (q == null || (q.getControlType() != Constants.CONTROL_SELECT_ONE && q.getControlType() != Constants.CONTROL_SELECT_MULTI)) {
return "";
}
// NOTE: this is highly suspect. We have no context against
// which to evaluate
// a dynamic selection list. This will generally cause that
// evaluation to break
// if any filtering is done, or, worst case, give unexpected
// results.
//
// We should hook into the existing code (FormEntryPrompt) for
// pulling
// display text for select choices. however, it's hard,
// because we don't really have
// any context to work with, and all the situations where that
// context would be used
// don't make sense for trying to reverse a select value back
// to a label in an unrelated
// expression
List<SelectChoice> choices;
ItemsetBinding itemset = q.getDynamicChoices();
if (itemset != null) {
if (itemset.getChoices() == null) {
if (ref.isAmbiguous()) {
// SurveyCTO: We need a absolute "ref" to populate the dynamic choices,
// like we do when we populate those at FormEntryPrompt (line 251).
// The "ref" here is ambiguous, so we need to make it concrete first.
ref = ref.contextualize(ec.getContextRef());
}
f.populateDynamicChoices(itemset, ref);
}
choices = itemset.getChoices();
} else {
// static choices
choices = q.getChoices();
}
if (choices != null) {
for (SelectChoice ch : choices) {
if (ch.getValue().equals(value)) {
// this is really not ideal. we should hook into the
// existing code (FormEntryPrompt) for pulling
// display text for select choices. however, it's
// hard, because we don't really have
// any context to work with, and all the situations
// where that context would be used
// don't make sense for trying to reverse a select
// value back to a label in an unrelated
// expression
String textID = ch.getTextID();
String templateStr;
if (textID != null) {
templateStr = f.getLocalizer().getText(textID);
} else {
templateStr = ch.getLabelInnerText();
}
return fillTemplateString(templateStr, ref);
}
}
}
return "";
} catch (Exception e) {
throw new WrappedException("error in evaluation of xpath function [choice-name]", e);
}
}
@Override
public List<Class[]> getPrototypes() {
Class[] proto = { String.class, String.class };
List<Class[]> v = new ArrayList<Class[]>(1);
v.add(proto);
return v;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
});
}
}
use of org.javarosa.core.model.condition.IFunctionHandler in project javarosa by opendatakit.
the class XPathFuncExpr method eval.
/**
* Evaluate the function call.
*
* First check if the function is a member of the built-in function suite. If not, then check
* for any custom handlers registered to handler the function. If not, throw and exception.
*
* Both function name and appropriate arguments are taken into account when finding a suitable
* handler. For built-in functions, the number of arguments must match; for custom functions,
* the supplied arguments must match one of the function prototypes defined by the handler.
*/
public Object eval(DataInstance model, EvaluationContext evalContext) {
String name = id.toString();
Object[] argVals = new Object[args.length];
HashMap<String, IFunctionHandler> funcHandlers = evalContext.getFunctionHandlers();
// TODO: Func handlers should be able to declare the desire for short circuiting as well
if (name.equals("if")) {
assertArgsCount(name, args, 3);
return ifThenElse(model, evalContext, args, argVals);
} else if (name.equals("coalesce")) {
assertArgsCount(name, args, 2);
argVals[0] = args[0].eval(model, evalContext);
if (!isNull(argVals[0])) {
return argVals[0];
} else {
// that was null, so try the other one...
argVals[1] = args[1].eval(model, evalContext);
return argVals[1];
}
} else if (name.equals("indexed-repeat")) {
if ((args.length == 3 || args.length == 5 || args.length == 7 || args.length == 9 || args.length == 11)) {
return indexedRepeat(model, evalContext, args, argVals);
} else {
throw new XPathUnhandledException("function \'" + name + "\' requires " + "3, 5, 7, 9 or 11 arguments. Only " + args.length + " provided.");
}
}
for (int i = 0; i < args.length; i++) {
argVals[i] = args[i].eval(model, evalContext);
}
// check built-in functions
if (name.equals("true")) {
assertArgsCount(name, args, 0);
return Boolean.TRUE;
} else if (name.equals("false")) {
assertArgsCount(name, args, 0);
return Boolean.FALSE;
} else if (name.equals("boolean")) {
assertArgsCount(name, args, 1);
return toBoolean(argVals[0]);
} else if (name.equals("number")) {
assertArgsCount(name, args, 1);
return toNumeric(argVals[0]);
} else if (name.equals("int")) {
// non-standard
assertArgsCount(name, args, 1);
return toInt(argVals[0]);
} else if (name.equals("round")) {
// Proximate XPath 3.0 and Excel-style round(value,decimal place)
final int places;
if (args.length == 1) {
places = 0;
} else {
assertArgsCount(name, args, 2);
places = toNumeric(argVals[1]).intValue();
}
return round(toNumeric(argVals[0]), places);
} else if (name.equals("string")) {
assertArgsCount(name, args, 1);
return toString(argVals[0]);
} else if (name.equals("date")) {
// non-standard
assertArgsCount(name, args, 1);
return toDate(argVals[0], false);
} else if (name.equals("date-time")) {
// non-standard -- convert double/int/string to Date object
assertArgsCount(name, args, 1);
return toDate(argVals[0], true);
} else if (name.equals("decimal-date-time")) {
// non-standard -- convert string/date to decimal days off 1970-01-01T00:00:00.000-000
assertArgsCount(name, args, 1);
return toDecimalDateTime(argVals[0], true);
} else if (name.equals("decimal-time")) {
// non-standard -- convert string/date to decimal days off 1970-01-01T00:00:00.000-000
assertArgsCount(name, args, 1);
return toDecimalDateTime(argVals[0], false);
} else if (name.equals("not")) {
assertArgsCount(name, args, 1);
return boolNot(argVals[0]);
} else if (name.equals("boolean-from-string")) {
assertArgsCount(name, args, 1);
return boolStr(argVals[0]);
} else if (name.equals("format-date")) {
assertArgsCount(name, args, 2);
return formatDateTime(argVals[0], argVals[1]);
} else if (name.equals("abs")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.abs(toDouble(argVals[0]));
} else if (name.equals("acos")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.acos(toDouble(argVals[0]));
} else if (name.equals("asin")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.asin(toDouble(argVals[0]));
} else if (name.equals("atan")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.atan(toDouble(argVals[0]));
} else if (name.equals("atan2")) {
// XPath 3.0
checkArity(name, 2, args.length);
return Math.atan2(toDouble(argVals[0]), toDouble(argVals[1]));
} else if (name.equals("cos")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.cos(toDouble(argVals[0]));
} else if (name.equals("exp")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.exp(toDouble(argVals[0]));
} else if (name.equals("exp10")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.pow(10.0, toDouble(argVals[0]));
} else if (name.equals("log")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.log(toDouble(argVals[0]));
} else if (name.equals("log10")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.log10(toDouble(argVals[0]));
} else if (name.equals("pi")) {
// XPath 3.0
checkArity(name, 0, args.length);
return Math.PI;
} else if (name.equals("sin")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.sin(toDouble(argVals[0]));
} else if (name.equals("sqrt")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.sqrt(toDouble(argVals[0]));
} else if (name.equals("tan")) {
// XPath 3.0
checkArity(name, 1, args.length);
return Math.tan(toDouble(argVals[0]));
} else if (name.equals("format-date-time")) {
// non-standard
assertArgsCount(name, args, 2);
return formatDateTime(argVals[0], argVals[1]);
} else if ((name.equals("selected") || name.equals("is-selected"))) {
// non-standard
assertArgsCount(name, args, 2);
return multiSelected(argVals[0], argVals[1], name);
} else if (name.equals("count-selected")) {
// non-standard
assertArgsCount(name, args, 1);
return countSelected(argVals[0]);
} else if (name.equals("selected-at")) {
// non-standard
assertArgsCount(name, args, 2);
return selectedAt(argVals[0], argVals[1]);
} else if (name.equals("position")) {
// TODO: Technically, only the 0 length argument is valid here.
if (args.length == 1) {
XPathNodeset nodes = (XPathNodeset) argVals[0];
if (nodes.size() == 0) {
// Will likely cause an error downstream when used in an XPath.
return (double) (1 + TreeReference.INDEX_UNBOUND);
} else {
// if or how this might manifest into a bug... .
return position(nodes.getRefAt(0));
}
} else if (args.length == 0) {
if (evalContext.getContextPosition() != -1) {
return (double) (1 + evalContext.getContextPosition());
}
return position(evalContext.getContextRef());
} else {
throw new XPathUnhandledException("function \'" + name + "\' requires either exactly one argument or no arguments. Only " + args.length + " provided.");
}
} else if (name.equals("count")) {
assertArgsCount(name, args, 1);
return count(argVals[0]);
} else if (name.equals("count-non-empty")) {
assertArgsCount(name, args, 1);
return countNonEmpty(argVals[0]);
} else if (name.equals("sum")) {
assertArgsCount(name, args, 1);
if (argVals[0] instanceof XPathNodeset) {
return sum(((XPathNodeset) argVals[0]).toArgList());
} else {
throw new XPathTypeMismatchException("not a nodeset");
}
} else if (name.equals("max")) {
if (args.length == 1 && argVals[0] instanceof XPathNodeset) {
return max(((XPathNodeset) argVals[0]).toArgList());
} else {
return max(argVals);
}
} else if (name.equals("min")) {
if (args.length == 1 && argVals[0] instanceof XPathNodeset) {
return min(((XPathNodeset) argVals[0]).toArgList());
} else {
return min(argVals);
}
} else if (name.equals("today")) {
assertArgsCount(name, args, 0);
return DateUtils.roundDate(new Date());
} else if (name.equals("now")) {
assertArgsCount(name, args, 0);
return new Date();
} else if (name.equals("concat")) {
if (args.length == 1 && argVals[0] instanceof XPathNodeset) {
return join("", ((XPathNodeset) argVals[0]).toArgList());
} else {
return join("", argVals);
}
} else if (name.equals("join") && args.length >= 1) {
if (args.length == 2 && argVals[1] instanceof XPathNodeset) {
return join(argVals[0], ((XPathNodeset) argVals[1]).toArgList());
} else {
return join(argVals[0], subsetArgList(argVals, 1));
}
} else if (name.equals("substr") && (args.length == 2 || args.length == 3)) {
return substring(argVals[0], argVals[1], args.length == 3 ? argVals[2] : null);
} else if (name.equals("contains") && args.length == 2) {
return toString(argVals[0]).contains(toString(argVals[1]));
} else if (name.equals("starts-with") && args.length == 2) {
return toString(argVals[0]).startsWith(toString(argVals[1]));
} else if (name.equals("ends-with") && args.length == 2) {
return toString(argVals[0]).endsWith(toString(argVals[1]));
} else if (name.equals("string-length")) {
assertArgsCount(name, args, 1);
return stringLength(argVals[0]);
} else if (name.equals("checklist") && args.length >= 2) {
// non-standard
if (args.length == 3 && argVals[2] instanceof XPathNodeset) {
return checklist(argVals[0], argVals[1], ((XPathNodeset) argVals[2]).toArgList());
} else {
return checklist(argVals[0], argVals[1], subsetArgList(argVals, 2));
}
} else if (name.equals("weighted-checklist") && args.length >= 2 && args.length % 2 == 0) {
// non-standard
if (args.length == 4 && argVals[2] instanceof XPathNodeset && argVals[3] instanceof XPathNodeset) {
Object[] factors = ((XPathNodeset) argVals[2]).toArgList();
Object[] weights = ((XPathNodeset) argVals[3]).toArgList();
if (factors.length != weights.length) {
throw new XPathTypeMismatchException("weighted-checklist: nodesets not same length");
}
return checklistWeighted(argVals[0], argVals[1], factors, weights);
} else {
return checklistWeighted(argVals[0], argVals[1], subsetArgList(argVals, 2, 2), subsetArgList(argVals, 3, 2));
}
} else if (name.equals("regex")) {
// non-standard
assertArgsCount(name, args, 2);
return regex(argVals[0], argVals[1]);
} else if (name.equals("depend") && args.length >= 1) {
// non-standard
return argVals[0];
} else if (name.equals("random")) {
// non-standard
assertArgsCount(name, args, 0);
// calculated expressions may be recomputed w/o warning! use with caution!!
return MathUtils.getRand().nextDouble();
} else if (name.equals("once")) {
assertArgsCount(name, args, 1);
XPathPathExpr currentFieldPathExpr = XPathPathExpr.fromRef(evalContext.getContextRef());
Object currValue = currentFieldPathExpr.eval(model, evalContext).unpack();
if (currValue == null || toString(currValue).length() == 0) {
// this is the "once" case
return argVals[0];
} else {
return currValue;
}
} else if (name.equals("uuid") && (args.length == 0 || args.length == 1)) {
// calculated expressions may be recomputed w/o warning! use with caution!!
if (args.length == 0) {
return PropertyUtils.genUUID();
}
int len = toInt(argVals[0]).intValue();
return PropertyUtils.genGUID(len);
} else if (name.equals("version")) {
// non-standard
assertArgsCount(name, args, 0);
final String formVersion = (model instanceof FormInstance) ? ((FormInstance) model).formVersion : "";
return formVersion == null ? "" : formVersion;
} else if (name.equals("property")) {
// non-standard
// return a property defined by the property manager.
// NOTE: Property should be immutable.
// i.e., does not work with 'start' or 'end' property.
assertArgsCount(name, args, 1);
String s = toString(argVals[0]);
return PropertyManager._().getSingularProperty(s);
} else if (name.equals("pow") && (args.length == 2)) {
// XPath 3.0
double a = toDouble(argVals[0]);
double b = toDouble(argVals[1]);
return Math.pow(a, b);
} else if (name.equals("enclosed-area") || name.equals("area")) {
assertArgsCount(name, args, 1);
Object argVal = argVals[0];
if (!(argVal instanceof XPathNodeset)) {
throw new XPathUnhandledException("function \'" + name + "\' requires a field as the parameter.");
}
Object[] argList = ((XPathNodeset) argVal).toArgList();
int repeatSize = argList.length;
List<GeoUtils.GPSCoordinates> gpsCoordinatesList;
if (repeatSize == 1) {
// Try to determine if the argument is of type GeoShapeData
try {
GeoShapeData geoShapeData = new GeoShapeData().cast(new UncastData(toString(argList[0])));
if (geoShapeData.points.size() <= 2) {
return 0d;
} else {
gpsCoordinatesList = new ArrayList<GeoUtils.GPSCoordinates>();
for (GeoPointData point : geoShapeData.points) {
gpsCoordinatesList.add(new GeoUtils.GPSCoordinates(point.getPart(0), point.getPart(1)));
}
}
} catch (Exception e) {
throw new XPathTypeMismatchException("The function \'" + name + "\' received a value that does not represent GPS coordinates: " + argList[0]);
}
} else {
if (repeatSize <= 2) {
return 0d;
} else {
// treat the input as a series of GeoPointData
gpsCoordinatesList = new ArrayList<GeoUtils.GPSCoordinates>();
for (Object arg : argList) {
try {
GeoPointData geoPointData = new GeoPointData().cast(new UncastData(toString(arg)));
gpsCoordinatesList.add(new GeoUtils.GPSCoordinates(geoPointData.getPart(0), geoPointData.getPart(1)));
} catch (Exception e) {
throw new XPathTypeMismatchException("The function \'" + name + "\' received a value that does not represent GPS coordinates: " + arg);
}
}
}
}
return GeoUtils.calculateAreaOfGPSPolygonOnEarthInSquareMeters(gpsCoordinatesList);
} else if (name.equals("digest") && (args.length == 2 || args.length == 3)) {
return DigestAlgorithm.from((String) argVals[1]).digest((String) argVals[0], args.length == 3 ? Encoding.from((String) argVals[2]) : Encoding.BASE64);
} else {
// check for custom handler
IFunctionHandler handler = funcHandlers.get(name);
if (handler != null) {
return evalCustomFunction(handler, argVals, evalContext);
} else {
throw new XPathUnhandledException("function \'" + name + "\'");
}
}
}
use of org.javarosa.core.model.condition.IFunctionHandler in project javarosa by opendatakit.
the class XPathEvalTest method getFunctionHandlers.
private EvaluationContext getFunctionHandlers() {
EvaluationContext ec = new EvaluationContext(null);
final Class[][] allPrototypes = { { Double.class, Double.class }, { Double.class }, { String.class, String.class }, { Double.class, String.class, Boolean.class }, { Boolean.class }, { Boolean.class, Double.class, String.class, Date.class, CustomType.class } };
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "testfunc";
}
@Override
public List<Class[]> getPrototypes() {
List<Class[]> p = new ArrayList<Class[]>();
p.add(new Class[0]);
return p;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
return TRUE;
}
});
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "regex";
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
System.out.println("EVAL REGEX TESTS:");
for (Object arg : args) {
System.out.println("REGEX ARGS: " + arg.toString());
}
// String.re args[0].
return TRUE;
}
@Override
public List<Class[]> getPrototypes() {
List<Class[]> p = new ArrayList<Class[]>();
p.add(allPrototypes[2]);
return p;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
});
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "add";
}
@Override
public List<Class[]> getPrototypes() {
List<Class[]> p = new ArrayList<Class[]>();
p.add(allPrototypes[0]);
return p;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
return (Double) args[0] + (Double) args[1];
}
});
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "proto";
}
@Override
public List<Class[]> getPrototypes() {
List<Class[]> p = new ArrayList<Class[]>();
p.add(allPrototypes[0]);
p.add(allPrototypes[1]);
p.add(allPrototypes[2]);
p.add(allPrototypes[3]);
return p;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
return printArgs(args);
}
});
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "raw";
}
@Override
public List<Class[]> getPrototypes() {
List<Class[]> p = new ArrayList<Class[]>();
p.add(allPrototypes[3]);
return p;
}
@Override
public boolean rawArgs() {
return true;
}
@Override
public boolean realTime() {
return false;
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
return printArgs(args);
}
});
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "null-proto";
}
@Override
public List<Class[]> getPrototypes() {
return null;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
return FALSE;
}
});
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "concat";
}
@Override
public List<Class[]> getPrototypes() {
return new ArrayList<Class[]>();
}
@Override
public boolean rawArgs() {
return true;
}
@Override
public boolean realTime() {
return false;
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < args.length; i++) sb.append(XPathFuncExpr.toString(args[i]));
return sb.toString();
}
});
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "convertible";
}
@Override
public List<Class[]> getPrototypes() {
List<Class[]> p = new ArrayList<Class[]>();
p.add(new Class[0]);
return p;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
return new IExprDataType() {
@Override
public Boolean toBoolean() {
return TRUE;
}
@Override
public Double toNumeric() {
return 5.0;
}
public String toString() {
return "hi";
}
};
}
});
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "inconvertible";
}
@Override
public List<Class[]> getPrototypes() {
List<Class[]> p = new ArrayList<Class[]>();
p.add(new Class[0]);
return p;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
return new Object();
}
});
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "get-custom";
}
@Override
public List<Class[]> getPrototypes() {
List<Class[]> p = new ArrayList<Class[]>();
p.add(allPrototypes[4]);
return p;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
return (Boolean) args[0] ? new CustomSubType() : new CustomType();
}
});
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "check-types";
}
@Override
public List<Class[]> getPrototypes() {
List<Class[]> p = new ArrayList<Class[]>();
p.add(allPrototypes[5]);
return p;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
if (args.length != 5 || !(args[0] instanceof Boolean) || !(args[1] instanceof Double) || !(args[2] instanceof String) || !(args[3] instanceof Date) || !(args[4] instanceof CustomType))
fail("Types in custom function handler not converted properly/prototype not matched properly");
return TRUE;
}
});
return ec;
}
Aggregations