Drools Geneva

From Training Material
Jump to navigation Jump to search

Basic

EX1

rule "Exercise 1 - all Salgrade facts "
enabled false
when 
	$s: Salgrade()
then    
	System.out.format("%d %d %d\n", $s.grade, $s.losal, $s.hisal)
end

EX2

rule "Exercise 2" 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  )
end

EX3

rule "Exercise 3" enabled false
when 
	$e : Emp(deptno == 20, job == "CLERK")
then    
	System.out.println($e.id + " " + $e.name + " " + $e.job + " " + $e.mgr + " " + $e.hiredate 
                             + " " + $e.sal + " " + $e.deptno)
end

EX4

rule "Exercise 4"
when 
	$e : Emp()
	$e2 : Emp(id == $e.mgr) 
then    
	System.out.println($e.id + "\t" + $e.name + "\t" + $e.job + "\t" + $e.mgr + "\t" + $e.hiredate + "\t" + $e.sal + "\t" + $e.deptno)
end

EX5

// Select manager’s annual remuneration. 
rule "Exercise 5"
when 
 $e : Emp(job == "MANAGER") 
then    
 System.out.println($e.id + " " + $e.name + " " + $e.job + " " + $e.hiredate + " " + $e.sal*12 + " " + $e.deptno)
end

EX6

rule "Exercise 6"
when
  $e : Emp(name matches ".LA.*")
then
  System.out.println($e.name)
end

EX7

rule "Exercise 7"
when 
	$e : Emp(name matches '.*N', name contains 'T') 
then    
	System.out.println($e.name)
end

EX8

rule "Exercise 8" 
when 
  $e : Emp((job == 'MANAGER' && deptno != 10) || (job != 'MANAGER' && deptno == 10) )
then    
  System.out.println($e.name+" "+ $e.deptno )

end

Advanced

EX31

rule "Exercise 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\t" + $d.loc)
end

EX32

rule "Exercise 32" enabled false
when 
 e : Emp()
 d : Dept(deptno == e.deptno) 

then    
  System.out.println(e.name + " " + d.dname + " " + d.deptno)
end

EX33

// Select the names of the employees, their salary and salary grade, but only those whose salary is more than 2000. 

rule "Exercise 33" enabled false
when
   d :Dept()
   e :Emp(d.deptno == e.deptno)
   s :Salgrade(e.sal >= 2000, e.sal >= losal, e.sal <= hisal)
then    
  System.out.println(e.name + "\t" + e.sal + "\t" + s.grade)
end

EX34

// Select employees working in London.

rule "Exercise 34"
when
   d :Dept()
   e :Emp(d.deptno == e.deptno, d.loc == "LONDON")
then    
  System.out.println(e.name + "\t" + d.loc)
end

EX35

rule "Exercise 35"
when 
	$e : Emp()
	$s : Salgrade(losal <= $e.sal, hisal > $e.sal) 
	$d : Dept(loc != 'LONDON', $e.deptno == deptno) 
then    
	System.out.println($e.name + "\t" + $s.grade + "\t" + $d.loc)
end

EX36

// 36. Exercise
// Find departments without employees. 
rule "36. Exercise"  enabled false
when
   d :Dept()
   not (Emp(deptno == d.deptno))
then    
  System.out.println( d.dname )
end

EX37

// 37. *Exercise
// Select an employee’s name and his/her boss’s name 
rule "37. Exercise"  enabled false
when
   e :Emp()
   m :Emp(m.id == e.mgr)
then    
  System.out.println( m.name + " boss of " + e.name   )
end

EX38

// Select employees who doesn't have a boss.

rule "Exercise 38" enabled false  
when
   e :Emp()
   not Emp(id == e.mgr)
then    
  System.out.println(e.name)
end

EX39

rule "Exercise 39"
  //enabled false
when
  $m : Emp()
  not (Emp(mgr == $m.id))
then
  System.out.println($m.name)
end

EX41

rule "Exercise 41" enabled false 
when 
 e : Emp($hd : hiredate)
 m : Emp(e.mgr == id && $hd<hiredate)
