Learn Drools: Part II(Cross Product)

Learn Drools: Part  II(Cross Product)

In the previous article, we got a basic idea what is Drools and How it works. In this article, we pay attention to the details how Rule works with facts.


When we write Rules Often a question Pops up our mind is
How can I invoke one rule from another Rule like we call a method?

The answer is no we can’t call a Rule from another Rule , The reason Drools match the Rules with incoming data/facts and if data satisfies Rule condition it stores the data in an Agenda, It immediately not fire the then part of a Rule as, It may be possible Same Data or facts can be matched by different rules so It stores matching facts in a Agenda and after firing all rules then it takes the action on Agenda i.e fires the then parts on facts.


So, as the rules apply on data/facts it is not possible to call a rule from another as we can’t pass any arguments/facts  beforehand as facts are coming at runtime.



So, rather than confused the Rules with functional/oops programming consider it with RDBMS.

Where we can compare Drools Rules and Facts with RDBMS component


Drools Component
RDBMS Component
Data/Facts/Domain Object data structure
Table
Facts/Domain Objects
Rows
Fact /Domain Object attributes
Column
Domain Objects HAS-A relationship
Joining/Cartesian Product
Drools operators
Filter Criterias
Drools When
When in Sql
Drools Then
Trigger
Drools Rule
Sql Query

Try to understand the above relationship with a simple example, Suppose we have Two Domain Objects say Department and Employee, and Each Employee is associated with a Department.


Step 1: Creating Data structure for Department and Employee, Nothing but two Simple POJOs which same as Two tables Department and Employee.


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;
   }
   
   

}


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;
   }
   
   
   
   
   

}



Step 2: Create a simple rule

employee.drl

package com.rules

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

rule "print cross product"
   when
      emp: Employee();
      dept: Department();
   then
   System.out.println("Fire print cross product Rule");
   System.out.println(dept.getName() + "::" + emp.getName()+ ": "+emp.getDept().getName());
end


We create a simple rule , it tells that for every instance of Employee and Department in working memory print the department name and employee name and Employee's department name.

It is same as the following sql

Select * from Employee emp Department dept where emp.deptId=dept.deptId

So it will create all cartesian product in Working memory

So If we have two departments and two employees in working memory it creates four combinations and then fires the rules on these combinations.


Step 3: Create Working memory and insert Objects to show the result.

package com.example.droolsExample;

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

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 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.executeDroolsEmployee();
   }

       public void executeDroolsEmployee() 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 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.fireAllRules();

   }

}


Step 4: Checking the Output
Civil::Shamik Mitra: IT
IT::Shamik Mitra: IT
Civil::Samir Mitra: Civil
IT::Samir Mitra: Civil

Please note that as we have inserted two employees Objects and Two department Objects in working memory so it creates four different combinations.

In the next Article, we will discuss  How to filter resultset using Drools?

Learn Drools: Part 1

Drools Introduction


When we implement a complex software often we require to maintains a set of rules which will be applied on a set of data to take action on them. In a regular term, we called them Rule Engine.
If there is a small set of rules we can create our own Rule Engine which will maintain a certain order and applied on incoming data to take the decision or categorize the data.
The advantage of maintaining own rule engine is that we have a pure control over the Rule Engine's algorithm so we can easily change the Algorithm logic , To be simple we don’t have to rely on the third party for the pattern matching logic.
On Other hand, if rules are ever changing or there is a huge set of rules probably we will not want to maintain our own Rule engine as it increases our development cost not only that how the Rule engine performs and it’s optimization, Who wants to take this responsibility?
It would be nice if we delegate that work to some third party which is tested and trusted. So we can clearly separate the data and logic.
Third Party maintains the Rule Engine application and we just define the Rules as a strategy, on top of it, it would be nice if it is declarative so Business Analyst can understand the logic.

Drools:
Drools is this kind of Business Logic integration Platform (BLiP). Drools is Open source project written in java, Red Hat and Jboss maintains Drools.


