Список свободных переменных в выражении 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;
}