Search code examples
javadroolsexpert-system

Execution of a single rule for a group in Drools


I am working on an expert system based on legislation, I have many rules like these:

Rule 1: If the seizure has an amount greater than 3000, seize the amount, justification law 100

Rule 2: If the seizure is of a family type, seize the amount, justification law 200

The problem is that the action "Seize" can only be applied once, but I need to save the history of the rules that are met, I present an example below

rule "law 100"

when 
  $seizure: Seizure(amount>3000)
then
  $seizure.getRules().add("Justification: law 100 of the civil that says bla bla");
  $seizure.applyPunishment();

rule "law 200"

when 
  $seizure: Seizure(type == TYPES.Family)
then
  $seizure.getRules().add("Justification: law 200 of the family code that says bla bla");
  $seizure.applyPunishment();

As I showed above, I need the "then" part that save the description rule "$seizure.getRules().add("Justification: law of the civil code");". and I also need that if the "$seizure.applyPunishment();" was already applied in rule 1, it will not be reapplied in the rule 2.

Thanks in advice


Solution

  • You have several options here.

    1. Change applyPunishment to be idempotent.

      You don't show the code for applyPunishment, but it could look like

      private boolean alreadySeized = false;
      
      public void applyPunishment() {
          if (alreadySeized) {
              return;
          }
      
          alreadySeized = true;
      

      You could also base this on some other variable that already exists. E.g. if (seizedAmount > 0) return;. But it's hard to say how that might work without the code.

    2. You could change applyPunishment to something like markForPunishment, which could look like

      private boolean markedForPunishment;
      
      public void markForPunishment() {
          markedForPunishment = true;
      }
      

      Then add a rule like

      rule "Punish"
      
      when
        $seizure: Seizure(markedForPunishment  == true)
      then
        $seizure.applyPunishment();
      

      With an appropriate getter.

      Your other rules would call markForPunishment rather than applyPunishment.

    3. You could use a ruleflow to separate the justifications from the punishment.

    4. You could set a variable in your then clause that you use in your rules.

    There are probably other options. The big decision to make is whether you want an MVEL solution or a Java solution. Several of the options will require changing both.