Получить значения выражений в JEXL

Имея следующее JEXL выражение:

String expression = "myVar >= 12345 && mySecondVar <= 56789";

Я могу вызвать createScript и getVariables, чтобы получить myVar и mySecondVar в качестве значений, таких как:

Set<List<String>> expressionVars = JEXL.createScript(expression).getVariables();


Что я хотел бы знать, так это то, что при наличии того же выражения я мог бы вызвать какой-то другой метод, который бы возвращал значения для этих переменных. Причина в том, что я хотел бы проверить ввод некоторых из этих значений. Я проверил документы и поиграл с классом JexlScript, но не могу найти элегантный способ сделать это.
Поскольку JEXL уже выполняет работу по синтаксическому анализу моего выражения, было бы замечательно иметь возможность извлекать эту информацию и не нужно вручную анализировать мое выражение, чтобы получить эти значения.

Что-то в линии script.getValue("myVar"); возвращение 12345

1 ответ

С JEXL вы оцениваете скрипт / выражение в заданном контексте (JexlContext), который содержит переменные и их значения. JexlContext предоставляет методы has и get, которые соответственно проверяют существование и получают значение переменных. В вашем случае вам нужно выяснить, какой у вас JexlContext (или должен быть); оттуда, это просто итерировать ваши переменные (извлеченные из вашего скрипта) и проверить их значения (из контекста).

Смотрите: http://commons.apache.org/proper/commons-jexl/apidocs/org/apache/commons/jexl3/JexlContext.html http://commons.apache.org/proper/commons-jexl/apidocs/org/apache/commons/jexl3/JexlScript.html

Вы должны реализовать свой собственный контекст:

public class ZenContext implements JexlContext {
  static private final Map<String, Object> reservedVars = new HashMap<String, Object>();
  private final Map<String, Object> scriptDefinedVars  = new HashMap<String, Object>();
  static {
    reservedVars.put("math", java.lang.Math.class);
    reservedVars.put("stats", apache.commons.math3.stats.Stats);
    // whatever else ...
  }

  public boolean has(String name) {
    if (reservedVars .get(name) != null) return true;
    return scriptDefinedVars.get(name) != null;
  }

  public boolean get (String name) {
    Object value = null;
    if ((value = reservedVars .get(name)) != null) return value;

    return scriptDefinedVars.get(name);
  }

  public void set(String name, Object value) {
    scriptDefinedVars.set(name, value);
  }

  public Map<String, Object> getReservedVars () {
    return reservedVars;
  }
  public Map<String, Object> getScriptDefinedVars   () {
    return scriptDefinedVars ;
  }
}

Таким образом, у вас будет

  • карта зарезервированных имен переменных для объектов, которые вы не разрешаете скриптам изменять их значения. например,
  • отдельная карта варов, которая может быть установлена ​​из скрипта.

А потом добавьте эти методы.

public Object execute(File scriptFile) {
    JexlScript script = jexlEngine.createScript(scriptFile);
    return script.execute(this); // supply this as the context 
}
public Object execute (String scriptText) {
    JexlScript script = jexlEngine.createScript(scriptText);
    return script.execute(this); // supply this as the context 
}

Вы можете изменить метод набора, который я написал здесь, чтобы проверить переменные в картах, прежде чем разрешить им установку.

Однако это не сработает для локальных переменных скрипта.

var greeting = 'The rain in Maine falls plainly insane';

Поскольку локальная переменная полагается на другой механизм, org.apache.commons.jexl3.internal.Scope, использующий метод getLocalVariables(), в котором есть ошибка.

Другие вопросы по тегам