Last active
June 24, 2023 16:26
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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