MethodInvokableFunction implements InvokableFunction { @Override public Object invoke(Environment env, Object input, FunctionArguments args) { Object[] argArray = new Object[_parameters.size()]; if (_environmentParameter != null) { argArray[_environmentParameter.getOrdinal()] = env; } if (_inputParameter != null) { argArray[_inputParameter.getOrdinal()] = input; } boolean argsMissing = false; for (Parameter parameter : _parameters.values()) { if (parameter != _inputParameter && parameter != _environmentParameter) { Object arg = args.getArgument(parameter.getName()); Object resolvedArg = resolveArgument(parameter, arg); argArray[parameter.getOrdinal()] = resolvedArg; if (resolvedArg == null && !parameter.isNullable()) { argsMissing = true; } } } if (argsMissing) { return missingArguments(argArray); } try { return _method.invoke(_receiver, argArray); } catch (IllegalAccessException e) { throw new OpenGammaRuntimeException("Unable to access method", e); } catch (InvocationTargetException | IllegalArgumentException e) { Exception cause = EngineUtils.getCause(e); String methodName = _method.getDeclaringClass().getSimpleName() + "." + _method.getName() + "()"; s_logger.warn("Exception invoking " + methodName, cause); return Result.failure(cause); } } MethodInvokableFunction(Object receiver,
                                        Map<String, Parameter> parameters,
                                        Parameter environmentParameter,
                                        Parameter inputParameter,
                                        Method method); @Override Object invoke(Environment env, Object input, FunctionArguments args); @Override Object getReceiver(); @Override Object getUnderlyingReceiver(); @Override Class<?> getDeclaringClass();  }
@Test public void oneMissingArg() { FunctionModelConfig config = config(implementations(Fn.class, Impl.class)); FunctionMetadata metadata = EngineUtils.createMetadata(Fn.class, "foo"); FunctionModel model = FunctionModel.forFunction(metadata, config); InvokableFunction invokableFunction = model.build(new FunctionBuilder(), ComponentMap.EMPTY); FunctionArguments args = new FunctionArguments(ImmutableMap.<String, Object>of("bar", "barVal")); Result<?> result = (Result<?>) invokableFunction.invoke(mock(Environment.class), null, args); assertFalse(result.isSuccess()); assertEquals(FailureStatus.MISSING_ARGUMENT, result.getStatus()); String expectedMessage = "No argument provided for non-nullable parameter for method Fn.foo(), " + "parameter 'baz', type Object"; assertEquals(expectedMessage, result.getFailureMessage()); }
@Test public void multipleMissingArgs() { FunctionModelConfig config = config(implementations(Fn.class, Impl.class)); FunctionMetadata metadata = EngineUtils.createMetadata(Fn.class, "foo"); FunctionModel model = FunctionModel.forFunction(metadata, config); InvokableFunction invokableFunction = model.build(new FunctionBuilder(), ComponentMap.EMPTY); Result<?> result = (Result<?>) invokableFunction.invoke(mock(Environment.class), null, FunctionArguments.EMPTY); assertFalse(result.isSuccess()); assertEquals(FailureStatus.MISSING_ARGUMENT, result.getStatus()); String expectedMessage = "No arguments provided for non-nullable parameters of method Fn.foo(), " + "parameters [Object bar, Object baz]"; assertEquals(expectedMessage, result.getFailureMessage()); }