then    
  System.out.println(e.name + ' was hired in ' + e.hiredate + ', her boss ' + m.name + ' was hired in ' + m.hiredate)
end

EX44

rule "Exercise 44"
when  	
	$e: Emp(deptno == 10)
	not(Emp(job == $e.job, deptno == 20))
then    
	System.out.println($e.job)
end

EX23

// Find the minimal, maximal and average salaries of people employed in 1981. 

rule "Exercise 23" enabled false
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"
)
end

EX24

// Find the difference between maximal and minimal salary.
rule "Exercise 24"
  //enabled false
when
  accumulate ($e : Emp(),
    $min : min($e.sal),
    $max : max($e.sal)
  )
then
  System.out.println("Salary range: " + ($max - $min))
end

EX26

rule "Exercise 26" 
when 
 accumulate (e:Emp(job == 'MANAGER'), $count : count(e))
then    
  System.out.println('count ' + $count)
end

EX25

declare JobType
  job : String
end

rule "Exercise 25"
  enabled false
when
  Emp($j : job)
  not JobType($j == job)
  accumulate ($e : Emp(job == $j),
    $avgsal : average($e.sal)
  )
then
  System.out.println($j + "\t" + $avgsal)
  insert(new JobType($j))
end

EX27

// Find the average annual salaries in departments.

declare AvgYearlySalPerDept
   deptno: int
   avgsal: Double
end

rule "Exercise 27" enabled false
when
	Emp($d: deptno) and not AvgYearlySalPerDept($d == deptno)
	accumulate (e :Emp(deptno == $d), $avg : average(e.sal * 12))
then
   System.out.println($d + "\t|\t" + $avg)
   insert (new AvgYearlySalPerDept($d, $avg))
end

rule "Exercise 27 - average annual salaries in departments"
when
  Dept($d: deptno) and
  accumulate (e :Emp(deptno == $d), $avg : average(e.sal * 12))
then    
  System.out.println(   $d + ": " + $avg )
end

// lj:
rule "Exercise 27"
when 
	$d : Dept($dept : deptno) 
	accumulate (f: Emp($sal : sal, deptno == $dept),
		$avg : average(12 * $sal)
	)
then    
	System.out.println($d.deptno + " " + $avg)
end

EX43

declare CountByJob
  job : String
end 

rule "Exercise 43" 
when 
 em: Emp(j : job)
 exists Emp(job == j && (hiredate==1982)) 
 exists Emp(job == j && (hiredate==1983))
 not (CountByJob(job == j))
 accumulate (e:Emp(job == j) , $count : count())
then    
  System.out.println(em.job + ' ' + $count)
  insert (new CountByJob(em.job))
end

//lj:
rule "Exercise 43"
when 
	$e : Emp(hiredate == 1982, $job: job)
	exists(Emp(hiredate == 1983, job == $job)) 
then    
	System.out.println($e.job)
end

EX28

rule "Exercise 28" enabled false
when
    Dept($deptno: deptno)
	accumulate (e :Emp(deptno == $deptno), $cnt: count(e))
	Number($cnt > 3) from $cnt
then
	System.out.println($deptno + " " + $cnt)
end

EX45

rule "Exercise 45"
when 
	Number($avg : longValue) from accumulate (m :Emp(job == 'MANAGER'), average(m.sal)) 
	$e : Emp(sal > $avg)
then    
	System.out.println($e.name + "\t" + $e.sal)
end

EX46

rule "Exercise 46"
when 
	$e : Emp()
	not (Emp(sal > $e.sal, job == $e.job))
then    
	System.out.println($e.name + "\t" + $e.sal)
end

declare MaxJob
	name: String
	max: long
end	

rule "Exercise 46 BIS"
when
	$e : Emp($job : job) 	
	Number($max : longValue) from accumulate (m :Emp(job == $job), max(m.sal))
	not(MaxJob(name == $job))
then    
	insert(new MaxJob($job, $max))
end

rule "Exercise 46 BIS - 2"
when
	$m : MaxJob()
	$e : Emp(job == $m.name, sal == $m.max)
