Список свободных переменных в выражении EL

У меня есть приложение, которое содержит некоторые оценки EL, используемые для программной конфигурации. Учитывая выражение EL, я хочу получить, какие свободные переменные он содержит, фактически не оценивая его. Цель состоит в том, чтобы предоставить пользовательский интерфейс, в котором конечные пользователи могут связывать значения со свободными переменными, прежде чем нажимать кнопку "оценить".

к несчастью javax.el.ValueExpression не предоставляет эту функциональность, поэтому мне может понадобиться использовать API-интерфейс конкретного поставщика. Это довольно рано в разработке, поэтому я еще не определился с выбором реализации. Я думал о MVEL, JUEL и SpEL, но, конечно, все, что я выбрал, должно иметь функциональность, описанную выше.

3 ответа

Решение

ParserContext MVEL может рассказать вам все о переменных, организованных местными жителями и входами.

ParserContext ctx = ParserContext.create();
MVEL.analysisCompile("a = 0; b = 0;", ctx);

HashMap<String, Class> vars = ctx.getVariables();

assert vars.containsKey("a") && Number.class.isAssignableFrom(vars.get("a"));
assert vars.containsKey("b") && Number.class.isAssignableFrom(vars.get("b"));

Как насчет этого...

    SpelExpression parseExpression = (SpelExpression) new SpelExpressionParser().parseExpression(expressionString);
    SpelNode node = parseExpression.getAST();
    List<String> vars = getVars(node);

...


private List<String> getVars(SpelNode node) {
    List<String> vars = new ArrayList<String>();
    for (int i = 0; i < node.getChildCount(); i++) {
        SpelNode child = node.getChild(i);
        if (child.getChildCount() > 0) {
            vars.addAll(getVars(child));
        }
        else {
            if (child instanceof VariableReference) {
                vars.add(child.toStringAST());
            }
        }
    }
    return vars;
}

Ответ Гэри хорош, но он не работал для меня, когда выражение содержало одну переменную, например, "#var" (один узел без дочерних элементов). Небольшое изменение:

private Set<String> getVars(SpelNode node) {
    Set<String> vars = new HashSet<String>();
    if (node == null) {
        return vars;
    }

    if (node instanceof VariableReference) {
        // Remove the "#" to get the actual variable name
        vars.add(StringUtils.remove(node.toStringAST(), "#"));
    }

    for (int i = 0; i < node.getChildCount(); i++) {
        SpelNode child = node.getChild(i);
        vars.addAll(getVars(child));
    }

    return vars;
}
Другие вопросы по тегам