BAEL-5143 (#11273)
* BAEL-5143 * Modified as per PR comments * The List<> type for session data is changed to a more generic Collection<> * Version upgrade Co-authored-by: 0swald <andrey.bichkevskiy@gmail.com>
This commit is contained in:
parent
4dfe21a3dc
commit
025afb1f7d
35
rule-engines/evrete/pom.xml
Normal file
35
rule-engines/evrete/pom.xml
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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.baeldung.evrete</groupId>
|
||||
<artifactId>evrete</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>evrete</name>
|
||||
|
||||
<properties>
|
||||
<evrete.version>2.1.04</evrete.version>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>rule-engines</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- Core library -->
|
||||
<dependency>
|
||||
<groupId>org.evrete</groupId>
|
||||
<artifactId>evrete-core</artifactId>
|
||||
<version>${evrete.version}</version>
|
||||
</dependency>
|
||||
<!-- Annotated Java classes -->
|
||||
<dependency>
|
||||
<groupId>org.evrete</groupId>
|
||||
<artifactId>evrete-dsl-java</artifactId>
|
||||
<version>${evrete.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,47 @@
|
||||
package com.baeldung.evrete.introduction;
|
||||
|
||||
import com.baeldung.evrete.introduction.model.Customer;
|
||||
import com.baeldung.evrete.introduction.model.Invoice;
|
||||
import org.evrete.KnowledgeService;
|
||||
import org.evrete.api.Knowledge;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
public class IntroductionAJR {
|
||||
public static void main(String[] args) throws IOException {
|
||||
ClassLoader classLoader = IntroductionAJR.class.getClassLoader();
|
||||
KnowledgeService service = new KnowledgeService();
|
||||
URL rulesetUrl = classLoader.getResource("rules/SalesRuleset.java");
|
||||
Knowledge knowledge = service.newKnowledge(
|
||||
"JAVA-SOURCE",
|
||||
rulesetUrl
|
||||
);
|
||||
|
||||
List<Customer> customers = Arrays.asList(
|
||||
new Customer("Customer A"),
|
||||
new Customer("Customer B"),
|
||||
new Customer("Customer C")
|
||||
);
|
||||
|
||||
Random random = new Random();
|
||||
Collection<Object> sessionData = new LinkedList<>(customers);
|
||||
for (int i = 0; i < 100_000; i++) {
|
||||
Customer randomCustomer = customers.get(random.nextInt(customers.size()));
|
||||
Invoice invoice = new Invoice(randomCustomer, 100 * random.nextDouble());
|
||||
sessionData.add(invoice);
|
||||
}
|
||||
|
||||
knowledge
|
||||
.newStatelessSession()
|
||||
.insert(sessionData)
|
||||
.fire();
|
||||
|
||||
for (Customer c : customers) {
|
||||
System.out.printf("%s:\t$%,.2f%n", c.getName(), c.getTotal());
|
||||
}
|
||||
|
||||
service.shutdown();
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.baeldung.evrete.introduction;
|
||||
|
||||
import org.evrete.KnowledgeService;
|
||||
import org.evrete.api.Knowledge;
|
||||
import com.baeldung.evrete.introduction.model.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class IntroductionInline {
|
||||
public static void main(String[] args) {
|
||||
KnowledgeService service = new KnowledgeService();
|
||||
Knowledge knowledge = service
|
||||
.newKnowledge()
|
||||
.newRule("Clear total sales")
|
||||
.forEach("$c", Customer.class)
|
||||
.execute(ctx -> {
|
||||
Customer c = ctx.get("$c");
|
||||
c.setTotal(0.0);
|
||||
})
|
||||
.newRule("Compute totals")
|
||||
.forEach(
|
||||
"$c", Customer.class,
|
||||
"$i", Invoice.class
|
||||
)
|
||||
.where("$i.customer == $c")
|
||||
.execute(ctx -> {
|
||||
Customer c = ctx.get("$c");
|
||||
Invoice i = ctx.get("$i");
|
||||
c.addToTotal(i.getAmount());
|
||||
});
|
||||
|
||||
|
||||
List<Customer> customers = Arrays.asList(
|
||||
new Customer("Customer A"),
|
||||
new Customer("Customer B"),
|
||||
new Customer("Customer C")
|
||||
);
|
||||
|
||||
Random random = new Random();
|
||||
Collection<Object> sessionData = new LinkedList<>(customers);
|
||||
for (int i = 0; i < 100_000; i++) {
|
||||
Customer randomCustomer = customers.get(random.nextInt(customers.size()));
|
||||
Invoice invoice = new Invoice(randomCustomer, 100 * random.nextDouble());
|
||||
sessionData.add(invoice);
|
||||
}
|
||||
|
||||
knowledge
|
||||
.newStatelessSession()
|
||||
.insert(sessionData)
|
||||
.fire();
|
||||
|
||||
for (Customer c : customers) {
|
||||
System.out.printf("%s:\t$%,.2f%n", c.getName(), c.getTotal());
|
||||
}
|
||||
|
||||
service.shutdown();
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.baeldung.evrete.introduction.model;
|
||||
|
||||
public class Customer {
|
||||
private double total = 0.0;
|
||||
private final String name;
|
||||
|
||||
public Customer(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void addToTotal(double amount) {
|
||||
this.total += amount;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public double getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(double total) {
|
||||
this.total = total;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.baeldung.evrete.introduction.model;
|
||||
|
||||
public class Invoice {
|
||||
private final Customer customer;
|
||||
private final double amount;
|
||||
|
||||
public Invoice(Customer customer, double amount) {
|
||||
this.customer = customer;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public Customer getCustomer() {
|
||||
return customer;
|
||||
}
|
||||
|
||||
public double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
}
|
13
rule-engines/evrete/src/main/resources/logback.xml
Normal file
13
rule-engines/evrete/src/main/resources/logback.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
@ -0,0 +1,20 @@
|
||||
package org.abc.author1;
|
||||
|
||||
import com.baeldung.evrete.introduction.model.Customer;
|
||||
import com.baeldung.evrete.introduction.model.Invoice;
|
||||
import org.evrete.dsl.annotation.Rule;
|
||||
import org.evrete.dsl.annotation.Where;
|
||||
|
||||
public class SalesRuleset {
|
||||
|
||||
@Rule
|
||||
public void rule1(Customer $c) {
|
||||
$c.setTotal(0.0);
|
||||
}
|
||||
|
||||
@Rule
|
||||
@Where("$i.customer == $c")
|
||||
public void rule2(Customer $c, Invoice $i) {
|
||||
$c.addToTotal($i.getAmount());
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package com.baeldung.evrete.introduction;
|
||||
|
||||
import com.baeldung.evrete.introduction.model.Customer;
|
||||
import com.baeldung.evrete.introduction.model.Invoice;
|
||||
import org.evrete.KnowledgeService;
|
||||
import org.evrete.api.Knowledge;
|
||||
import org.evrete.api.RuleSession;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
class IntroductionAJRUnitTest {
|
||||
private static KnowledgeService service;
|
||||
|
||||
@BeforeAll
|
||||
static void setUpClass() {
|
||||
service = new KnowledgeService();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void shutDownClass() {
|
||||
service.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test makes sure that each customer's actual total sales is equal to the amount
|
||||
* computed by the rule engine
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"true", "false"})
|
||||
void sessionTotalsTest(String type) throws IOException {
|
||||
boolean stateful = Boolean.parseBoolean(type);
|
||||
ClassLoader classLoader = IntroductionAJR.class.getClassLoader();
|
||||
KnowledgeService service = new KnowledgeService();
|
||||
Knowledge knowledge = service
|
||||
.newKnowledge(
|
||||
"JAVA-SOURCE",
|
||||
classLoader.getResource("rules/SalesRuleset.java")
|
||||
);
|
||||
|
||||
|
||||
List<Customer> customers = Arrays.asList(
|
||||
new Customer("Customer A"),
|
||||
new Customer("Customer B"),
|
||||
new Customer("Customer C")
|
||||
);
|
||||
Collection<Object> sessionData = new LinkedList<>(customers);
|
||||
|
||||
HashMap<Customer, Double> actualTotals = new HashMap<>();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 1_000; i++) {
|
||||
Customer randomCustomer = customers.get(random.nextInt(customers.size()));
|
||||
Invoice invoice = new Invoice(randomCustomer, random.nextInt(100));
|
||||
sessionData.add(invoice);
|
||||
|
||||
Double d = actualTotals.get(randomCustomer);
|
||||
if(d == null) {
|
||||
d = 0.0;
|
||||
}
|
||||
d = d + invoice.getAmount();
|
||||
actualTotals.put(randomCustomer, d);
|
||||
}
|
||||
|
||||
RuleSession<?> session = stateful ? knowledge.newStatefulSession() : knowledge.newStatelessSession();
|
||||
session
|
||||
.insert(sessionData)
|
||||
.fire();
|
||||
|
||||
for(Customer c : customers) {
|
||||
double d1 = c.getTotal();
|
||||
double d2 = actualTotals.get(c);
|
||||
assert d1 == d2;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package com.baeldung.evrete.introduction;
|
||||
|
||||
import com.baeldung.evrete.introduction.model.Customer;
|
||||
import com.baeldung.evrete.introduction.model.Invoice;
|
||||
import org.evrete.KnowledgeService;
|
||||
import org.evrete.api.Knowledge;
|
||||
import org.evrete.api.RuleSession;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class IntroductionInlineUnitTest {
|
||||
private static KnowledgeService service;
|
||||
|
||||
@BeforeAll
|
||||
static void setUpClass() {
|
||||
service = new KnowledgeService();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void shutDownClass() {
|
||||
service.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test makes sure that each customer's actual total sales is equal to the amount
|
||||
* computed by the rule engine
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"true", "false"})
|
||||
void sessionTotalsTest(String type) {
|
||||
boolean stateful = Boolean.parseBoolean(type);
|
||||
Knowledge knowledge = service
|
||||
.newKnowledge()
|
||||
.newRule("Clear customer's total sales")
|
||||
.forEach("$c", Customer.class)
|
||||
.execute(ctx -> {
|
||||
Customer c = ctx.get("$c");
|
||||
c.setTotal(0.0);
|
||||
})
|
||||
.newRule("Compute totals")
|
||||
.forEach(
|
||||
"$c", Customer.class,
|
||||
"$i", Invoice.class
|
||||
)
|
||||
.where("$i.customer == $c")
|
||||
.execute(ctx -> {
|
||||
Customer c = ctx.get("$c");
|
||||
Invoice i = ctx.get("$i");
|
||||
c.addToTotal(i.getAmount());
|
||||
});
|
||||
|
||||
|
||||
List<Customer> customers = Arrays.asList(
|
||||
new Customer("Customer A"),
|
||||
new Customer("Customer B"),
|
||||
new Customer("Customer C")
|
||||
);
|
||||
Collection<Object> sessionData = new LinkedList<>(customers);
|
||||
|
||||
HashMap<Customer, Double> actualTotals = new HashMap<>();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 1_000; i++) {
|
||||
Customer randomCustomer = customers.get(random.nextInt(customers.size()));
|
||||
Invoice invoice = new Invoice(randomCustomer, random.nextInt(100));
|
||||
sessionData.add(invoice);
|
||||
|
||||
Double d = actualTotals.get(randomCustomer);
|
||||
if(d == null) {
|
||||
d = 0.0;
|
||||
}
|
||||
d = d + invoice.getAmount();
|
||||
actualTotals.put(randomCustomer, d);
|
||||
}
|
||||
|
||||
RuleSession<?> session = stateful ? knowledge.newStatefulSession() : knowledge.newStatelessSession();
|
||||
session
|
||||
.insert(sessionData)
|
||||
.fire();
|
||||
|
||||
for(Customer c : customers) {
|
||||
double d1 = c.getTotal();
|
||||
double d2 = actualTotals.get(c);
|
||||
assert d1 == d2;
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@
|
||||
|
||||
<modules>
|
||||
<module>easy-rules</module>
|
||||
<module>evrete</module>
|
||||
<module>openl-tablets</module>
|
||||
<module>rulebook</module>
|
||||
<!-- <module>jess</module> --> <!-- requires dependencies which are not publicly available -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user