then    
	System.out.println($e.name + "\t" + $e.job + "\t" + $e.sal)
end

EX51

rule "Exercise 51 - employees earning more than the average salary in their department."
enabled false
when
  $e: Emp()
  Number($avg : longValue) from  accumulate (e:Emp(deptno == $e.deptno), average(e.sal))
  exists Emp($avg <= sal, $e.id == id)
then    
  System.out.println(   $e.name + ": " + $e.job + " "+ $e.sal)
end

EX55

declare DeptAvg
   dept : String
   avg: double
end

rule "Exercise 55 - Find the maximum average salary of departments. (1/2)"
when
  $d: Dept()
  accumulate (e:Emp(deptno == $d.deptno), $avg: average(e.sal))
then    
  insert(new DeptAvg($d.dname, $avg))
end

rule "Exercise 55 - Find the maximum average salary of departments. (2/2)"
when
  $da: DeptAvg()
  not DeptAvg(avg > $da.avg)
then    
  System.out.println(   $da.dept + " " + $da.avg)
end

//

declare AvgJob
	deptno: Number
	avg: double
end	

rule "Exercise 55"
when
	$e : Dept($deptno : deptno) 	
	Number($avg : doubleValue) from accumulate (m :Emp(deptno == $deptno), average(m.sal))
	not(AvgJob(deptno == $deptno))
then    
	insert(new AvgJob($deptno, $avg))
end

rule "Exercise 55 B"
when
	accumulate (a :AvgJob(), 
  	$max : max(a.avg)
  	) 
then    
	System.out.println($max)
end

// two accumulate functions

rule "55. Find the maximum average salary of departments." enabled true
when 
	Number($max : doubleValue) from accumulate(
		$dep : Dept($depId : deptno)
		and
		Number($avg : doubleValue) 
			from accumulate($emp : Emp(deptno == $depId),
		   		average($emp.sal)
			),
		max($avg)
	)
    d:Dept()
    Number($avgOfDept : doubleValue) from accumulate(e:Emp(deptno == d.deptno), average(e.sal))
    Number(doubleValue == $max) from $avgOfDept
then   
  	System.out.println(d.deptno + " Salary: " + $max)
end

///

rule "Exercise 55 B"
when
	 $max : Number() from accumulate(
	     $e : Dept($deptno : deptno) and
         $avg: Number() from accumulate(
         	m :Emp(deptno == $deptno), average(m.sal)
         ),
         max( $avg ) 
	)
then    
	System.out.println($max)
end

EX29

declare NotUnique
end

rule "Exercise 29"
when
	$e: Emp()
	exists(Emp(id == $e.id && this != $e))
then    
	insert(new NotUnique())	
end

rule "isUnique"
when
	not(NotUnique())
then    
	System.out.println("All Un1que!")
end

declare EmpUnique
   id : long
   cnt : int
end

rule "Exercise 29 - Every Id is unique"
when
  	$e: Emp()
  	accumulate (e: Emp(id == $e.id), $cnt : count(e))
then    
  insert(new EmpUnique($e.id, $cnt))
end

rule "Exercise 29 - Every Id is unique (check)"
when
  	forall(EmpUnique(cnt == 1))
then    
  System.out.println("Every Id is unique")
end

// ----

declare EmpType
  id : long
end

rule "Exercise 29"
when
  $e : Emp()
  accumulate ($e2 : Emp(id == $e.id),
    $count : count()
  )
  Number(longValue != 1) from $count 
  not EmpType(id == $e.id)
then
  insert(new EmpType($e.id))
  System.out.println($e.id + "\t" + $count)
end

Shopping Example

Fact Model

rules

rule "Notify about purchase"
no-loop true
when
    $p : Purchase()
then
    System.out.format("Customer %s just purchased a %s\n", $p.customer.name, $p.product.name);
end

rule "Check apply discount"
when
    $c : Customer()
    accumulate (pur: Purchase(customer == $c), $sum: sum(pur.product.price))
    Number(intValue >= 1000) from $sum
    not Discount(customer == $c)
