Drools - przykładowy program Drools

W tym rozdziale utworzymy projekt Drools dla następującego stwierdzenia problemu -

W zależności od miasta i rodzaju produktu (połączenie miasta i produktu) sprawdź podatek lokalny związany z tym miastem.

Będziemy mieć dwa pliki DRL dla naszego projektu Drools. Dwa pliki DRL będą oznaczać dwa rozważane miasta (Pune i Nagpur) oraz cztery rodzaje produktów (artykuły spożywcze, leki, zegarki i towary luksusowe).

  • Podatek od leków w obu miastach jest zerowy.

  • W przypadku artykułów spożywczych przyjęliśmy podatek w wysokości 2 Rs w Pune i 1 Rs w Nagpur.

Użyliśmy tej samej ceny sprzedaży, aby zademonstrować różne wyniki. Zwróć uwagę, że wszystkie reguły są uruchamiane w aplikacji.

Oto model do przechowywania każdego przedmiotu -

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

Pliki DRL

Jak sugerowano wcześniej, użyliśmy tutaj dwóch plików DRL: Pune.drl i Nagpur.drl.

Pune.drl

To jest plik DRL, który wykonuje reguły dla miasta 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

To jest plik DRL, który wykonuje reguły dla miasta 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

Napisaliśmy pliki DRL w oparciu o miasto, ponieważ daje nam to możliwość dodania dowolnej liczby plików reguł później, jeśli dodawane są nowe miasta.

Aby zademonstrować, że wszystkie reguły są uruchamiane z naszych plików reguł, użyliśmy dwóch typów pozycji (lekarstwa i artykuły spożywcze); a lekarstwa są wolne od podatku, a artykuły spożywcze są opodatkowane według obowiązującego w mieście podatku.

Nasza klasa testowa ładuje pliki reguł, wstawia fakty do sesji i generuje wynik.

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

Jeśli uruchomisz ten program, jego dane wyjściowe będą następujące -

PUNE 0
PUNE 20
NAGPUR 0
NAGPUR 10

W przypadku Pune i Nagpur, gdy produkt jest lekiem, lokalny podatek wynosi zero; podczas gdy gdy artykuł jest produktem spożywczym, podatek jest według miasta. Więcej reguł można dodać w plikach DRL dla innych produktów. To tylko przykładowy program.

Wywołaj funkcję zewnętrzną z pliku DRL

Tutaj pokażemy, jak wywołać funkcję statyczną z pliku Java w pliku DRL.

Przede wszystkim utwórz klasę HelloCity.java w tym samym opakowaniu com.sample.

package com.sample;

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

Następnie dodaj instrukcję importu w pliku DRL, aby wywołać metodę writeHello z pliku DRL. W poniższym bloku kodu zmiany w pliku DRL Pune.drl są podświetlone na żółto.

// 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

Uruchom program ponownie, a jego wyjście będzie wyglądać następująco -

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

Różnica w wynikach jest teraz oznaczona na żółto, co pokazuje wynik metody statycznej w klasie Java.

Zaletą wywołania metody Java jest to, że możemy napisać dowolną funkcję narzędzia / pomocniczą w Javie i wywołać ją z pliku DRL.