public static Object notifyCompilationError(EvaluationContext feelExprCtx, String message) { feelExprCtx.notifyEvt(() -> new ASTEventBase(Severity.ERROR, message, null)); return null; }
public static Boolean coerceToBoolean(EvaluationContext ctx, Object value) { if (value == null || value instanceof Boolean) { return (Boolean) value; } ctx.notifyEvt(() -> new ASTEventBase( FEELEvent.Severity.ERROR, Msg.createMessage( Msg.X_TYPE_INCOMPATIBLE_WITH_Y_TYPE, value == null ? "null" : value.getClass(), "Boolean"), null)); return null; }
private Object withIndex(Object filterIndex) { if (value == null) { return null; } List list = value instanceof List ? (List) value : Arrays.asList(value); if (filterIndex instanceof Number) { int i = ((Number) filterIndex).intValue(); if (i > 0 && i <= list.size()) { return list.get(i - 1); } else if (i < 0 && Math.abs(i) <= list.size()) { return list.get(list.size() + i); } else { ctx.notifyEvt(() -> new ASTEventBase(Severity.ERROR, Msg.createMessage(Msg.INDEX_OUT_OF_BOUND), null)); return null; } } else if (filterIndex == null) { return Collections.emptyList(); } else { ctx.notifyEvt(() -> new ASTEventBase(Severity.ERROR, Msg.createMessage(Msg.ERROR_EXECUTING_LIST_FILTER, filterIndex), null)); return null; } } }
@Override public Object evaluate(EvaluationContext ctx) { ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.BASE_NODE_EVALUATE_CALLED) ) ); return null; }
private Comparable convertToComparable(EvaluationContext ctx, Object s) { Comparable start; if( s instanceof Comparable ) { start = (Comparable) s; } else if( s instanceof Period ) { // period has special semantics start = new ComparablePeriod( (Period) s ); } else { ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.INCOMPATIBLE_TYPE_FOR_RANGE, s.getClass().getSimpleName() ))); start = null; } return start; }
private static UnaryTest toUnaryTest(EvaluationContext ctx, Object o) { if ( o instanceof UnaryTest ) { return (UnaryTest) o; } else if ( o instanceof Range ) { return (c, x) -> { try { return ((Range) o).includes( x ); } catch ( Exception e ) { ctx.notifyEvt( () -> new FEELEventBase( FEELEvent.Severity.ERROR, Msg.createMessage( Msg.EXPRESSION_IS_RANGE_BUT_VALUE_IS_NOT_COMPARABLE, o.toString(), x.toString() ), e ) ); throw e; } }; } else if ( o instanceof List ) { return (c, x) -> ((List<?>) o).contains( x ); } else { return (c, x) -> x.equals( o ); } }
@Override public Object evaluate(EvaluationContext ctx) { if (expression == null) return null; BigDecimal result = EvalHelper.getBigDecimalOrNull( expression.evaluate( ctx ) ); if ( result == null ) { ctx.notifyEvt( astEvent(Severity.WARN, Msg.createMessage(Msg.NEGATING_A_NULL))); return null; } else if ( Sign.NEGATIVE == sign ) { return BigDecimal.valueOf( -1 ).multiply( result ); } else { return result; } }
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; } }
private UnaryTest createInUnaryTest() { return (c, o) -> { if (o == null) { return false; } Object val = value.evaluate( c ); if (val instanceof Range) { try { return ((Range) val).includes(o); } catch (Exception e) { c.notifyEvt(astEvent(Severity.ERROR, Msg.createMessage(Msg.EXPRESSION_IS_RANGE_BUT_VALUE_IS_NOT_COMPARABLE, o.toString(), val.toString()))); throw e; } } else if (val instanceof Collection) { return ((Collection) val).contains(o); } else { return false; // make consistent with #createNotUnaryTest() } }; }
/** * C# – return the count of the outputs */ public static Object countCollect( EvaluationContext ctx, DecisionTable dt, List<? extends Indexed> matches, List<Object> results) { ctx.notifyEvt( () -> { List<Integer> indexes = matches.stream().map( m -> m.getIndex() + 1 ).collect( toList() ); return new DecisionTableRulesSelectedEvent( FEELEvent.Severity.INFO, "Rules fired for decision table '" + dt.getName() + "': " + indexes, dt.getName(), dt.getName(), indexes ); } ); return generalizedCollect( ctx, dt, results, x -> new BigDecimal( x.collect( toSet() ).size() ) ); }
public Object satisfies(Function<EvaluationContext, Object> expression) { if (quantOp == Quantifier.SOME || quantOp == Quantifier.EVERY) { return iterateContexts(ctx, iterationContexts, expression, quantOp); } // can never happen, but anyway: ctx.notifyEvt(() -> new ASTEventBase(Severity.ERROR, Msg.createMessage(Msg.IS_NULL, "Quantifier"), null)); return null; }
@Override public Boolean evaluate(EvaluationContext ctx) { if( quantifier == Quantifier.SOME || quantifier == Quantifier.EVERY ) { return iterateContexts( ctx, iterationContexts, expression, quantifier ); } ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.IS_NULL, "Quantifier")) ); return null; }
private void valueMustBeANumber(EvaluationContext ctx, Object value) { if (!(value instanceof BigDecimal)) { ctx.notifyEvt(() -> new ASTEventBase(Severity.ERROR, Msg.createMessage(Msg.VALUE_X_NOT_A_VALID_ENDPOINT_FOR_RANGE_BECAUSE_NOT_A_NUMBER, value), null)); throw new EndpointOfRangeNotOfNumberException(); } }
private void valueMustBeANumber(EvaluationContext ctx, Object value) { if (!(value instanceof BigDecimal)) { ctx.notifyEvt(astEvent(Severity.ERROR, Msg.createMessage(Msg.VALUE_X_NOT_A_VALID_ENDPOINT_FOR_RANGE_BECAUSE_NOT_A_NUMBER, value), null)); throw new EndpointOfRangeNotOfNumberException(); } }
private UnaryTest createBooleanUnaryTest( ) { return (context, left) -> { Object right = value.evaluate( context ); if( right instanceof Boolean ) { return (Boolean) right; } else { context.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.EXTENDED_UNARY_TEST_MUST_BE_BOOLEAN, left.toString(), value.toString() ) ) ); return Boolean.FALSE; } }; }
/** * Returns true when at least one of the elements of the list matches the target. * The list may contain both objects (equals) and UnaryTests (apply) */ public static Boolean exists( EvaluationContext ctx, Object tests, Object target) { if (!(tests instanceof List)) { if (tests == null) { ctx.notifyEvt(() -> new ASTEventBase(FEELEvent.Severity.ERROR, Msg.createMessage(Msg.IS_NULL, "value"), null)); return null; } return applyUnaryTest(ctx, tests, target); } for (Object test : (List) tests) { Boolean r = applyUnaryTest(ctx, test, target); if (Boolean.TRUE.equals(r)) { return true; } } return false; }
@Override public Range evaluate(EvaluationContext ctx) { Object s = start.evaluate( ctx ); Object e = end.evaluate( ctx ); boolean problem = false; if ( s == null ) { ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.IS_NULL, "Start"))); problem = true; } if ( e == null ) { ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.IS_NULL, "End"))); problem = true; } if (problem) { return null; } if ( BuiltInType.determineTypeFromInstance( s ) != BuiltInType.determineTypeFromInstance( e ) && !s.getClass().isAssignableFrom( e.getClass() ) ) { ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.X_TYPE_INCOMPATIBLE_WITH_Y_TYPE, "Start", "End"))); return null; } Comparable start = convertToComparable( ctx, s ); Comparable end = convertToComparable( ctx, e ); return new RangeImpl( lowerBound==IntervalBoundary.OPEN ? Range.RangeBoundary.OPEN : Range.RangeBoundary.CLOSED, start, end, upperBound==IntervalBoundary.OPEN ? Range.RangeBoundary.OPEN : Range.RangeBoundary.CLOSED ); }
@Override public Object evaluate(EvaluationContext ctx) { String varName = EvalHelper.normalizeVariableName( getText() ); if( ! ctx.isDefined( varName ) ) { ctx.notifyEvt( astEvent( FEELEvent.Severity.ERROR, Msg.createMessage( Msg.UNKNOWN_VARIABLE_REFERENCE, getText()), null) ); return null; } return ctx.getValue( varName ); }
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; }
@Override public Boolean evaluate(EvaluationContext ctx) { if (exprs == null) return null; Object value = this.value.evaluate( ctx ); Object expr = this.exprs.evaluate( ctx ); if ( expr != null ) { if ( expr instanceof Iterable ) { // evaluate in the collection for ( Object e : ((Iterable) expr) ) { // have to compare to Boolean.TRUE because in() might return null if ( in( ctx, value, e ) == Boolean.TRUE ) { return true; } } return false; } else { // evaluate single entity return in( ctx, value, expr ); } } ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.IS_NULL, "Expression")) ); return null; }