then
    System.out.format("Customer %s for your purchase you received a discount of 10 \n", $c.name);
    insert(new Discount($c, 10));
end

rule "Notify client about discount removal"
when 
   $c : Customer()
   accumulate (pur: Purchase(customer == $c), $sum: sum(pur.product.price))
   Number(intValue < 1000) from $sum
   $d: Discount(customer == $c)
then    
    System.out.format("Customer %s you lost your discount.\n", $c.name);
	retract($d)
end

// -------------

rule "Notify about Purchase"
	no-loop true
    when
        $p : Purchase()
    then    	
        System.out.printf("%1$s just purchased %2$s.\n",$p.getCustomer(),$p.getProduct())
end

rule "Give discount"
	no-loop true
    when    	
        $c : Customer()               
        $total: Float() from accumulate(
        	$p : Purchase(customer == $c) and
        	$m : Product(this == $p.getProduct()),         		
         	sum( $m.getPrice() ) 
        )
        Number($total > 1000) from $total
    then    	
    	insertLogical(new Discount($c, 10))
end

rule "Notify on discount"
	no-loop true
    when    	
        $d : Discount()               
    then    	
    	System.out.printf("%1$s just got awarded %2$s%% discount.\n",$d.getCustomer(),$d.getAmount())
end

jUnit test

public class TestScenario {
	private KieSession ks;
	
	@Before
	public void setUp() {
		KieServices ksvr = KieServices.Factory.get();
		KieContainer kContainer = ksvr.getKieClasspathContainer();
		this.ks = kContainer.newKieSession("ksession-rules");
	}
	
	@After
	public void tearDown() {
		ks.dispose();
	}
	
	@Test
	public void testCase() {
		KnowledgeRuntimeLogger logger =
				KnowledgeRuntimeLoggerFactory.newFileLogger((KnowledgeRuntimeEventManager) ks, "/tmp/shopping_model");
		
		Customer customer1 = new Customer("Test", 10);
		ks.insert(customer1);
		
		Product product1 = new Product("Laser", 600);
		Product product2 = new Product("Shower Gel", 600);
		ks.insert(product1);
		ks.insert(product2);
		
		Purchase purchase1 = new Purchase(customer1, product1);
		Purchase purchase2 = new Purchase(customer1, product2);
		FactHandle fh = ks.insert(purchase1);
		ks.insert(purchase2);
		
		ks.fireAllRules();
		
		ks.delete(fh);
		
		ks.fireAllRules();
	}
	
	@Test
	public void noDiscountNotification() {
		KnowledgeRuntimeLogger logger =
				KnowledgeRuntimeLoggerFactory.newFileLogger((KnowledgeRuntimeEventManager) ks, "/tmp/shopping_model");
		
		Customer customer1 = new Customer("Test", 10);
		ks.insert(customer1);
		
		Product product1 = new Product("Laser", 600);
		ks.insert(product1);
		
		Purchase purchase1 = new Purchase(customer1, product1);
		FactHandle fh = ks.insert(purchase1);
		
		ks.fireAllRules();
		
		ks.delete(fh);
		
		ks.fireAllRules();
	}
}

// -------------------------------------

	/**
	 * Utility method to assert on discounts.
	 */
	@SuppressWarnings("unchecked")
	private static Collection<Discount> getDiscounts(KieSession kSession) {
		return (Collection<Discount>) kSession.getObjects(new ObjectFilter() {
			@Override
			public boolean accept(Object o) {
				return o instanceof Discount;
			}
		});
	}

// -----------------------------------

kSession.addEventListener(new RuleRuntimeEventListener() {				
				@Override
				public void objectUpdated(ObjectUpdatedEvent arg0) {					
					
				}
				
				@Override
				public void objectInserted(ObjectInsertedEvent arg0) {
					
					
				}
				
				@Override
				public void objectDeleted(ObjectDeletedEvent arg0) {
					Object obj = arg0.getOldObject();
					if(obj instanceof Discount) {
						Discount discount = (Discount) obj;
						System.out.printf("Discount was removed from %1$s.\n",discount.getCustomer());
					}										
				}
});