Учебники

Drools — Пример программы Drools

В этой главе мы создадим проект Drools для следующей постановки задачи:

В зависимости от города и вида продукта (комбинация города и продукта) узнайте местный налог, связанный с этим городом.

У нас будет два файла DRL для нашего проекта Drools. Два файла DRL будут обозначать два рассматриваемых города (Пуна и Нагпур) и четыре типа товаров (продукты питания, лекарства, часы и предметы роскоши).

  • Налог на лекарства в обоих городах считается нулевым.

  • Для продуктов мы взяли налог в 2 рупии в Пуне и 1 рупию в Нагпуре.

Налог на лекарства в обоих городах считается нулевым.

Для продуктов мы взяли налог в 2 рупии в Пуне и 1 рупию в Нагпуре.

Мы использовали одну и ту же цену продажи, чтобы продемонстрировать разные результаты. Обратите внимание, что все правила запускаются в приложении.

Вот модель для хранения каждого 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;
   }
}

Файлы DRL

Как предлагалось ранее, мы использовали два файла DRL: Pune.drl и Nagpur.drl.

Pune.drl

Это файл DRL, который выполняет правила для города Пуна.

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

Это файл DRL, который выполняет правила для города Нагпур.

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

Мы написали файлы DRL, основанные на городе, поскольку это дает нам возможность добавлять любое количество файлов правил позже, если добавляются новые города.

Чтобы продемонстрировать, что все правила запускаются из наших файлов правил, мы использовали два типа элементов (лекарства и продукты питания); и медицина не облагается налогом, а продукты облагаются налогом в соответствии с городом.

Наш тестовый класс загружает файлы правил, вставляет факты в сеанс и выдает результат.

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

Если вы запустите эту программу, ее вывод будет следующим:

PUNE 0
PUNE 20
NAGPUR 0
NAGPUR 10

Для Пуны и Нагпура, когда предмет является лекарством, местный налог равен нулю; тогда как, когда продукт — продуктовый продукт, налог в соответствии с городом. Дополнительные правила могут быть добавлены в файлы DRL для других продуктов. Это всего лишь пример программы.

Вызов внешней функции из файла DRL

Здесь мы продемонстрируем, как вызывать статическую функцию из файла Java в вашем файле DRL.

Прежде всего, создайте класс HelloCity.java в том же пакете com.sample .

package com.sample;

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

После этого добавьте оператор импорта в файл DRL, чтобы вызвать метод writeHello из файла DRL. В следующем блоке кода изменения в файле DRL Pune.drl выделены желтым цветом.

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

Запустите программу еще раз, и ее вывод будет следующим:

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

Теперь разница в выводе отмечена желтым цветом, который показывает вывод статического метода в классе Java.

Преимущество вызова метода Java состоит в том, что мы можем написать любую вспомогательную / вспомогательную функцию на Java и вызвать ее из файла DRL.