Drools - Amostra de programa Drools
Neste capítulo, criaremos um projeto Drools para a seguinte declaração de problema -
Dependendo da cidade e do tipo de produto (combinação de cidade e produto), informe-se sobre o imposto local referente a essa cidade.
Teremos dois arquivos DRL para nosso projeto Drools. Os dois arquivos DRL significarão duas cidades em consideração (Pune e Nagpur) e quatro tipos de produtos (mantimentos, medicamentos, relógios e bens de luxo).
O imposto sobre medicamentos nas duas cidades é considerado zero.
Para mantimentos, assumimos uma taxa de Rs 2 em Pune e Rs 1 em Nagpur.
Usamos o mesmo preço de venda para demonstrar resultados diferentes. Observe que todas as regras estão sendo disparadas no aplicativo.
Aqui está o modelo para conter cada 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;
}
}
Arquivos DRL
Conforme sugerido anteriormente, usamos dois arquivos DRL aqui: Pune.drl e Nagpur.drl.
Pune.drl
Este é o arquivo DRL que executa as regras para a cidade 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
Este é o arquivo DRL que executa as regras para a cidade 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
Escrevemos os arquivos DRL com base na cidade, pois nos dá extensibilidade para adicionar qualquer número de arquivos de regras posteriormente, se novas cidades estiverem sendo adicionadas.
Para demonstrar que todas as regras estão sendo acionadas de nossos arquivos de regras, usamos dois tipos de itens (medicamentos e mantimentos); e os remédios são isentos de impostos e os mantimentos são tributados de acordo com a cidade.
Nossa classe de teste carrega os arquivos de regras, insere os fatos na sessão e produz a saída.
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;
}
}
Se você executar este programa, sua saída será a seguinte -
PUNE 0
PUNE 20
NAGPUR 0
NAGPUR 10
Para Pune e Nagpur, quando o item é um medicamento, o imposto local é zero; já quando o item é de mercearia, o imposto é o da cidade. Mais regras podem ser adicionadas aos arquivos DRL para outros produtos. Este é apenas um programa de amostra.
Chame uma função externa de um arquivo DRL
Aqui, demonstraremos como chamar uma função estática de um arquivo Java em seu arquivo DRL.
Em primeiro lugar, crie uma classe HelloCity.java no mesmo pacote com.sample.
package com.sample;
public class HelloCity {
public static void writeHello(String name) {
System.out.println("HELLO " + name + "!!!!!!");
}
}
Depois disso, adicione a instrução import no arquivo DRL para chamar o método writeHello do arquivo DRL. No bloco de código a seguir, as alterações no arquivo DRL Pune.drl são destacadas em amarelo.
// 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
Execute o programa novamente e sua saída será a seguinte -
HELLO PUNE!!!!!!
PUNE 0
PUNE 20
NAGPUR 0
NAGPUR 10
A diferença agora na saída está marcada em amarelo, o que mostra a saída do método estático na classe Java.
A vantagem de chamar um método Java é que podemos escrever qualquer função utilitário / auxiliar em Java e chamá-la de um arquivo DRL.