Natan
Natan

Reputation: 2858

Nashorn assign a Java function to a map

I have this engine which runs user-input (trusted) javascript function to filter some data for them using Nashorn. Don't want to go into the details of the requirements but let's say it's some sort of plugin system.

This javascript gets a Java map(which acts like a JS object) as a parameter to get some contextual data. So I want to add some convenience extension methods to this JS object for the users. So I did the following:

Map<String, String> inputMap = ....
inputMap.put("containsMagic", (Function<String, Boolean>) param -> some complex magic check and return boolean);

Works perfectly!

if(inputMap.containsMagic('Im Por Ylem'))
  do stuff;

However, I want it to accept no parameter as well, because null is a valid value and containsMagic() looks better than containsMagic(null).

if(inputMap.containsMagic())
  do stuff;

But I get this:

TypeError: Can not invoke method ......$$Lambda$15/1932831450@30c15d8b with the passed arguments; they do not match any of its method signatures.

I guess that's kind of normal given how Java works. If I pass null, it works of course but that's not very intuitive.

I can't add another function with 0 parameters and the same name because Java maps are single keyed. The complex magic check needs to be in java, so I can't assign a javascript function (JSObject?) either. Any ideas how I can accomplish this?

Upvotes: 2

Views: 1070

Answers (2)

Attila Szegedi
Attila Szegedi

Reputation: 4595

java.util.function unfortunately lacks a standard interface for variadic functions, but you could add your own:

@FunctionalInterface
public interface VariadicFunction<T,R> {
    public R apply(T... args);
}

and then

inputMap.put("containsMagic", (VariadicFunction<String, Boolean>) param -> some complex magic check and return boolean);

Upvotes: 1

wero
wero

Reputation: 33000

You can implement containsMagic as explicit method with a varargs parameter:

public static class InputMap extends HashMap<String, Object> {
    public Boolean containsMagic(String... args) {
        String arg = args.length == 1 ? args[0] : null;
        // do magic 
    }
}

...
Map<String, Object> inputMap = new InputMap(); 

Upvotes: 1

Related Questions