Working with Accumulate


This example follows on from Drools5.6 Basic Example

This is a quick example that shows a very simple use of the accumulate statement.

Problem

Write a rule that accumulates and stores the number of iPhone and Android devices owned by students, so that further rules can analyse and act on that information.

The Code

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.skills421.examples.drools</groupId>
  <artifactId>DroolsExamples</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <properties>
		<drools-version>5.6.0.Final</drools-version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.drools</groupId>
			<artifactId>drools-core</artifactId>
			<version>${drools-version}</version>
		</dependency>
		<dependency>
			<groupId>org.drools</groupId>
			<artifactId>knowledge-api</artifactId>
			<version>${drools-version}</version>
		</dependency>
		<dependency>
			<groupId>org.drools</groupId>
			<artifactId>drools-compiler</artifactId>
			<version>${drools-version}</version>
		</dependency>
		<dependency>
			<groupId>org.drools</groupId>
			<artifactId>drools-decisiontables</artifactId>
			<version>${drools-version}</version>
		</dependency>
		
		<!-- JUnit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
		</dependency>

	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.0</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

RuleRunner.java

package com.skills421.examples.drools.controller;
 
import java.util.Collection;
 
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.definition.KnowledgePackage;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;
 
public class RuleRunner 
{
    public RuleRunner()
    {
    }
 
    public void runRules(String[] rules, Object[] facts)
    {
 
        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
 
        for (int i = 0; i < rules.length; i++)
        {
            String ruleFile = rules[i];
            System.out.println("Loading file: " + ruleFile);
            kbuilder.add(ResourceFactory.newClassPathResource(ruleFile, RuleRunner.class), ResourceType.DRL);
        }
 
        Collection<KnowledgePackage> pkgs = kbuilder.getKnowledgePackages();
        kbase.addKnowledgePackages(pkgs);
        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
 
        for (int i = 0; i < facts.length; i++)
        {
            Object fact = facts[i];
            System.out.println("Inserting fact: " + fact);
            ksession.insert(fact);
        }
 
        ksession.fireAllRules();
    }
}

SimpleFact

package com.skills421.examples.drools.helper;

public class SimpleFact
{
	private String name;
	private Object value;

	public SimpleFact(String name, Object value)
	{
		super();
		this.name = name;
		this.value = value;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public Object getValue()
	{
		return value;
	}

	public void setValue(Object value)
	{
		this.value = value;
	}
	
	public int intValue()
	{
		if(value instanceof Number)
		{
			return ((Number) value).intValue();
		}
		
		return -1;
	}

	@Override
	public String toString()
	{
		return String.format("SimpleFact [name=%s, value=%s]", name, value);
	}

}

AccumulateTest.java (JUnit)

package com.examples.drools.examples;

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.List;

import org.junit.Test;

import com.skills421.examples.drools.controller.RuleRunner;
import com.skills421.examples.drools.model.Student;

public class AccumulateTest
{

	@Test
	public void test()
	{
		Student[] students = new Student[]
		{
			new Student("Jon Doe", 1, 0),
			new Student("Jane Doe", 0, 1),
			new Student("Mark Smith", 2, 0),
			new Student("Alice Jenkins", 1, 2)
		};
		
		RuleRunner runner = new RuleRunner();
		
		String[] rules = new String[] { "examples/accumulate.drl" };
		
		runner.runRules(rules, students);
	}

}

accumulate.drl

package examples;

import com.skills421.examples.drools.model.Student;
import com.skills421.examples.drools.helper.SimpleFact;

dialect "mvel"

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

rule "Print all iPhone Students"
	when
		$student:Student(iPhone>0)
	then
		System.out.println($student);
end

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

rule "generate list of androids and iphones owned by students"
	when
		$iPhones : Number ( ) from accumulate ( Student ( $iPhone : iPhone ), sum ( $iPhone ) )
		$androids : Number ( ) from accumulate ( Student ( $android : android ), sum ( $android ) )
	then
		System.out.println("iPhones: "+$iPhones);
		System.out.println("Androids: "+$androids);
		
		insert(new SimpleFact("iPhones",$iPhones));
		insert(new SimpleFact("androids",$androids));
end

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

rule "more iPhones"
	when
		SimpleFact(name=="iPhones",$iPhones:intValue)
		SimpleFact(name=="androids",$androids:intValue < $iPhones)
	then
		System.out.println("more iPhones - "+$iPhones+" : "+$androids);
end

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

rule "more androids"
	when
		SimpleFact(name=="iPhones",$iPhones:intValue)
		SimpleFact(name=="androids",$androids:intValue > $iPhones)
	then
		System.out.println("more androids - "+$androids+" : "+$iPhones);
end

Output

Loading file: examples/accumulate.drl
Inserting fact: Student [name=Jon Doe, iPhone=1, android=0]
Inserting fact: Student [name=Jane Doe, iPhone=0, android=1]
Inserting fact: Student [name=Mark Smith, iPhone=2, android=0]
Inserting fact: Student [name=Alice Jenkins, iPhone=1, android=2]
Student [name=Alice Jenkins, iPhone=1, android=2]
Student [name=Mark Smith, iPhone=2, android=0]
Student [name=Jon Doe, iPhone=1, android=0]
iPhones: 4.0
Androids: 3.0
more iPhones - 4 : 3
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s