public Object invokeFunction ( EvaluationContext ctx , String name , List < Object > args ) { // find function with given name Method func = getFunction ( name ) ; if ( func == null ) { throw new EvaluationError ( "Undefined function: " + name ) ; } List < Object > parameters = new ArrayList <> ( ) ; List < Object > remainingArgs = new ArrayList <> ( args ) ; for ( Parameter param : Parameter . fromMethod ( func ) ) { BooleanDefault defaultBool = param . getAnnotation ( BooleanDefault . class ) ; IntegerDefault defaultInt = param . getAnnotation ( IntegerDefault . class ) ; StringDefault defaultStr = param . getAnnotation ( StringDefault . class ) ; if ( param . getType ( ) . equals ( EvaluationContext . class ) ) { parameters . add ( ctx ) ; } else if ( param . getType ( ) . isArray ( ) ) { // we've reach a varargs param parameters . add ( remainingArgs . toArray ( new Object [ remainingArgs . size ( ) ] ) ) ; remainingArgs . clear ( ) ; break ; } else if ( remainingArgs . size ( ) > 0 ) { Object arg = remainingArgs . remove ( 0 ) ; parameters . add ( arg ) ; } else if ( defaultBool != null ) { parameters . add ( defaultBool . value ( ) ) ; } else if ( defaultInt != null ) { parameters . add ( defaultInt . value ( ) ) ; } else if ( defaultStr != null ) { parameters . add ( defaultStr . value ( ) ) ; } else { throw new EvaluationError ( "Too few arguments provided for function " + name ) ; } } if ( ! remainingArgs . isEmpty ( ) ) { throw new EvaluationError ( "Too many arguments provided for function " + name ) ; } try { return func . invoke ( null , parameters . toArray ( new Object [ parameters . size ( ) ] ) ) ; } catch ( Exception e ) { List < String > prettyArgs = new ArrayList <> ( ) ; for ( Object arg : args ) { String pretty ; if ( arg instanceof String ) { pretty = "\"" + arg + "\"" ; } else { try { pretty = Conversions . toString ( arg , ctx ) ; } catch ( EvaluationError ex ) { pretty = arg . toString ( ) ; } } prettyArgs . add ( pretty ) ; } throw new EvaluationError ( "Error calling function " + name + " with arguments " + StringUtils . join ( prettyArgs , ", " ) , e ) ; } }
Invokes a function