2015-09-17 4 views
2

У меня есть этот движок, который запускает функцию javascript, вводимую пользователем (доверенным), чтобы фильтровать некоторые данные для них с помощью Nashorn. Не хочу вдаваться в детали требований, но скажем, это какая-то система плагинов.Nashorn назначает Java-функцию карте

Этот javascript получает карту Java (которая действует как объект JS) в качестве параметра для получения некоторых контекстуальных данных. Поэтому я хочу добавить некоторые методы расширения удобства для этого объекта JS для пользователей. Поэтому я сделал следующее:

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

Работает отлично!

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

Однако, я хочу, чтобы принять не параметр, а также, потому что нуль является допустимым значением и containsMagic() выглядит лучше, чем containsMagic(null).

if(inputMap.containsMagic()) 
    do stuff; 

Но я получаю это:

TypeError: Can not invoke method ......$$Lambda$15/[email protected] with the passed arguments; they do not match any of its method signatures. 

Я предполагаю, что это своего рода нормально, учитывая, как работает Java. Если я передаю null, это работает, конечно, но это не очень интуитивно.

Я не могу добавить еще одну функцию с 0 параметрами и одним и тем же именем, потому что карты Java имеют одно ключевое слово. комплексная проверка магии должна быть в java, поэтому я не могу назначить функцию javascript (JSObject?). Любые идеи, как я могу это сделать?

ответ

1

Вы можете реализовать containsMagic в качестве явного метода с параметром массива аргументов:

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(); 
+0

Ах, умный! Чтобы отметить, я попытался расширить HashMap при построении (например, анонимные классы, не уверен, что это называется сейчас), но Nashorn это не понравилось. Собственный класс отлично работал. Благодарю. – Natan

1

java.util.function, к сожалению, отсутствует стандартный интерфейс для переменным числом функций, но вы можете добавить свои собственные:

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

, а затем

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

хорошая идея, но это не работает. Он не работает с 'java.lang.ClassCastException: не может использовать java.lang.String для [Ljava.lang.Object;' – wero