Drools Albuquerque
Jump to navigation
Jump to search
Basic
EX1
rule "01. Select all Salgrade facts"
when
$s : Salgrade()
then
System.out.println(
$s.grade + "\t" +
$s.losal + "\t" +
$s.hisal);
endEX2
rule "2 - Select shown data about employees who earn between 1000 and 2000."
// enabled false
when
$e : Emp( sal>=1000, sal<=2000 )
then
System.out.println(
$e.id + " " +
$e.name + " " +
$e.job + " " +
$e.mgr + " " +
$e.hiredate + " " +
$e.sal + " " +
$e.deptno);
endEX3
rule "Clerks in 20"
enabled true
when
$e : Emp($e.getJob() == "CLERK" , $e.getDeptno() == 20)
then
System.out.println($e.getId() + " " + $e.getName() + "\t" + $e.getJob()
+ "\t" + $e.getMgr() + " " + $e.getHiredate() + " " + $e.getSal() + " " + $e.getDeptno())
endEX4
rule "04. Select employees who have a boss."
when
//$e : Emp( job in ('SALESMEN', 'CLERK', 'ANALYST'))
$e : Emp( job not in ('PRESIDENT', 'MANAGER'))
then
System.out.println($e.id + " " +
$e.name + " " +
$e.job + " " +
$e.mgr + " " +
$e.hiredate + " " +
$e.sal + " " +
$e.deptno);
endEX5
/*
7566 PUTIN MANAGER 7839 1981 35700 20
7782 MERKEL MANAGER 7839 1981 29400 10
7698 BLAIR MANAGER 7839 1981 34200 30
*/
rule "05. Select manager's annual remuneration"
enabled true
when
$e : Emp(job == "MANAGER")
then
System.out.println($e.id + "\t"
+ $e.name + "\t"
+ $e.job + "\t"
+ $e.mgr + "\t"
+ $e.hiredate + "\t"
+ ($e.sal*12) + "\t"
+ $e.deptno)
endEX6
/*Expected Output
+-------+
| name |
+-------+
| BLAIR |
+-------+
*/
rule "employees with second letter “L” and third “A”"
when
$e : Emp(name matches ".LA.*")
then
System.out.println("| " + $e.name + " |")
endEX7
rule "7 - Find employees whose name ends with N and contains T."
// enabled false
when
$e : Emp( name matches ".*T.*N" )
then
System.out.println($e.name);
endEX8
/* EXPECTED OUTPUT:
+--------+-----------+--------+
| ename | job | deptno |
+--------+-----------+--------+
| BUSH | PRESIDENT | 10 |
| BLAIR | MANAGER | 30 |
| PUTIN | MANAGER | 20 |
| ELISON | CLERK | 10 |
+--------+-----------+--------+
*/
rule "08. Find employees who either work as managers or work in department no 10, but not both."
enabled true
when
$e : Emp( (job == "MANAGER" && deptno != 10) ||
(job != "MANAGER" && deptno == 10) )
then
System.out.println("+--------+-----------+--------+");
System.out.printf("| %-6s | %-9s | %-6s |\n", $e.name, $e.job, $e.deptno );
endAdvanced
EX31
rule "31 - Select the name of the employee and the city (LOC column in DEPT table) in which they work"
// enabled false
when
$e : Emp()
$d : Dept( deptno == $e.deptno )
then
System.out.println($e.name + "\t" + $d.loc);
endEX32
rule "Select the names of the employees, and the name and number of their department"
enabled true
when
$e : Emp()
$d : Dept($e.deptno == deptno)
then
System.out.println($e.name + "\t" + $d.dname + "\t" + $d.deptno)
endEX33
/* 33. EXPECTED OUTPUT:
+----------+---------+-------+
| ename | sal | grade |
+----------+---------+-------+
| BUSH | 5000.00 | 5 |
| BLAIR | 2850.00 | 4 |
| MERKEL | 2450.00 | 4 |
| PUTIN | 2975.00 | 4 |
| TOOSK | 3000.00 | 4 |
| CARNEGIE | 3000.00 | 4 |
+----------+---------+-------+
*/
rule "33. Select the names of the employees, their salary and salary grade, but only those whose salary is more than 2000."
enabled false
when
e : Emp( sal > 2000 )
s : Salgrade(e.sal >= losal && e.sal <= hisal)
then
System.out.printf("| %-8s | %-4s.00 | %-9s |\n", e.name, e.sal, s.grade );
endEX34
rule 'London employees'
enabled true
when
$e : Emp()
$d : Dept($e.deptno == deptno && loc == 'LONDON')
then
System.out.println($e.name + '\t' + $d.loc);
endEX35
rule "35. Select employees and their salary grades except those from London."
enabled true
when
$d : Dept(loc != "LONDON")
$e : Emp(deptno == $d.deptno)
$s : Salgrade(losal <= $e.sal && $e.sal <= hisal)
then
System.out.println($e.name + "\t"
+ $d.loc + "\t"
+ $s.grade)
endEX36
/* Expected Output
OPERATIONS
*/
rule "Find departments without employees"
enabled true
when
d :Dept()
not (Emp(deptno == d.deptno))
then
System.out.println(d.dname)
end
EX37
rule "#37 Employee and their boss"
// enable false
when
$e :Emp()
$m :Emp(id == $e.mgr)
then
System.out.println($m.name + " manages " + $e.name)
endEX38
/* 38. EXPECTED OUTPUT:
BUSH
*/
rule "38. Select employees who doesn't have a boss. "
enabled true
when
e : Emp()
not (Emp(e.mgr == id))
then
System.out.println(e.name);
endEX39
rule "39 - Show all employees who have no subordinates"
// enabled false
when
$e: Emp()
not ( Emp( mgr==$e.id ) )
then
System.out.println($e.name);
endEX41
// Exercise 41
rule "Select employees hired earlier than their bosses"
enabled true
when
$e :Emp()
$m :Emp($e.mgr == $m.id , $e.hiredate < $m.hiredate)
then
System.out.println($e.name + " was hired in " + $e.hiredate
+ " the boss " + $m.name + " was hired in " + $m.hiredate)
endEX44
rule "44 - Find jobs which are in department 10 but not in department 20."
// enabled false
when
$e1: Emp( deptno==10 )
not (Emp( deptno==20, job==$e1.job ))
// NOTE: this isn't the most stable:
// If two employees, both in department 10, have the same job, and that job is not in department 20, it will be printed twice.
// But we can do no better with what we've learned up until this point in the course.
then
System.out.println($e1.job);
endEX23
// Exercise 23
rule "Find the minimal, maximal and average salaries of people employed in 1981"
enabled true
when
accumulate (e :Emp(hiredate == 1981),
$avg : average(e.sal),
$min : min(e.sal),
$max : max(e.sal)
)
then
System.out.println(
"Average salary: " + $avg + "\n" +
"Min salary: " + $min + "\n" +
"Max salary: " + $max + "\n"
)
endEX24
rule "Ex 24. Find the difference between maximal and minimal salary."
when
accumulate (e :Emp(),
$min : min(e.sal),
$max : max(e.sal)
)
then
System.out.println("Salary range: " + ($max-$min) + ".");
endEX26
rule "How many managers work for the company?"
enabled true
when
accumulate (e :Emp(job == "MANAGER"), numMgrs : count(e))
then
System.out.println("Company has " + numMgrs + " managers")
endEX25
+-----------+-------------+
| job | Average |
+-----------+-------------+
| ANALYST | 3000.000000 |
| CLERK | 1037.500000 |
| MANAGER | 2758.333333 |
| PRESIDENT | 5000.000000 |
| SALESMAN | 1400.000000 |
+-----------+-------------+
declare SalByJob
job : String
end
rule "#25 - Find the average salary for every post."
//enabled true
when
Emp(j: job) and
not SalByJob(j == job)
accumulate (e :Emp(job == j), $avg : average(e.sal))
then
System.out.println("Position " + j + " has average salary: " + $avg + "." )
insert(new SalByJob(j))
endEX27
/* 27. EXPECTED OUTPUT:
+--------+-----------------+
| deptno | Annual Salaries |
+--------+-----------------+
| 10 | 35000.000000 |
| 20 | 26100.000000 |
| 30 | 18800.000000 |
+--------+-----------------+
*/
declare Deps
dn : int
end
rule "27. Find the average annual salaries in departments."
enabled true
when
Emp( d : deptno ) and not Deps( d == dn )
accumulate (
e : Emp( d == deptno ),
avg : average((e.sal * 12))
)
then
System.out.printf("| %s | %.2f |\n", d, avg);
insert(new Deps(d))
endEX43
declare AlreadyFiredRule43
job : String
end
rule "43 - Find post filled in 1982 and 1983."
// enabled false
when
Emp( $post: job, hiredate==1982)
and not AlreadyFiredRule43( job==$post )
Emp( job==$post, hiredate==1983)
then
System.out.println($post);
insert(new AlreadyFiredRule43($post));
endrule "43+"
when
e1 : Emp(hiredate == 1982)
e2 : Emp(hiredate == 1983)
exists (Emp(e1.job == job, e2.job == job))
then
System.out.println( e1.job)
endEX28
/* 28. EXPECTED OUTPUT:
+--------+----------+
| deptno | count(*) |
+--------+----------+
| 20 | 5 |
| 30 | 6 |
+--------+----------+
*/
rule "28. Find departments with more than 3 workers."
enabled true
when
Dept( d : deptno )
accumulate (
e : Emp(d == deptno),
c : count(e)
)
Number(doubleValue > 3) from c
then
System.out.printf("| %s | %s |\n", d, c);
endEX45
rule "45 - Find employees earning more than the manager's (job=='MANAGER') average."
// enabled false
when
accumulate(
$m : Emp ( job=="MANAGER", $ss: sal ),
$avg : average($ss)
)
$e: Emp( $s: sal>$avg.doubleValue(), $n: name )
then
System.out.println($n + " " + $s);
endEX46
solution 1
/* 46. EXPECTED OUTPUT:
+----------+-----------+---------+
| ename | job | sal |
+----------+-----------+---------+
| ELISON | CLERK | 1300.00 |
| BAROSSO | SALESMAN | 1600.00 |
| PUTIN | MANAGER | 2975.00 |
| TOOSK | ANALYST | 3000.00 |
| CARNEGIE | ANALYST | 3000.00 |
| BUSH | PRESIDENT | 5000.00 |
+----------+-----------+---------+
*/
rule "46. Select employees earning the maximum salaries in their positions (jobs). "
enabled false
when
e : Emp()
Number(max_sal : longValue) from accumulate (Emp(s: sal, job == e.job), max(s))
Number(doubleValue == e.sal) from max_sal
then
System.out.printf("| %-9s | %-10s | %s.00 |\n", e.name, e.job, e.sal);
endsolution 2 - doesn't work
declare RichJobs
job: String
name: String
end
//Example 46
rule "Select employees earning the maximum salaries in their positions (jobs). "
when
Emp($job: job, $name: name, $sal: sal) and not RichJobs($job == job, $name == name)
accumulate (
$e: Emp(job == $job),
$max: max($e.sal)
)
Number($sal == $max) from $max
then
System.out.println(
$name + " | " + $job + " | " + $max + "\n"
)
insert(new RichJobs($job, $name))
endEX51
rule "51. Find employees earning more than the average salary in their department."
enabled true
when
e : Emp()
Number(longValue < e.sal) from accumulate (Emp(s : sal, deptno == e.deptno), average(s))
then
System.out.println(e.name + " " + e.sal + " " + e.deptno);
endEX55
solution 1
declare AvgDep
deptno: int
avg: long
end
rule "55.a *Exercise Find the maximum average salary of departments. " enabled true
when
$dept : Dept($deptno:deptno,$dname:dname)
Number($avg : longValue) from accumulate (Emp(deptno==$deptno, $s: sal),average($s))
then
insert(new AvgDep($deptno,$avg))
end
rule "55.b " enabled true
when
Number($max : longValue) from accumulate (AvgDep($avg: avg),max($avg))
AvgDep(avg==$max,$deptno:deptno)
$d: Dept(deptno==$deptno)
then
System.out.println($d.dname+' '+$d.deptno+' '+ $max)
endsolution 2
/* 55. EXPECTED OUTPUT:
10 2916.666667
*/
rule "55. Find the maximum average salary of departments."
enabled true
when
Number(max_val : doubleValue) from accumulate (
Dept( d : deptno )
and
Number(avg_val : doubleValue) from accumulate (
Emp(s: sal, deptno == d), average(s)
), max(avg_val)
)
then
System.out.printf("%f\n", max_val);
end
insertLogical
Rules
package _30_mvel
import com.nobleprog.FactModel.*
dialect "mvel"
declare AccessToSecretFile
emp : Emp
end
rule "Grant access to employees of Dept. 10"
when
e : Emp( deptno == 10 )
then
insertLogical( new AccessToSecretFile(e) )
end
jUnit test
package com.nobleprog;
import org.junit.Test;
import org.kie.api.KieServices;
import org.kie.api.event.KieRuntimeEventManager;
import org.kie.api.logger.KieRuntimeLogger;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
import org.kie.internal.logger.KnowledgeRuntimeLoggerFactory;
import com.nobleprog.FactModel.*;
public class Test01 {
@Test
public void test1() {
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession ksession = kContainer.newKieSession("ksession-rules");
/**
* Prepare Data
*/
ksession.insert(new Emp(7839, "BUSH", "PRESIDENT", 0, 1981, 5000, 10));
ksession.insert(new Emp(7782, "MERKEL", "MANAGER", 7839, 1981, 2450, 10));
ksession.insert(new Emp(7566, "PUTIN", "MANAGER", 7839, 1981, 2975, 20));
ksession.insert(new Emp(7654, "CHIRACK", "SALESMAN", 7698, 1981, 1250,30));
ksession.insert(new Emp(7499, "BAROSSO", "SALESMAN", 7698, 1981, 1600,30));
ksession.insert(new Emp(7844, "GATES", "SALESMAN", 7698, 1981, 1500, 30));
ksession.insert(new Emp(7900, "BUFFETT", "CLERK", 7698, 1981, 950, 30));
ksession.insert(new Emp(7521, "WALTON", "SALESMAN", 7698, 1981, 1250,30));
ksession.insert(new Emp(7902, "TOOSK", "ANALYST", 7566, 1981, 3000, 20));
ksession.insert(new Emp(7369, "THATCHER", "CLERK", 7902, 1980, 800, 20));
ksession.insert(new Emp(7788, "CARNEGIE", "ANALYST", 7566, 1982, 3000,20));
ksession.insert(new Emp(7876, "FORD", "CLERK", 7788, 1983, 1100, 20));
ksession.insert(new Emp(7934, "ELISON", "CLERK", 7782, 1982, 1300, 10));
ksession.insert(new Emp(7698, "BLAIR", "MANAGER", 7839, 1981, 2850, 30));
Emp elison = new Emp(7934, "ELISON", "CLERK", 7782, 1982, 1300, 10);
FactHandle elisonFH = ksession.insert(elison);
KieRuntimeLogger logger =
KnowledgeRuntimeLoggerFactory.newFileLogger((KieRuntimeEventManager) ksession, "/tmp/logicalinsert_exercise");
ksession.fireAllRules();
elison.setDeptno(20);
ksession.update(elisonFH, elison);
ksession.fireAllRules();
logger.close();
}
}
DSL
EX1
package rules1
import com.nobleprog.FactModel.*;
import java.lang.Math
dialect "mvel"
expander Exercise01.dsl
rule "Rule 1"
when
There are employees earning more than 2000
then
Show name and salary
end[condition][]There (is (a|an)|are) {o} {cond}=$e: {o}( {cond} )
[consequence][]Show {f1} and {f2}=System.out.println($e.{f1} + ", " + $e.{f2});
[keyword][Emp]salary=sal
[keyword][]employees?=Emp
[keyword][Emp]earning more than {amt}=sal>{amt}EX2
[condition][]There is a department which:=d:Dept()
[consequence][]Show department name=System.out.println(d.dname)
[condition][]has at least {c} employees working in it=accumulate(e:Emp(deptno == d.deptno), $countOfEmployees : count(e)) && Number(intValue >= {c}) from $countOfEmployees
[condition][]average salary is greater than {sal}=accumulate(e2:Emp(deptno == d.deptno), $avgSal: average(e2.sal)) && Number(doubleValue > {sal}) from $avgSalpackage rules2
import com.nobleprog.FactModel.*;
import java.lang.Math
dialect "mvel"
expander Exercise02.dsl
rule "Rule 2"
when
There is a department which:
has at least 3 employees working in it
average salary is greater than 2000
then
Show department name
endEX3
package rules3
import com.nobleprog.FactModel.*;
import java.lang.Math
dialect "mvel"
expander Exercise03.dsl
rule "Rule 3"
when
// Make sure that the rule will work for both cases
// There are departments where:
There is a department where:
// there are analysts working in
there is an analyst working in it
then
Show department name
end[condition][]There (is a|are) departments? where:=$d :Dept()
[condition][]there (is an|are) analysts? working in( it)?=exists Emp($d.deptno == deptno , job == "ANALYST")
[consequence][]Show department name=System.out.println($d.dname)
Shopping Example
Fact Model
package newpack;
public class FactModel {
public static class Customer {
@Override
public String toString() {
return "Customer [name=" + name + ", discount=" + discount + "]";
}
public Customer(String name, double discount) {
super();
this.name = name;
this.discount = discount;
}
private String name;
private double discount;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getDiscount() {
return discount;
}
public void setDiscount(double discount) {
this.discount = discount;
}
}
public static class Purchase {
@Override
public String toString() {
return "Purchase [cust=" + cust + ", prod=" + prod + "]";
}
public Purchase(Customer cust, Product prod) {
super();
this.cust = cust;
this.prod = prod;
}
private Customer cust;
private Product prod;
public Customer getCust() {
return cust;
}
public void setCust(Customer cust) {
this.cust = cust;
}
public Product getProd() {
return prod;
}
public void setProd(Product prod) {
this.prod = prod;
}
}
public static class Discount {
@Override
public String toString() {
return "Discount [cust=" + cust + ", discount=" + discount + "]";
}
public Discount(Customer cust, double discount) {
super();
this.cust = cust;
this.discount = discount;
}
private Customer cust;
private double discount;
public Customer getCust() {
return cust;
}
public void setCust(Customer cust) {
this.cust = cust;
}
public double getDiscount() {
return discount;
}
public void setDiscount(double discount) {
this.discount = discount;
}
}
public static class Product {
public Product(String name, double price) {
super();
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Product [name=" + name + ", price=" + price + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
private String name;
private double price;
}
}rules
//created on: Aug 26, 2016
package rules
import newpack.FactModel.*
import java.lang.Math
import java.util.ArrayList
dialect "mvel"
rule "Notify of purchase"
when
p : Purchase()
then
System.out.printf("New purchase made: %s\n", p);
end
declare AlreadyFoundCust
customer : Customer
end
rule "Set discount for total purchase over 1000"
when
c : Customer() and not AlreadyFoundCust(c == customer)
accumulate( Purchase(product : prod && c == cust), total : sum(product.price))
then
System.out.printf("Total: %s\n", total);
insert(new AlreadyFoundCust(c))
endjUnit
package newpack;
import static org.junit.Assert.*;
import org.junit.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import newpack.FactModel.*;
@SuppressWarnings("unused")
public class TestSCRules {
@Test
public void test() {
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession ksession = kContainer.newKieSession("ksession-rules");
/**
* Prepare Data
*/
Customer cust = new Customer("John", 0.0);
ksession.insert(cust);
Product prod1 = new Product("Foo", 600);
ksession.insert(prod1);
Product prod2 = new Product("Bar", 600);
ksession.insert(prod2);
Product prod3 = new Product("Baz", 600);
ksession.insert(prod3);
Purchase pur1 = new Purchase(cust, prod1);
ksession.insert(pur1);
Purchase pur2 = new Purchase(cust, prod2);
ksession.insert(pur2);
ksession.fireAllRules();
}
}