Drools has two main parts
1. Authoring : By Authoring we create Rules file for Drools this is (.drl ) the file which contains the Rule definition in a declarative way. In this file ,we can write a set of Rules which will be fired at the run time. It is Developer's responsibility to write these Rules as per business requirements.
2. Runtime : By Runtime we create working memory , It is same as Session in Hibernate. As Rules file contains a set of rules, Runtime creating memory load these rules and apply on the incoming data , In drools, we called incoming data as facts.

Rules :
A rule is nothing but the logic which will be applied on incoming data. It has two main parts when and then.
When : It determines the condition,on which condition the Rule will be fired.
Then : It is the action If rules met the condition, its defines what work this rule performs

Syntax :

rule <Rule Name>

  when

    <condition>

  then

    <Action>

End 



Problem : We will greet a Person based on current time.
We will define the rules in Drools files , Drool will load these rules and fire on the incoming data.
Step 1. Create a .drl (droolRule.drl)file where we will define the rules.

package com.rules

import com.example.droolsExample.Person

rule "Good Morning"
    when
    person: Person(time >= 0 , time < 12)
    then
    person.setGreet("Good Morning " + person.getName());
    end
rule "Good Afternoon"
    when
    person: Person(time >= 12 , time < 16)
    then
    person.setGreet("Good Afternoon " + person.getName());
    end
rule "Good Night"
    when
    person: Person(time >= 16 , time <= 24)
    then
    person.setGreet("Good Night " + person.getName());
    end



Please note that here we create three rules “Good Morning”, “Good Afternoon “ and “Good Night.” In when section we check the current time based on the Person POJO’s time property . and in then part, we set the greet message accordingly.


Step 2: Create Person POJO class

package com.example.droolsExample;

public class Person {

    private String name;
    private int time;
    private String greet;

