Thursday, April 26, 2012

sbt scala drools expert system skeleton project

Just released a simple scala drools project skeleton. The Knowledge base is used to evaluate drools-mvel / scala interaction.
The Knowledge Base :
package dummy;

dialect "mvel"

import java.util.LinkedList;

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

rule "who is young"
  when
    Someone($name:name, age < 30)
  then
    System.out.println($name+" is very young")
end

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

rule "people cars"
  when
    $someone:Someone($name:name)
    $car : Car(someone == $someone)
  then
    System.out.println("One of "+$name+"'s car is "+$car.color.name+" "+$car.model)
end

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

rule "who own at least one red car"
  when
    $someone:Someone($name:name)
    exists Car(someone == $someone, color == Color.red)
  then
    System.out.println($name+" has at least one red car")
end

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

rule "who doesn't have a home"
  when
    $someone:Someone($name:name)
    not Home(someone == $someone)
  then
    insert(new InformationRequest($someone, $name+"'s home is unknown"))
end

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

rule "who doesn't have an address"
  when
    $someone:Someone($name:name)
    Home(someone == $someone, !address.isDefined)
  then
    insert(new InformationRequest($someone, $name+" address is unknown"))
end

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

rule "process information requests"
  when
    InformationRequest($who:someone, $what:message)
  then
    System.out.println("INFORMATION REQUESTED FOR "+$who+" : "+$what)
end

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

rule "who owns more than 1 car"
  when
    $someone : Someone($name:name)
    $cars    : LinkedList( size>1 ) from collect(Car(someone == $someone))
  then
    System.out.println($name+" has "+$cars.size+" cars")  
end

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

And the startup code :
package dummy

// ----------------------------------------------------------------
// DOMAIN MODEL

case class Someone(name:String, age:Int)

case class Car(someone:Someone, model:String, year:Int, color:Color)

case class Color(name:String)

object Color {
  val red = Color("red")
  val blue = Color("blue")
  val green = Color("green")
  val black = Color("black")
}

case class Address(street:String, town:String, country:String)

case class Home(someone:Someone, address:Option[Address]) 

case class InformationRequest(someone:Someone, message:String)




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


import java.io.FileInputStream
import java.io.InputStreamReader
import org.drools.RuleBaseFactory
import org.drools.audit.WorkingMemoryFileLogger
import org.drools.compiler.PackageBuilder


object Dummy {

  def main(args: Array[String]) {
    System.setProperty("drools.dialect.mvel.strict", "false")
    
    val rulesfilename = "src/main/resources/KBExpertise.drl"
    val source = new InputStreamReader(new FileInputStream(rulesfilename))
    
    val builder = new PackageBuilder()
    builder.addPackageFromDrl(source)
    if (builder.hasErrors()) {
      System.out.println(builder.getErrors().toString())
      throw new RuntimeException("Unable to compile " + rulesfilename + ".")
    }

    val pkg = builder.getPackage()
    val ruleBase = RuleBaseFactory.newRuleBase()
    ruleBase.addPackage(pkg)

    val session = ruleBase.newStatefulSession()
    //session.addEventListener(new org.drools.event.DebugAgendaEventListener())
    //session.addEventListener(new org.drools.event.DebugWorkingMemoryEventListener())
    
    // setup the audit logging
    val logger:WorkingMemoryFileLogger = new WorkingMemoryFileLogger(session)
    logger.setFileName("drools")
    logger.writeToDisk()

    val martine = Someone(name="Martine", age=30)
    val martin  = Someone(name="Martin", age=40)
    val jack    = Someone(name="Jack", age=12)
    val martineCar = Car(martine, "Ford", 2010, Color.blue)
    val martinCar  = Car(martin, "GM", 2010, Color.black)
    val martinCar2 = Car(martin, "Ferrari", 2012, Color.red)
    val martinCar3 = Car(martin, "Porshe", 2011, Color.red)
    
    val martinHome = Home(martin, None)
    val jackHome   = Home(jack, Some(Address("221B Baker Street", "London", "England")))
    
    List(martine, martin, jack, 
        martineCar, martinCar, martinCar2, martinCar3,
        martinHome, jackHome
    ).foreach(session.insert(_)) 

    session.fireAllRules()

    session.dispose()
  }
}
To finish, the build.sbt file, to build and run the project :
import AssemblyKeys._

seq(assemblySettings: _*)

name := "ScalaDroolsDummyProject"

version := "0.0.1"

scalaVersion := "2.9.2"

mainClass in assembly := Some("dummy.Dummy")

jarName in assembly := "dummy.jar"



libraryDependencies += "org.drools" % "drools-compiler" % "5.3.1.Final"

libraryDependencies += "org.drools" % "drools-core" % "5.3.1.Final"

libraryDependencies += "org.drools" % "drools-jsr94"  % "5.3.1.Final"

