Drools - Exemple de programme Drools

Dans ce chapitre, nous allons créer un projet Drools pour l'énoncé de problème suivant -

En fonction de la ville et du type de produit (combinaison de ville et de produit), renseignez-vous sur la taxe locale liée à cette ville.

Nous aurons deux fichiers DRL pour notre projet Drools. Les deux fichiers DRL signifieront deux villes considérées (Pune et Nagpur) et quatre types de produits (épicerie, médicaments, montres et produits de luxe).

  • La taxe sur les médicaments dans les deux villes est considérée comme nulle.

  • Pour l'épicerie, nous avons supposé une taxe de Rs 2 à Pune et de Rs 1 à Nagpur.

Nous avons utilisé le même prix de vente pour démontrer différents extrants. Notez que toutes les règles sont déclenchées dans l'application.

Voici le modèle pour contenir chaque itemType -

package com.sample;
import java.math.BigDecimal;
public class ItemCity {
   public enum City {
      PUNE, NAGPUR
   }
   public enum Type {
      GROCERIES, MEDICINES, WATCHES, LUXURYGOODS
   }
   private City purchaseCity;
   private BigDecimal sellPrice;
   private Type typeofItem;
   private BigDecimal localTax;
   
   public City getPurchaseCity() {
      return purchaseCity;
   }
   public void setPurchaseCity(City purchaseCity) {
      this.purchaseCity = purchaseCity;
   }
   public BigDecimal getSellPrice() {
      return sellPrice;
   }
   public void setSellPrice(BigDecimal sellPrice) {
      this.sellPrice = sellPrice;
   }
   public Type getTypeofItem() {
      return typeofItem;
   }
   public void setTypeofItem(Type typeofItem) {
      this.typeofItem = typeofItem;
   }
   public BigDecimal getLocalTax() {
      return localTax;
   }
   public void setLocalTax(BigDecimal localTax) {
      this.localTax = localTax;
   }
}

Fichiers DRL

Comme suggéré précédemment, nous avons utilisé deux fichiers DRL ici: Pune.drl et Nagpur.drl.

Pune.drl

Il s'agit du fichier DRL qui exécute les règles de la ville de Pune.

// created on: Dec 24, 2014
package droolsexample

// list any import classes here.
import com.sample.ItemCity;
import java.math.BigDecimal;

// declare any global variables here
dialect "java"
rule "Pune Medicine Item"
   when
      item : ItemCity (purchaseCity == ItemCity.City.PUNE,
         typeofItem == ItemCity.Type.MEDICINES)
   then
      BigDecimal tax = new BigDecimal(0.0);
      item.setLocalTax(tax.multiply(item.getSellPrice()));
end

rule "Pune Groceries Item"
   when
      item : ItemCity(purchaseCity == ItemCity.City.PUNE,
         typeofItem == ItemCity.Type.GROCERIES)
   then
      BigDecimal tax = new BigDecimal(2.0);
      item.setLocalTax(tax.multiply(item.getSellPrice()));
end

Nagpur.drl

Il s'agit du fichier DRL qui exécute les règles pour la ville de Nagpur.

// created on: Dec 26, 2014
package droolsexample

// list any import classes here.
import com.sample.ItemCity;
import java.math.BigDecimal;

// declare any global variables here
dialect "java"
rule "Nagpur Medicine Item"
   when
      item : ItemCity(purchaseCity == ItemCity.City.NAGPUR, 
         typeofItem == ItemCity.Type.MEDICINES)
   then
      BigDecimal tax = new BigDecimal(0.0);
      item.setLocalTax(tax.multiply(item.getSellPrice()));
end

rule "Nagpur Groceries Item"
   when
      item : ItemCity(purchaseCity == ItemCity.City.NAGPUR, 
         typeofItem == ItemCity.Type.GROCERIES)
   then
      BigDecimal tax = new BigDecimal(1.0);
      item.setLocalTax(tax.multiply(item.getSellPrice()));
end

Nous avons écrit les fichiers DRL en fonction de la ville, car cela nous donne la possibilité d'ajouter un nombre quelconque de fichiers de règles ultérieurement si de nouvelles villes sont ajoutées.

Pour démontrer que toutes les règles sont déclenchées à partir de nos fichiers de règles, nous avons utilisé deux types d'articles (médicaments et épicerie); et les médicaments sont exonérés de taxe et les produits d'épicerie sont taxés selon la ville.

Notre classe de test charge les fichiers de règles, insère les faits dans la session et produit la sortie.

Droolstest.java

package com.sample;

import java.math.BigDecimal;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;
import com.sample.ItemCity.City;
import com.sample.ItemCity.Type;

/* 
   *This is a sample class to launch a rule. 
*/

public class DroolsTest {
   public static final void main(String[] args) {
      try {
         // load up the knowledge base
         KnowledgeBase kbase = readKnowledgeBase();
         StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
         
         ItemCity item1 = new ItemCity();
         item1.setPurchaseCity(City.PUNE);
         item1.setTypeofItem(Type.MEDICINES);
         item1.setSellPrice(new BigDecimal(10));
         ksession.insert(item1);
         
         ItemCity item2 = new ItemCity();
         item2.setPurchaseCity(City.PUNE);
         item2.setTypeofItem(Type.GROCERIES);
         item2.setSellPrice(new BigDecimal(10));
         ksession.insert(item2);
         
         ItemCity item3 = new ItemCity();
         item3.setPurchaseCity(City.NAGPUR);
         item3.setTypeofItem(Type.MEDICINES);
         item3.setSellPrice(new BigDecimal(10));
         ksession.insert(item3);
         
         ItemCity item4 = new ItemCity();
         item4.setPurchaseCity(City.NAGPUR);
         item4.setTypeofItem(Type.GROCERIES);
         item4.setSellPrice(new BigDecimal(10));         
         ksession.insert(item4);
         
         ksession.fireAllRules();
         
         System.out.println(item1.getPurchaseCity().toString() + " " 
            + item1.getLocalTax().intValue());
         
         System.out.println(item2.getPurchaseCity().toString() + " "
            + item2.getLocalTax().intValue());
         
         System.out.println(item3.getPurchaseCity().toString() + " "
            + item3.getLocalTax().intValue());
         
         System.out.println(item4.getPurchaseCity().toString() + " "
            + item4.getLocalTax().intValue());
                            
      } catch (Throwable t) {
         t.printStackTrace();
      }
   }
   private static KnowledgeBase readKnowledgeBase() throws Exception {
      KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
      kbuilder.add(ResourceFactory.newClassPathResource("Pune.drl"), ResourceType.DRL);
      kbuilder.add(ResourceFactory.newClassPathResource("Nagpur.drl"), ResourceType.DRL);
      KnowledgeBuilderErrors errors = kbuilder.getErrors();
      
      if (errors.size() > 0) {
         for (KnowledgeBuilderError error: errors) {
            System.err.println(error);
         }
         throw new IllegalArgumentException("Could not parse knowledge.");
      }
      KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
      kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
      return kbase;
   }
}

Si vous exécutez ce programme, sa sortie serait la suivante -

PUNE 0
PUNE 20
NAGPUR 0
NAGPUR 10

Pour Pune et Nagpur, lorsque l'article est un médicament, la taxe locale est de zéro; alors que lorsque l'article est un produit d'épicerie, la taxe est selon la ville. Plus de règles peuvent être ajoutées dans les fichiers DRL pour d'autres produits. Ceci n'est qu'un exemple de programme.

Appeler une fonction externe depuis un fichier DRL

Ici, nous allons montrer comment appeler une fonction statique à partir d'un fichier Java dans votre fichier DRL.

Tout d'abord, créez une classe HelloCity.java dans le même emballage com.sample.

package com.sample;

public class HelloCity {
   public static void writeHello(String name) {
      System.out.println("HELLO " + name + "!!!!!!");
   }
}

Ensuite, ajoutez l'instruction d'importation dans le fichier DRL pour appeler la méthode writeHello à partir du fichier DRL. Dans le bloc de code suivant, les modifications du fichier DRL Pune.drl sont surlignées en jaune.

// created on: Dec 24, 2014
package droolsexample

// list any import classes here.
import com.sample.ItemCity;
import java.math.BigDecimal;
 
import com.sample.HelloCity;

//declare any global variables here
dialect "java"

rule "Pune Medicine Item"
   when
      item : ItemCity(purchaseCity == ItemCity.City.PUNE, 
         typeofItem == ItemCity.Type.MEDICINES)
   then
      BigDecimal tax = new BigDecimal(0.0);
      item.setLocalTax(tax.multiply(item.getSellPrice()));
      HelloCity.writeHello(item.getPurchaseCity().toString());
end

rule "Pune Groceries Item"
   when
      item : ItemCity(purchaseCity == ItemCity.City.PUNE, 
         typeofItem == ItemCity.Type.GROCERIES)
   then
      BigDecimal tax = new BigDecimal(2.0);
      item.setLocalTax(tax.multiply(item.getSellPrice()));
end

Exécutez à nouveau le programme et sa sortie serait la suivante -

HELLO PUNE!!!!!!
PUNE 0
PUNE 20
NAGPUR 0
NAGPUR 10

La différence maintenant dans la sortie est marquée en jaune, ce qui montre la sortie de la méthode statique dans la classe Java.

L'avantage d'appeler une méthode Java est que nous pouvons écrire n'importe quelle fonction utilitaire / d'assistance en Java et l'appeler à partir d'un fichier DRL.