Skip to content

Instantly share code, notes, and snippets.

@dacr
Last active June 24, 2023 16:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dacr/fd48009178f3874b7dd89d6d71c7c066 to your computer and use it in GitHub Desktop.
Save dacr/fd48009178f3874b7dd89d6d71c7c066 to your computer and use it in GitHub Desktop.
Basic drools usage examples through unit test cases. / published by https://github.com/dacr/code-examples-manager #e23fa6f0-a1d4-4333-81ae-26ebe7512174/753e5e77204771940870555cfc8ae289c2020259
// summary : Basic drools usage examples through unit test cases.
// keywords : scala, drools, mvel, scalatest, ai, @testable
// publish : gist
// authors : David Crosson
// license : Apache NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2)
// id : e23fa6f0-a1d4-4333-81ae-26ebe7512174
// execution : scala ammonite script (http://ammonite.io/) - run as follow 'amm scriptname.sc'
// created-on : 2018-09-12T21:11:39+02:00
// managed-by : https://github.com/dacr/code-examples-manager
// run-with : scala-cli $file
// ---------------------
//> using scala "3.3.0"
//> using dep "fr.janalyse::drools-scripting:1.1.0"
//> using dep "org.scalatest::scalatest:3.2.16"
// ---------------------
import fr.janalyse.droolscripting._, org.scalatest._, flatspec._, matchers._, OptionValues._
import scala.jdk.CollectionConverters._
import DroolsEngineConfig._
class SimpleTest extends AnyFlatSpec with should.Matchers {
override val suiteName = "SimpleTest"
"Drools" should "say hello" in {
val drl =
"""package testdrools
|rule "hello" when
|then
| insert("HELLO WORLD");
|end
|""".stripMargin
val engine = DroolsEngine(drl)
engine.fireAllRules()
engine.getObjects.headOption.value shouldBe "HELLO WORLD"
engine.dispose()
}
it should "support logging within defined kb" in {
val drl =
"""package testdrools
|global org.slf4j.Logger logger
|rule "hello" when
|then
| logger.info("Hello");
| insert("HELLO WORLD");
|end
|""".stripMargin
val engine = DroolsEngine(drl)
engine.fireAllRules()
engine.getObjects.headOption.value shouldBe "HELLO WORLD"
engine.dispose()
}
it should "be possible to get objects" in {
val drl=
"""package test
|declare Top
| age:int
|end
|
|rule "init"
|when
|then
| insert(new Top(42));
| insert(new Top(24));
|end
|""".stripMargin
val engine = DroolsEngine(drl)
engine.fireAllRules()
engine.getObjects.size shouldBe 2
}
it should "be possible to get object by their types" in {
val drl=
"""package test
|declare Top
| age:int
|end
|
|rule "init"
|when
|then
| insert(new Top(42));
| insert(new Top(24));
|end
|""".stripMargin
val engine = DroolsEngine(drl)
engine.fireAllRules()
engine.getModelInstances("test.Top").size shouldBe 2
}
it should "be possible to get object by their super types" in {
val drl=
"""package test
|declare Top
| age:int
|end
|
|declare Bottom extends Top end
|
|rule "init"
|when
|then
| insert(new Bottom(42));
| insert(new Bottom(24));
|end
|""".stripMargin
val engine = DroolsEngine(drl)
engine.fireAllRules()
engine.getModelInstances("test.Top").size shouldBe 2
}
it should "be possible to get java raw types from working memory" in {
val drl=
"""package test
|rule "init" when then
| insert("Cool Raoul");
|end
|""".stripMargin
val engine = DroolsEngine(drl)
engine.fireAllRules()
val strings = engine.getModelInstances("java.lang.String")
strings should have size 1
strings.headOption.value shouldBe "Cool Raoul"
}
it should "be possible to get easily java Strings from working memory" in {
val drl=
"""package test
|rule "init" when then
| insert("Cool Raoul");
|end
|""".stripMargin
val engine = DroolsEngine(drl)
engine.fireAllRules()
engine.strings shouldBe List("Cool Raoul")
}
it should "react on an inserted message" in {
val drl =
"""package testdrools
|rule "hello message"
|when
| $msg:String()
|then
| insert(1);
|end
|
|""".stripMargin
val engine = DroolsEngine(drl)
engine.insert("some message")
engine.fireAllRules()
engine.getObjects.size shouldBe 2
engine.getModelInstances("java.lang.Integer").headOption.value shouldBe 1
engine.dispose()
}
it should "allow us to access internal model definitions" in {
val drl =
"""package testdrools
|
|global org.slf4j.Logger logger
|
|declare Message
| content:String
|end
|
|rule "init"
|when
|then
| insert(new Message("Hello World"));
|end
|
|""".stripMargin
val engine = DroolsEngine(drl)
engine.fireAllRules()
val instances = engine.getModelInstances("testdrools.Message")
instances should have size 1
engine.getModelInstanceAttribute(instances.head, "content").value shouldBe "Hello World"
engine.getModelFirstInstanceAttribute("testdrools.Message", "content").value shouldBe "Hello World"
}
it should "be possible collect things and loop over found occurences" in {
val drl =
"""package testdrools
|
|global org.slf4j.Logger logger
|import java.util.LinkedList
|
|declare Message
| content:String
|end
|
|
|declare AllMessages
| all:String
|end
|
|
|rule "init"
|when
|then
| insert(new Message("msg1"));
| insert(new Message("msg2"));
| insert(new Message("msg3"));
|end
|
|
|rule "collect"
|when
| $messages: LinkedList(size>0) from collect( Message() )
|then
| StringBuffer sb=new StringBuffer();
| for(Object msg: $messages) sb.append(((Message)msg).getContent()+"-");
| insert(new AllMessages(sb.toString()));
|end
|
|""".stripMargin
info("Drools collect objects into List without supporting generics.")
info("In this example $messages is a LinkedList of Objects.")
info("In order to iterate in the then clause you'll to iterate through objects and use explicit cast.")
info("WARNING : it is forbidden to access the field ")
val engine = DroolsEngine(drl)
engine.fireAllRules()
val instances = engine.getModelInstances("testdrools.AllMessages")
instances should have size 1
engine
.getModelFirstInstanceAttribute("testdrools.AllMessages", "all")
.value
.toString
.split("[-]").toList.sorted.mkString("-") shouldBe "msg1-msg2-msg3"
}
it should "be possible to update logically inserted fact" in {
val drl =
"""package testdrools
|
|global org.slf4j.Logger logger
|
|declare That
| value:int
|end
|
|declare Something
| content:String
|end
|
|declare Flag
|end
|
|rule "init"
|when
|then
| insert(new That(42));
|end
|
|rule "found something"
|when
| That($value:value)
|then
| insertLogical(new Something("found-"+$value));
| insert(new Flag());
|end
|
|rule "update found"
|no-loop
|when
| String(this == "update")
| $that:That()
|then
| update($that);
|end
|""".stripMargin
val engine = DroolsEngine(drl,configWithIdentity)
engine.fireAllRules()
engine.getModelInstances("testdrools.Something") should have size 1
engine.getModelInstances("testdrools.Flag") should have size 1
engine.getModelFirstInstanceAttribute("testdrools.Something", "content") shouldBe Some("found-42")
engine.insert("update")
engine.fireAllRules()
engine.getModelInstances("testdrools.Something") should have size 1
engine.getModelInstances("testdrools.Flag") should have size 2
engine.getModelFirstInstanceAttribute("testdrools.Something", "content") shouldBe Some("found-42")
info("As Something is logically inserted, it is removed on updateThat and then reinserted.")
}
}
(new SimpleTest).execute()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment