Таким образом, у вас есть сотрудник, в котором его отдел может быть указан в любом из пяти мест. Лучший способ выяснить это - выяснить, где находится отдел до того, как применить правила, а затем изменить объект, который вы передаете в правила. Вы не ограничены в отношении того, какие объекты вы передаете в правила, если они сериализуются нормально; если EmployeeData в настоящее время является необработанными результатами вызова базы данных или чего-то еще, преобразуйте нужные вам части в новый POJO и передайте его в правила.
Так что для вашего примера я бы сделал что-то вроде:
class Employee {
private Integer employeeId;
private Integer departmentId; // assuming the only thing you need out of Department is id
public static Employee fromEmployeeData(EmployeeData data) {
Employee employee = new Employee();
employee.setEmployeeId(data.getEmployeeId());
if (data.getDept1() != null) {
employee.setDepartmentId(data.getDept1());
} else if (...) {} // other else-if omitted for brevity
return employee;
}
// getters and setters here
}
public void invokeRules(EmployeeData data) {
KieSession kieSession = ...;
Employee employee = Employee.fromEmployeeData(data);
kieSession.insert( employee );
kieSession.fireAllRules();
}
Затем вы можете написать правила, которые отключают идентификатор отдела:
rule "Employee is in department 6"
when
Employee( departmentId == 6 )
then
// do something
end
В качестве альтернативы, вы можете вызывать Java методы из когда пункт. Допустим, мы создаем класс с именем EmployeeUtils
, в котором есть метод для определения отдела из EmployeeData:
class EmployeeUtils {
public static Integer resolveDepartment(Employee e) {
Integer deptId = null;
if (e.getDept1Id() != null) {
deptId = e.getDept1Id();
} else if (...) {} // other else-if omitted for brevity
return deptId;
}
}
Затем этот метод можно вызвать с левой стороны следующим образом:
rule "Employee in department 6"
when
$employee: Employee()
Integer(this == 6) from EmployeeUtils.resolveDepartment($employee)
then
// do something
end
Очевидно, вы могли бы также назвать его с правой стороны:
rule "Example"
when
$employee: Employee()
then
System.out.println("Employee is in department " + EmployeeUtils.resolveDepartment($employee));
end
В общем не рекомендуется звонить Java методов с левой стороны, потому что такие вызовы не могут быть оптимизированы. Когда вы выполняете фильтрацию, например Employee(department == 6)
, Drools может оптимизировать утверждения, чтобы ваши правила выполнялись быстрее. Но если вы вызываете метод Java, это похоже на черный ящик с движком Drools; он не имеет ни малейшего представления о том, что будет делать метод Java, поэтому он должен позволить ему оценивать как есть, а не выполнять работу, чтобы ускорить его.
Кроме того, как правило, также не рекомендуется передавать произвольные данные в набор правил. Передайте только те данные, которые вам нужны для применения правил. При конвертации из другого источника данных, например. из SQL результата запроса или преобразования из электронной таблицы, проанализируйте части этих других данных, которые вам действительно нужны, и передайте этот проанализированный входной объект в правила.
Я работал в компании, которая передала бы результат базы данных прямо в правилах. Логика c заключалась в том, что код был скомпилирован, поэтому, если вам нужно внести изменения в объект ввода правил, вам нужно будет перекомпилировать код и сделать новый выпуск. Но схема и правила базы данных могут быть внешними по отношению к скомпилированному коду, поэтому они могут меняться без необходимой перекомпиляции, поэтому просто сделайте все данные доступными и не беспокойтесь о новом выпуске. Это сработало, когда компания была новой, а данные, которые мы передавали, были всего лишь несколькими объединенными таблицами; к тому времени, как я ушел, мы передавали сотни таблиц данных, добавляющих в память до нескольких сотен килобайт, хотя правилам требовалось всего несколько бит данных, возможно, из пяти таблиц. Это было медленно и расточительно. Не go по этому маршруту.
Примерно так: когда у вас есть Сотрудник, а у вас есть данные Отдела, внешние - объединение этих двух направлений - это то, что было бы оптимально выполнено в (например) SQL запрос. Такого рода реляционное соединение обычно не требует каких-либо решений, принятых на нем. И если для этого нужны решения (например, если код отдела находится в Dept5, то это означает что-то иное, чем если бы он был в Dept2), тогда несколько правил действительно являются . Но когда речь идет о том же логике c, но в потенциально 5 местах? Не надо делать это в правилах; в этом нет никакой пользы. Сделайте это в Java, а затем передайте результат в правила, чтобы сделать утверждения против.