Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Learn Drools (Part 5): Truth Maintenance

DZone's Guide to

Learn Drools (Part 5): Truth Maintenance

Drools handles truth tables via its Truth Maintenance System. As Drools facts change, the system logically inserts the new data, automatically keeping it updated.

· Java Zone
Free Resource

The single app analytics solutions to take your web and mobile apps to the next level.  Try today!  Brought to you in partnership with CA Technologies

In our previous article, we saw how Inferences are useful when we need to repetitively use a condition across our Drools rules. With an Inference, we insert the condition as a POJO and use that fact across the rules. It's a perfect way to separate the condition from its usage.

But think about a condition where two rules are mutually exclusive. In that scenario, it is far better to use Truth maintenance, which is nothing but a truth table. Let's walk through it with an example.

Suppose, for our intrepid IT department, that if someone is designated as a Manager, we give them laptop. But if an employee is not a Manager, we give them a desktop. So in Drools, we have to create two rules:

  1. The first rule checks to see if someone's designation is "Manager", then gives them a laptop if they are.

  2. The second rule checks to see if the designation is not a manager, then gives them a desktop if they aren't one.

These two rules are mutually exclusive. For an employee/Drools fact, only one rule can be true — not both. So, we can maintain a truth table for that. In Drools, we call that the Drools Truth Maintenance System (TMS). Through the TMS, we can logically insert the condition — note that it's not just inserted, but logically inserted. The advantage of logical insertion is that when the condition is false, the fact/POJO is automatically retracted.

To understand the advantage of the TMS, think of a scenario where an employee's current designation is not a manager. So, according to the rule, they got a desktop, and we logically insert the "Not a Manager" condition in the Drools knowledge base for that employee or fact. But say that employee just got a promotion! After some hard work, the employee has been recognized as a leader and is now managing other workers. Now, that fact/condition that we inserted into the Drools knowledge base for that employee has to be retracted, and a new fact/condition ("is Manager") has to be inserted.

Of course, that makes the employee eligible for a laptop. Using the TMS, all that will be done automatically. We don’t have to care about it. You can find the solution to the above problem statement in the code blocks below.

Employee.drl

package com.rules

import com.example.droolsExample.pojo.Employee
import com.example.droolsExample.pojo.Department
import com.example.droolsExample.pojo.ITManager
import com.example.droolsExample.pojo.ITEmployee

rule "IT Manager Inference1"
    when
    $dept: Department(name=="IT");
    $emp: Employee(dept == $dept,manager==true);
    then
    insertLogical(new ITManager($emp));
end

rule "IT Employee Inference1"
    when
    $dept: Department(name=="IT");
    $emp: Employee(dept == $dept,manager==false);
    then
    insertLogical(new ITEmployee($emp));
end

rule "give Manager Laptop"
    when
    $emp: Employee();
    $itManager: ITManager(emp == $emp);

    then
    $emp.setMessage("Give Laptop");
    System.out.println($emp.getName()+ ": "+$emp.getDept().getName()+ ":"+$emp.getMessage());
end

rule "give Employee Desktop"
    when
    $emp: Employee();
    $itEmployee: ITEmployee(emp == $emp);

    then
    $emp.setMessage("Give Desktop");
    System.out.println($emp.getName()+ ": "+$emp.getDept().getName()+ ":"+$emp.getMessage());
end


Employee.java

package com.example.droolsExample.pojo;

public class Employee {
    String name;
    boolean manager;
    String message;
    Department dept;
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isManager() {
        return manager;
    }

    public void setManager(boolean manager) {
        this.manager = manager;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Department getDept() {
        return dept;
    }

    public void setDept(Department dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Employee [name=" + name + ", manager=" + manager + ", message="
        + message + ", dept=" + dept + "]";
    }
}


Department.java

package com.example.droolsExample.pojo;

public class Department {
    String name;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }    
}


ITManager.java

package com.example.droolsExample.pojo;

public class ITManager {
    private Employee emp;

    public ITManager(Employee emp)
    {
        this.emp=emp;
    }
  
    public Employee getEmp() {
        return emp;
    }

    public void setEmp(Employee emp) {
        this.emp = emp;
    }  
}


ITEmployee.java

package com.example.droolsExample.pojo;

public class ITEmployee {

    private Employee emp;
    public ITEmployee(Employee emp)
    {
        this.emp=emp;
    }
  
    public Employee getEmp() {
        return emp;
    }

    public void setEmp(Employee emp) {
        this.emp = emp;
    }
}


DroolTest.java

package com.example.droolsExample;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;

import org.drools.compiler.compiler.DroolsParserException;
import org.drools.compiler.compiler.PackageBuilder;
import org.drools.core.RuleBase;
import org.drools.core.RuleBaseFactory;
import org.drools.core.WorkingMemory;
import org.drools.core.event.AgendaEventListener;
import org.kie.api.runtime.process.ProcessInstance;
import org.kie.api.runtime.rule.FactHandle;
import com.example.drools.listener.Activation;
import com.example.drools.listener.TrackingAgendaEventListener;
import com.example.droolsExample.pojo.Department;
import com.example.droolsExample.pojo.Employee;

public class DroolsTest {
    public static void main(String[] args) throws DroolsParserException,
    IOException {
        DroolsTest droolsTest = new DroolsTest();
        //droolsTest.executeDrools();
        droolsTest.executeDroolsEmployee("/com/rules/employeeTruthTable.drl");
    }

    public void executeDroolsEmployee(String ruleFile) throws DroolsParserException, IOException {
        PackageBuilder packageBuilder = new PackageBuilder();
        //String ruleFile = "/com/rules/employee.drl";
        InputStream resourceAsStream = getClass().getResourceAsStream(ruleFile);
        Reader reader = new InputStreamReader(resourceAsStream);
        packageBuilder.addPackageFromDrl(reader);
        org.drools.core.rule.Package rulesPackage = packageBuilder.getPackage();
        RuleBase ruleBase = RuleBaseFactory.newRuleBase();
        ruleBase.addPackage(rulesPackage);
        WorkingMemory workingMemory = ruleBase.newStatefulSession();
        Department dep = new Department();
        dep.setName("Civil");
        Department dep1 = new Department();
        dep1.setName("IT");
        
        Employee emp = new Employee();
        emp.setName("Shamik Mitra");
        emp.setManager(true);
        emp.setDept(dep1);
    
        Employee emp2 = new Employee();
        emp2.setName("Swastika Mitra");
        emp2.setManager(false);
        emp2.setDept(dep1);

        Employee emp1 = new Employee();
        emp1.setName("Samir Mitra");
        emp1.setManager(true);
        emp1.setDept(dep);

        workingMemory.insert(dep);
        workingMemory.insert(dep1);
        workingMemory.insert(emp);
        workingMemory.insert(emp1);
        workingMemory.insert(emp2);
        workingMemory.fireAllRules();
    }


Output

Shamik Mitra: IT:Give Laptop
Swastika Mitra: IT:Give Desktop


CA App Experience Analytics, a whole new level of visibility. Learn more. Brought to you in partnership with CA Technologies.

Topics:
drools ,java ,rule engine ,truth table

Published at DZone with permission of Shamik Mitra, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}