У меня есть xml-файл, который содержит условия, которые нужно проверить по входным данным JSON метаданных метаданных JSON *1004*.
Пример ввода метаданных JSON может быть
{
"max_cash":789,
"min_cash":12,
"start_date":"28 Oct 2018",
"end_date":"02 Dec 2018",
"allowed_cities":"3,4,5,6"
}
Пример значения данных JSON может быть
{
"cash":34,
"order_date":"03 Nov 2018",
"city_id":"5,4"
}
Каждое условие может формировать выражение и имеет следующий атрибут
- param_holder - это левый член выражения. Это просто ключ, значение которого находится в метаданных JSON.
- param_value_holder - это правильный термин выражения. Это просто ключ, значение которого находится в данных значения JSON.
- оператор - какой оператор будет выполняться слева и справа. Например, <,>, <=,> =, <>, ==, CONTAINS, NOT_CONTAINS, CONTAINS_AT_LEAST_ONE и т. Д.
- param_type - тип данных левого и правого члена. Например, НОМЕР, ДАТА, ВРЕМЯ, СТРОКА, СПИСОК.
Пример XML выглядит следующим образом
<condtion id="1" param_type="NUMBER" param_holder="max_cash" operator=">=" param_value_holder="cash" next_condition="2"></condtion>
<condtion id="2" param_type="NUMBER" param_holder="min_cash" operator="<=" param_value_holder="cash" next_condition="3"></condtion>
<condtion id="3" param_type="DATE" param_holder="start_date" operator="<=" param_value_holder="order_date" next_condition="4"></condtion>
<condtion id="4" param_type="DATE" param_holder="end_date" operator=">=" param_value_holder="order_date" next_condition="5"></condtion>
<condtion id="5" param_type="LIST" param_holder="allowed_cities" operator="CONTAINS" param_value_holder="city_id" next_condition="-1">
Я работаю с JAVA, и почти все здесь является динамическим, который можно добавлять, изменять и удалять в любое время. В будущем может появиться еще несколько операторов, типов данных и т. Д.
Я ищу решение, в котором люди могут добавлять любые условия без повторного развертывания кода. Развертывание кода следует выполнять только в случае изменения метаданных JSON.
Я читал об ANTLR, и он думает, что он перестанет убивать решение, а создание и поддержание грамматики и парсера - это накладные расходы для разработчика.
Я придумал другое решение с Factory Pattern, где Operator Factory принимает входные данные как оператор и возвращает соответствующий объект Operator, который дополнительно принимает левый член, правый член и тип параметра в качестве параметра, и оценивает условие на основе определенного типа параметра.
public abstract class Operator {
public abstract boolean evaluate(String leftTerm, String rightTerm, String param_type) throws ParseException;
}
public class GTEOperator extends Operator {
@Override
public boolean evaluate(String leftTerm, String rightTerm, String param_type) throws ParseException {
switch (param_type)
{
case "DATE":
return new SimpleDateFormat().parse(leftTerm).after(new SimpleDateFormat().parse(rightTerm));
case "NUMBER":
return Integer.parseInt(leftTerm) >=Integer.parseInt(rightTerm);
default:
return true;
}
}
}
public class ContainsOperator extends Operator {
@Override
public boolean evaluate(String leftTerm, String rightTerm, String param_type) throws ParseException {
return Arrays.asList(leftTerm.split(",")).contains(rightTerm);
}
}
Это решение не является динамическим и требует много переписывания кода.
Может ли кто-нибудь помочь мне с лучшим, расширяемым и объектно-ориентированным подходом.