@Override public Boolean apply(EvaluationContext ctx, Object obj) { return delegate.apply(ctx, obj); } }
@Override public int hashCode() { int result = lowBoundary != null ? lowBoundary.hashCode() : 0; result = 31 * result + (highBoundary != null ? highBoundary.hashCode() : 0); result = 31 * result + (lowEndPoint != null ? lowEndPoint.hashCode() : 0); result = 31 * result + (highEndPoint != null ? highEndPoint.hashCode() : 0); return result; }
public FEELFnResult<List<Object>> invoke(@ParameterName( "ctx" ) EvaluationContext ctx, @ParameterName("list") List list, @ParameterName("precedes") FEELFunction function) { if ( function == null ) { return invoke( list ); } else { return invoke(list, (a, b) -> { final Object result = function.invokeReflectively(ctx, new Object[]{a, b}); if (!(result instanceof Boolean) || ((Boolean) result)) { return -1; } else { return 1; } } ); } }
put( "first name", BuiltInType.STRING ); put( "last name", BuiltInType.STRING ); }}, new HashMap<String, Object>() {{ put( "first name", "John " ); put( "last name", "Doe" ); }}, new HashMap<String,Object>() {{ put( "name", "John Doe" ); }} }, put( "person", new MapBackedType() .addField( "first name", BuiltInType.STRING ) .addField( "last name", BuiltInType.STRING ) person.put("first name", "John "); person.put("last name", "Doe"); put( "person", person ); }}, new HashMap<String,Object>() {{ put( "name", "John Doe" ); }} }, put( "person", JavaBackedType.of(Person.class) ); }}, new HashMap<String, Object>() {{ put( "person", new Person("John ", "Doe") ); }}, new HashMap<String,Object>() {{
{ "{ first name : \"Bob\", birthday : date(\"1978-09-12\"), salutation : \"Hello \"+first name }", new HashMap<String,Object>() {{ put( "first name", "Bob" ); put( "birthday", LocalDate.of(1978, 9, 12) ); put( "salutation", "Hello Bob" ); }}, null }, put( "full name", new HashMap<String,Object>() {{ put( "first name", "Bob" ); put( "last name", "Doe" ); }} ); put( "birthday", LocalDate.of(1978, 9, 12) ); put( "salutation", "Hello Bob" ); }}, null }, put( "startdate", LocalDate.of(1978, 9, 12) ); put( "enddate", LocalDate.of(1978, 10, 13) ); put( "rangedates", new RangeImpl( Range.RangeBoundary.CLOSED, LocalDate.of(1978, 9, 12), LocalDate.of(1978, 10, 13), Range.RangeBoundary.CLOSED ) ); }}, null }, return addAdditionalParameters(cases, false);
public static Object invoke(EvaluationContext feelExprCtx, Object function, Object params) { if (function == null) { feelExprCtx.notifyEvt(() -> new ASTEventBase(Severity.ERROR, Msg.createMessage(Msg.FUNCTION_NOT_FOUND, function), null)); return null; } if (function instanceof FEELFunction) { Object[] invocationParams = toFunctionParams(params); FEELFunction f = (FEELFunction) function; if (function instanceof CompiledCustomFEELFunction) { CompiledCustomFEELFunction ff = (CompiledCustomFEELFunction) function; if (ff.isProperClosure()) { return ff.invokeReflectively(ff.getEvaluationContext(), invocationParams); } } return f.invokeReflectively(feelExprCtx, invocationParams); } else if (function instanceof UnaryTest) { return ((UnaryTest) function).apply(feelExprCtx, ((List)params).get(0)); } return null; }
private Boolean in(EvaluationContext ctx, Object value, Object expr) { // need to improve this to work with unary tests if ( expr == null ) { return value == expr; } else if ( expr instanceof UnaryTest ) { return ((UnaryTest) expr).apply( ctx, value ); } else if ( expr instanceof Range ) { try { return ((Range) expr).includes( value ); } catch ( Exception e ) { ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.EXPRESSION_IS_RANGE_BUT_VALUE_IS_NOT_COMPARABLE, value.toString(), expr.toString() ), e ) ); return null; } } else if ( value != null ) { return value.equals( expr ); } else { // value == null, expr != null return Boolean.FALSE; } }
public static String formatRange(final Range val, final boolean wrapDateTimeValuesInFunctions) { final StringBuilder sb = new StringBuilder(); sb.append(val.getLowBoundary() == Range.RangeBoundary.OPEN ? "( " : "[ "); sb.append(formatValue(val.getLowEndPoint(), wrapDateTimeValuesInFunctions)); sb.append(" .. "); sb.append(formatValue(val.getHighEndPoint(), wrapDateTimeValuesInFunctions)); sb.append(val.getHighBoundary() == Range.RangeBoundary.OPEN ? " )" : " ]"); return sb.toString(); }
@Test public void testOthers() { assertThat( evaluate("ceiling( 1.01 )") , is( getBigDecimalOrNull( 2d ) ) ); assertThat( evaluate("ceiling( x )", var("x", 1.01d )) , is( getBigDecimalOrNull( 2d ) ) ); assertThat( ((Map) evaluate("{ myf : function( v1, v2 ) ceiling(v1), invoked: myf(v2: false, v1: x) }", var("x", 1.01d) )).get("invoked"), is( getBigDecimalOrNull( 2d ) ) ); assertThat( ((Map) evaluate("{ myf : function( v1, v2 ) v1, invoked: myf(v2: false, v1: x) }", var("x", 1.01d) )).get("invoked"), is( getBigDecimalOrNull( 1.01d ) ) ); assertThat( evaluate(" x.y ", var("x", new HashMap<String, Object>(){{ put("y", 1.01d); }} )), is( getBigDecimalOrNull( 1.01d ) ) ); assertThat( evaluate("ceiling( x.y )", var("x", new HashMap<String, Object>(){{ put("y", 1.01d); }} )), is( getBigDecimalOrNull( 2d ) ) ); }
/** * WARNING: do not use as JUNit's @Parameters name the index {1} within this test class, as this would result in invalid character in the XML surefire-report * Original error was: An invalid XML character (Unicode: 0x8) was found in the value of attribute "name" and element is "testcase". */ @Parameterized.Parameters(name = "{index}: {0} ") public static Collection<Object[]> data() { final Object[][] cases = new Object[][] { // string concatenation { "\"foo\"+\"bar\"", "foobar" , null}, // string escapes { "\"string with \\\"quotes\\\"\"", "string with \"quotes\"", null}, { "\"a\\b\\t\\n\\f\\r\\\"\\'\\\\\\u2202b\"", "a\b\t\n\f\r\"\'\\\u2202b", null} }; return addAdditionalParameters(cases, false); } }
@Test public void test() { assertThat( evaluateInfix( 1 , InfixOperator.LT , 2d ), is( true ) ); assertThat( evaluateInfix( 2d , InfixOperator.LT , 1 ), is( false ) ); assertThat( evaluateInfix( 1 , InfixOperator.LTE , 2d ), is( true ) ); assertThat( evaluateInfix( 2d , InfixOperator.LTE , 1 ), is( false ) ); assertThat( evaluateInfix( 1 , InfixOperator.GT , 2d ), is( false ) ); assertThat( evaluateInfix( 2d , InfixOperator.GT , 1 ), is( true ) ); assertThat( evaluateInfix( 1 , InfixOperator.GTE , 2d ), is( false ) ); assertThat( evaluateInfix( 2d , InfixOperator.GTE , 1 ), is( true ) ); }
{ "(true or false) and false", Boolean.FALSE , null} }; return addAdditionalParameters(cases, false);
@Parameterized.Parameters(name = "{3}: {0} ({1}) = {2}") public static Collection<Object[]> data() { final Object[][] cases = new Object[][] { // constants { "null", null , null}, {"true", Boolean.TRUE , null}, { "false", Boolean.FALSE , null}, // dash is an unary test that always matches, so for now, returning true. // have to double check to know if this is not the case { "-", null, FEELEvent.Severity.ERROR }, { ".872", new BigDecimal( "0.872" ) , null}, { "-.872", new BigDecimal( "-0.872" ) , null}, { "+.872", new BigDecimal( "0.872" ) , null}, { "50", new BigDecimal( "50" ) , null}, { "-50", new BigDecimal( "-50" ) , null}, { "+50", new BigDecimal( "50" ) , null}, { "50.872", new BigDecimal( "50.872" ) , null}, { "-50.567", new BigDecimal( "-50.567" ) , null}, { "+50.567", new BigDecimal( "50.567" ) , null}, // quotes are a syntactical markup character for strings, so they disappear when the expression is evaluated { "\"foo bar\"", "foo bar" , null}, { "\"šomeÚnicodeŠtriňg\"", "šomeÚnicodeŠtriňg" , null}, { "\"横綱\"", "横綱" , null}, { "\"thisIsSomeLongStringThatMustBeProcessedSoHopefullyThisTestPassWithItAndIMustWriteSomethingMoreSoItIsLongerAndLongerAndLongerAndLongerAndLongerTillItIsReallyLong\"", "thisIsSomeLongStringThatMustBeProcessedSoHopefullyThisTestPassWithItAndIMustWriteSomethingMoreSoItIsLongerAndLongerAndLongerAndLongerAndLongerTillItIsReallyLong" , null}, { "\"\"", "" , null} }; return addAdditionalParameters(cases, false); } }
@Test public void testExpression() { feel = (testFEELTarget == FEEL_TARGET.JAVA_TRANSLATED) ? FEEL.newInstance(Collections.singletonList(new DoCompileFEELProfile())) : FEEL.newInstance(); assertResult( expression, inputTypes, inputValues, result ); }
/** * Checks that a given parameter matches a single cell test * @param ctx * @param param * @param test * @return */ private boolean satisfies(EvaluationContext ctx, Object param, UnaryTest test ) { return test.apply( ctx, param ); }
private static Boolean applyUnaryTest(EvaluationContext ctx, Object test, Object target) { if (test instanceof UnaryTest) { Boolean result = ((UnaryTest) test).apply(ctx, target); return result != null && result; } else if (test == null) { return target == null ? true : null; } else { return Objects.equals(test, target); } }
private static UnaryTest negatedUnaryTest(UnaryTest orig) { return (c, left) -> { Boolean r = orig.apply(c, left); if (r == null) { return null; } return r.equals(Boolean.FALSE); }; }
private static int sortByOutputsOrder(EvaluationContext ctx, List<UnaryTest> outs, Object r1, Object r2) { boolean r1found = false; boolean r2found = false; for( int index = 0; index < outs.size() && !r1found && !r2found; index++ ) { UnaryTest ut = outs.get( index ); if( ut.apply( ctx, r1 ) ) { r1found = true; } if( ut.apply( ctx, r2 ) ) { r2found = true; } } if ( r1found && r2found ) { return 0; } else if ( r1found ) { return -1; } else if ( r2found ) { return 1; } else { return 0; } }
public static Boolean not(Object arg, UnaryTest test) { return not(test.apply(null, arg)); }
@Override public boolean evaluate(Object rawExpression, Object resultValue, Class<?> resultClass) { if (rawExpression != null && !(rawExpression instanceof String)) { throw new IllegalArgumentException("Raw expression should be a string"); } EvaluationContext evaluationContext = newEvaluationContext(); List<UnaryTest> unaryTests = feel.evaluateUnaryTests((String) rawExpression); if(unaryTests.size() < 1) { throw new IllegalArgumentException("Impossible to parse the expression '" + rawExpression + "'"); } return unaryTests.stream().allMatch(unaryTest -> unaryTest.apply(evaluationContext, resultValue)); }