    public String getGreet() {
    return greet;
    }
    public void setGreet(String greet) {
    this.greet = greet;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public int getTime() {
    return time;
    }
    public void setTime(int time) {
    this.time = time;
    }






Step 3: We create a class named DroolsTest.java, In this class, we take some steps.
Step a : Load the rule file i.e droolsTest.drl by using InputStream.
Step b: create a package using above rule and add them into drools PackageBuilder.
Step c: Create a RuleBase by using above Package. Rulebase is same as Sessionfactory in Hibernate it is costly.
Step d: Create a Working memory from this RuleBase. It is same as Session class in Hibernate. This Working memory manages the rules and incoming data. Apply the rules on the data.
Step e: Add incoming data into Working memory here we create a Person Object and add it into Working Memory
Step f: Fire all rules.

DroolsTest.java

package com.example.droolsExample;

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

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;



public class DroolsTest {

    public static void main(String[] args) throws DroolsParserException,
    IOException {
    DroolsTest droolsTest = new DroolsTest();
    droolsTest.executeDrools();
    }

    public void executeDrools() throws DroolsParserException, IOException {

    PackageBuilder packageBuilder = new PackageBuilder();

    String ruleFile = "/com/rules/droolsRule.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();

    Person person = new Person();
    person.setName("Shamik Mitra");
    person.setTime(7);

    workingMemory.insert(person);
    workingMemory.fireAllRules();

    System.out.println(person.getGreet());
    }

}





Output:

Good Morning Shamik Mitra.

As we set the time 7, so it satisfies the Good Morning Rule condition and fire this rule. 

 
 

EnumSet Efficiency

EnumSet Efficiency 


EnumSet is Specialized Set which only takes Enum elements. Look at the signature of this class.

public abstract class EnumSet<E extends Enum<E>>
extends AbstractSet<E>
implements Cloneable, Serializable


The Beauty of EnumSet is we can perform any collection operations like (add,remove etc. ) on Enum as Enumset is a collection furthermore it provides some Static methods by which we can do union,range check,none etc. operation.

So by using Enumset we can dynamically add Enum element remove an element or perform union operation . we can use it in an efficient way and use its power but still Developer are not used this they put Enum in a Set or any other collection if required.


So where we can Use EnumSet?

Ummm a probable use case comes in my mind is ,
Role and operation implementation not only that say from UI we can manipulate it and can create a new Role with new operation Set.

To be specific say I have Three types of role say Self,Friend, and Guest.
As you can guess Owner of the profile got Self role , Friends of owner got friend role and any unknown person got Guest role. Now Owner wants to create a new role for few guests , those can perform Friend operation as well as guest operations both.


How we will implement that,

Obvious one can think of Bit representation for operations and do an anding operation to check is particular operation is valid for a role or not, the same way he can create a new role I don’t go for that implementation that will hard to maintain. rather I will try to solve it through EnumSet.

Code:

  1. I create an Operation Enum where I store all the possible Operations

    package com.example.enumtest;

    public enum Operation {
       
       VIEW_PROFILE,EDIT_PROFILE,DELETE_PROFILE,VIEW_ALBUM,EDIT_ALBUM,DELETE_ALBUM,COMMENT,RATE_PROFILE

    }

    2. Then I create a Role Enum and associate permitted operations with those roles.

    package com.example.enumtest;

    import java.util.EnumSet;

    import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils.Collections;

    public enum Role {
       
       SELF(EnumSet.of(Operation.VIEW_PROFILE,Operation.VIEW_ALBUM,Operation.EDIT_PROFILE,Operation.EDIT_ALBUM,Operation.DELETE_PROFILE,
              Operation.DELETE_ALBUM,Operation.COMMENT)),
             
       FRIEND(EnumSet.of(Operation.VIEW_ALBUM,Operation.VIEW_PROFILE,Operation.COMMENT)),
       
       GUEST(EnumSet.of(Operation.VIEW_PROFILE,Operation.RATE_PROFILE));
       
       
       EnumSet<Operation> operationSet;
       Role(EnumSet<Operation> operationSet){
          this.operationSet=operationSet;
       }
       

    }

    Look in Role Constructor I pass EnumSet<Operation>, and when we define the Enum element I called  a Static method of  on EnumSet. Which will perform a union operation.


    3. Now each role has its set of operations and we can easily print them by traversing on operationSet ,easily check an operation is permitted or not by using

    operationSet.contains(operation)


    4. Now I want to add a new Role which can perform both Friend and guest operations.

    package com.example.enumtest;

    import java.util.EnumSet;

    public class ProfileManager {
       
       
       public static void printOperationForCustomRole(EnumSet<Role>roles)
       {
          EnumSet<Operation> mergeSet = EnumSet.noneOf(Operation.class);
          for(Role role: roles)
          {
              for(Operation op : role.operationSet)
              mergeSet.add(op);
          }
         
          System.out.println(mergeSet);
       }
       
       public static void main(String[] args) {
         
          ProfileManager.printOperationForCustomRole(EnumSet.of(Role.FRIEND,Role.GUEST));
         
       }

    }


    Look , how easily we can do it just pass Role.Friend and Role.Guest in printOperationForCustomRole() role method and create a new Operation set which holds all the operations of friend and Guest.


    Output:

    [VIEW_PROFILE, VIEW_ALBUM, COMMENT, RATE_PROFILE]






Java : Extensible Enum with Interface

 Extensible Enum with Interface

 

Overview

In Java Enum is a powerful data type. Many places user uses Enum To get advantages from Enum type. Like In a Static Factory method it wise decision to pass Enum type rather than pass String. Below , I mention some situations where using Enum is advantageous.

Enum Advantages

    1. In a Static Factory method passing Enum type as argument make the method typesafe. Method users can’t pass an arbitrary value to this method.
    2. Instead of using bit fields using Enum and EnumSet make the code cleaner and easy to maintain.
    3. Using Enum one can achieve Singleton pattern which is inherently Thread Safe.
    4. Using Strategy Enum Pattern one can get rid of If/Switch statements.
Although, Enum has several advantages but it has one major disadvantage.

Enum DisAdvantage

    1. Unlike Class, we can not extend Enum.
So the Question is

“Can we Extend Enum and When it is needed?”

Yes we can emulate the extensibility in Enum but we have to play in a strategic way ,
We know that Enum can’t be extended but we know the fact that an Interface can be extended and Enum can implement the Interface. So combining these two statements we can achieve extensibility. Where Enum can’t be extended but an interface can so If we use “Coding to an Interface” Strategy we can easily replace BaseType enum with Our Extended Enum.
Now coming to the use case,
According to Joshua Bloch ,“There is at least one compelling use case for extensible enumerated types, which is operation codes, also known as opcodes. An opcode is an enumerated type whose elements represent operations on some machine, such as the Operation”
Sometimes it is desirable to let the users of an API provide their own operations,effectively extending the set of operations provided by the API.”


According to Josh Bloch In a case of operation, we can provide some basic operation in an Enum like a simple calculator and basic operations are plus ,minus etc but if API Users want more like XOR , Square root, they can achieve it through extending Operation Interface and create a new Enum.

Steps For Achieving Extensibility


Let’s take a Use Case , We have an Enum call Direction in an API ,it has entries for NORTH,SOUTH,EAST,WEST but most of the cases API Users use these basic directions but when it is about to showing the shortest path between source and destination API Users need some advanced direction like NORTH-EAST,NORTH-WEST etc.


How judiciously we implement the API so Users can have the option to extend the Basic Direction Enum?


Steps.
    1.Create an Interface called Direction and declares a method called showDirection().
    2. Create a BasicDirection enum by implement Direction interface.
    3. Put entries for NORTH,SOUTH,EAST,WEST.
    4. Please note that as it implements Direction interface , each Enum has to override showDirection method.
    5. Create an AdVANCEDIRECTION enum with NORTH-EAST,NORTH-WEST etc entries.
    6. Use this Enum anywhere.
    Java Code :
    Direction Interface

package com.example.enumtest;

public interface Direction {
   
    public void showDirection();



BasicDirection Enum 

package com.example.enumtest;

public enum BasicDirection implements Direction{
   
    NORTH{

        @Override
        public void showDirection() {
            System.out.println("I am NORTH");
          
        }
      
    },
    SOUTH{

        @Override
        public void showDirection() {
            System.out.println("I am South");
          
        }
      
    },
    EAST{

        @Override
        public void showDirection() {
            System.out.println("I am EAST");
          
        }
      
    },
    WEST{

        @Override
        public void showDirection() {
            System.out.println("I am WEST");
          
        }
      
    }

}


AdvanceDirection Enum

package com.example.enumtest;

public enum AdvanceDirection implements Direction{
    NORTHEAST{

        @Override
        public void showDirection() {
            System.out.println("I am NORTH-EAST");
          
        }
      
    },
    NORTHWEST{

        @Override
        public void showDirection() {
            System.out.println("I am NORTH-WEST");
          
        }
      
    },
    SOUTHEAST{

        @Override
        public void showDirection() {
            System.out.println("I am SOUTH-EAST");
          
        }
      
    },
    SOUTHWEST{

        @Override
        public void showDirection() {
            System.out.println("I am SOUTH-WEST");
          
        }
      
    }


}
 


DirectionDriver Class 

package com.example.enumtest;

public class DirectionDriver {
   
    public static void printDirection(Direction op)
    {
        op.showDirection();
    }
   
    public static <T extends Enum<T> & Direction> void  printDirections(Class<T> clazz)
    {
        for(Direction direction : clazz.getEnumConstants())
        {
            direction.showDirection();
        }
    }
   
    public static void main(String[] args) {
      
        DirectionDriver.printDirection(BasicDirection.EAST);
        DirectionDriver.printDirection(AdvanceDirection.SOUTHWEST);
      
        DirectionDriver.printDirections(BasicDirection.class);
        DirectionDriver.printDirections(AdvanceDirection.class);
      
    }

}

 

Output

I am EAST
I am SOUTH-WEST
I am NORTH
I am South
I am EAST
I am WEST
I am NORTH-EAST
I am NORTH-WEST
I am SOUTH-EAST
I am SOUTH-WEST





Please pay attention to the class DirectionDriver, here I create two methods
    printDirection which takes Direction as Input and I pass an Enum to it.
    Another version is printDirections method it prints all Enum entries to achieve that
I make a generic type which says T must be an Enum and a subtype of Direction by <T extends Enum<T> & Direction> . then pass class instance so I can iterate over EnumConstants.