libraryDependencies += "org.drools" % "drools-decisiontables"  % "5.3.1.Final"

libraryDependencies += "org.drools" % "knowledge-api"  % "5.3.1.Final"



libraryDependencies += "com.thoughtworks.xstream" % "xstream" % "1.4.2"
            


libraryDependencies += "org.scalatest" %% "scalatest" % "1.7.2" % "test"

libraryDependencies += "junit" % "junit" % "4.10" % "test"

resolvers += "JBoss third party releases repository" at "https://repository.jboss.org/nexus/content/repositories/thirdparty-releases"

Test it by your self :
$ sbt run
INFORMATION REQUESTED FOR Someone(Martin,40) : Martin address is unknown
One of Martin's car is red Porshe
Martin has 3 cars
Martin has at least one red car
One of Martin's car is red Ferrari
One of Martin's car is black GM
One of Martine's car is blue Ford
Jack is very young
INFORMATION REQUESTED FOR Someone(Martine,30) : Martine's home is unknown
[success] Total time: 6 s, completed 27 avr. 2012 22:35:37
And for those who don't know about SBT or GIT :
  • Download SBT jar file
    • You'll get a java jar executable named sbt-launch.jar
  • Download the scala drools skeleton zip archive
    • You'll get a file which will look like : "dacr-scala-drools-dummy-project-6b43143.zip"
    • unzip the content and rename the unzipped directory to scala-drools-dummy-project
test@localhost /tmp/test $ unzip dacr-scala-drools-dummy-project-6b43143.zip 
Archive:  dacr-scala-drools-dummy-project-6b43143.zip
6b43143f369bda03361ca2c5f2376d51ba7d5524
   creating: dacr-scala-drools-dummy-project-6b43143/
  inflating: dacr-scala-drools-dummy-project-6b43143/.gitignore  
  inflating: dacr-scala-drools-dummy-project-6b43143/README  
 extracting: dacr-scala-drools-dummy-project-6b43143/RELEASE-NOTES  
  inflating: dacr-scala-drools-dummy-project-6b43143/build.sbt  
  inflating: dacr-scala-drools-dummy-project-6b43143/cleanup.sh  
   creating: dacr-scala-drools-dummy-project-6b43143/project/
  inflating: dacr-scala-drools-dummy-project-6b43143/project/plugins.sbt  
   creating: dacr-scala-drools-dummy-project-6b43143/src/
   creating: dacr-scala-drools-dummy-project-6b43143/src/main/
   creating: dacr-scala-drools-dummy-project-6b43143/src/main/resources/
  inflating: dacr-scala-drools-dummy-project-6b43143/src/main/resources/KBExpertise.drl  
   creating: dacr-scala-drools-dummy-project-6b43143/src/main/scala/
   creating: dacr-scala-drools-dummy-project-6b43143/src/main/scala/dummy/
  inflating: dacr-scala-drools-dummy-project-6b43143/src/main/scala/dummy/Dummy.scala  
   creating: dacr-scala-drools-dummy-project-6b43143/src/test/
   creating: dacr-scala-drools-dummy-project-6b43143/src/test/scala/
   creating: dacr-scala-drools-dummy-project-6b43143/src/test/scala/dummy/
  inflating: dacr-scala-drools-dummy-project-6b43143/src/test/scala/dummy/DummyTest.scala  
test@localhost /tmp/test $ mv dacr-scala-drools-dummy-project-6b43143 scala-drools-dummy-project
test@localhost /tmp/test $ cd scala-drools-dummy-project
test@localhost /tmp/test/scala-drools-dummy-project $ java -jar ~/Downloads/sbt-launch.jar run
[info] Loading project definition from /tmp/test/scala-drools-dummy-project/project
[info] Set current project to ScalaDroolsDummyProject (in build file:/tmp/test/scala-drools-dummy-project/)
[info] Updating {file:/tmp/test/scala-drools-dummy-project/}default-d556eb...
[info] Resolving org.scala-lang#scala-library;2.9.2 ...
[info] Resolving org.drools#drools-compiler;5.3.1.Final ...
...
[info] Compiling 1 Scala source to /tmp/test/scala-drools-dummy-project/target/scala-2.9.2/classes...
[info] Running dummy.Dummy 
INFORMATION REQUESTED FOR Someone(Martin,40) : Martin address is unknown
One of Martin's car is red Porshe
Martin has 3 cars
Martin has at least one red car
One of Martin's car is red Ferrari
One of Martin's car is black GM
One of Martine's car is blue Ford
Jack is very young
INFORMATION REQUESTED FOR Someone(Martine,30) : Martine's home is unknown
[success] Total time: 8 s, completed 30 avr. 2012 12:59:17

1 comment:

  1. Thanks - I stumbled across your post after looking at a number of posts by others all of which are outdated.
    Yours works very nicely.

    ReplyDelete