Adding easy-rules-jexl to support Java Expression Language (JEXL)
parent
0072222390
commit
eab2e3b367
@ -0,0 +1,102 @@
|
||||
<?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>
|
||||
<parent>
|
||||
<groupId>org.jeasy</groupId>
|
||||
<artifactId>easy-rules</artifactId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>easy-rules-jexl</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Easy Rules JEXL module</name>
|
||||
<description>JEXL integration module</description>
|
||||
|
||||
<properties>
|
||||
<jexl.version>3.1</jexl.version>
|
||||
</properties>
|
||||
|
||||
<scm>
|
||||
<url>git@github.com:j-easy/easy-rules.git</url>
|
||||
<connection>scm:git:git@github.com:j-easy/easy-rules.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:j-easy/easy-rules.git</developerConnection>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<issueManagement>
|
||||
<system>GitHub</system>
|
||||
<url>https://github.com/j-easy/easy-rules/issues</url>
|
||||
</issueManagement>
|
||||
|
||||
<ciManagement>
|
||||
<system>Travis CI</system>
|
||||
<url>https://travis-ci.org/j-easy/easy-rules</url>
|
||||
</ciManagement>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>benas</id>
|
||||
<name>Mahmoud Ben Hassine</name>
|
||||
<url>http://benas.github.io</url>
|
||||
<email>mahmoud.benhassine@icloud.com</email>
|
||||
<roles>
|
||||
<role>Lead developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>MIT License</name>
|
||||
<url>http://opensource.org/licenses/mit-license.php</url>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jeasy</groupId>
|
||||
<artifactId>easy-rules-support</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>${slf4j-api.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-jexl3</artifactId>
|
||||
<version>${jexl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.stefanbirkner</groupId>
|
||||
<artifactId>system-rules</artifactId>
|
||||
<version>${system-rules.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.mycila</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<header>${project.parent.basedir}/licence-header-template.txt</header>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2020, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jeasy.rules.jexl;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.jexl3.JexlEngine;
|
||||
import org.apache.commons.jexl3.JexlException;
|
||||
import org.apache.commons.jexl3.JexlScript;
|
||||
import org.apache.commons.jexl3.MapContext;
|
||||
import org.jeasy.rules.api.Action;
|
||||
import org.jeasy.rules.api.Facts;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class JexlAction implements Action {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JexlAction.class);
|
||||
|
||||
private final JexlScript compiledScript;
|
||||
private final String expression;
|
||||
|
||||
public JexlAction(String expression) {
|
||||
this.expression = Objects.requireNonNull(expression, "expression cannot be null");
|
||||
this.compiledScript = JexlRule.DEFAULT_JEXL.createScript(expression);
|
||||
}
|
||||
|
||||
public JexlAction(String expression, JexlEngine jexl) {
|
||||
this.expression = Objects.requireNonNull(expression, "expression cannot be null");
|
||||
Objects.requireNonNull(jexl, "jexl cannot be null");
|
||||
this.compiledScript = jexl.createScript(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Facts facts) throws Exception {
|
||||
Objects.requireNonNull(facts, "facts cannot be null");
|
||||
MapContext ctx = new MapContext(facts.asMap());
|
||||
try {
|
||||
compiledScript.execute(ctx);
|
||||
} catch (JexlException e) {
|
||||
LOGGER.error("Unable to evaluate expression: '" + expression + "' on facts: " + facts, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2020, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jeasy.rules.jexl;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.jexl3.JexlEngine;
|
||||
import org.apache.commons.jexl3.JexlScript;
|
||||
import org.apache.commons.jexl3.MapContext;
|
||||
import org.jeasy.rules.api.Condition;
|
||||
import org.jeasy.rules.api.Facts;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class JexlCondition implements Condition {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JexlCondition.class);
|
||||
|
||||
private final JexlScript compiledScript;
|
||||
private final String expression;
|
||||
|
||||
public JexlCondition(String expression) {
|
||||
this.expression = Objects.requireNonNull(expression, "expression cannot be null");
|
||||
this.compiledScript = JexlRule.DEFAULT_JEXL.createScript(expression);
|
||||
}
|
||||
|
||||
public JexlCondition(String expression, JexlEngine jexl) {
|
||||
this.expression = Objects.requireNonNull(expression, "expression cannot be null");
|
||||
Objects.requireNonNull(jexl, "jexl cannot be null");
|
||||
this.compiledScript = jexl.createScript(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(Facts facts) {
|
||||
Objects.requireNonNull(facts, "facts cannot be null");
|
||||
MapContext ctx = new MapContext(facts.asMap());
|
||||
try {
|
||||
return (Boolean) compiledScript.execute(ctx);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Unable to evaluate expression: '" + expression + "' on facts: " + facts, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2020, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jeasy.rules.jexl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.jexl3.JexlBuilder;
|
||||
import org.apache.commons.jexl3.JexlEngine;
|
||||
import org.jeasy.rules.api.Action;
|
||||
import org.jeasy.rules.api.Condition;
|
||||
import org.jeasy.rules.api.Facts;
|
||||
import org.jeasy.rules.api.Rule;
|
||||
import org.jeasy.rules.core.BasicRule;
|
||||
|
||||
public class JexlRule extends BasicRule {
|
||||
|
||||
static final JexlEngine DEFAULT_JEXL = new JexlBuilder().create();
|
||||
|
||||
private Condition condition = Condition.FALSE;
|
||||
private final List<Action> actions = new ArrayList<>();
|
||||
private final JexlEngine jexl;
|
||||
|
||||
public JexlRule() {
|
||||
this(DEFAULT_JEXL);
|
||||
}
|
||||
|
||||
public JexlRule(JexlEngine jexl) {
|
||||
super(Rule.DEFAULT_NAME, Rule.DEFAULT_DESCRIPTION, Rule.DEFAULT_PRIORITY);
|
||||
this.jexl = Objects.requireNonNull(jexl, "jexl cannot be null");
|
||||
}
|
||||
|
||||
public JexlRule name(String name) {
|
||||
this.name = Objects.requireNonNull(name, "name cannot be null");
|
||||
return this;
|
||||
}
|
||||
|
||||
public JexlRule description(String description) {
|
||||
this.description = Objects.requireNonNull(description, "description cannot be null");
|
||||
return this;
|
||||
}
|
||||
|
||||
public JexlRule priority(int priority) {
|
||||
this.priority = priority;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JexlRule when(String condition) {
|
||||
Objects.requireNonNull(condition, "condition cannot be null");
|
||||
return when(condition, jexl);
|
||||
}
|
||||
|
||||
public JexlRule when(String condition, JexlEngine jexl) {
|
||||
Objects.requireNonNull(condition, "condition cannot be null");
|
||||
Objects.requireNonNull(jexl, "jexl cannot be null");
|
||||
this.condition = new JexlCondition(condition, jexl);
|
||||
return this;
|
||||
}
|
||||
|
||||
public JexlRule then(String action) {
|
||||
Objects.requireNonNull(action, "action cannot be null");
|
||||
return then(action, jexl);
|
||||
}
|
||||
|
||||
public JexlRule then(String action, JexlEngine jexl) {
|
||||
Objects.requireNonNull(action, "action cannot be null");
|
||||
Objects.requireNonNull(jexl, "jexl cannot be null");
|
||||
this.actions.add(new JexlAction(action, jexl));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate(Facts facts) {
|
||||
Objects.requireNonNull(facts, "facts cannot be null");
|
||||
return condition.evaluate(facts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Facts facts) throws Exception {
|
||||
Objects.requireNonNull(facts, "facts cannot be null");
|
||||
for (Action action : actions) {
|
||||
action.execute(facts);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2020, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jeasy.rules.jexl;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.jexl3.JexlEngine;
|
||||
import org.jeasy.rules.api.Rule;
|
||||
import org.jeasy.rules.api.Rules;
|
||||
import org.jeasy.rules.support.AbstractRuleFactory;
|
||||
import org.jeasy.rules.support.RuleDefinition;
|
||||
import org.jeasy.rules.support.RuleDefinitionReader;
|
||||
|
||||
public class JexlRuleFactory extends AbstractRuleFactory<JexlEngine> {
|
||||
|
||||
private RuleDefinitionReader reader;
|
||||
|
||||
public JexlRuleFactory(RuleDefinitionReader reader) {
|
||||
this.reader = Objects.requireNonNull(reader, "reader cannot be null");
|
||||
}
|
||||
|
||||
public Rule createRule(Reader ruleDescriptor) throws Exception {
|
||||
Objects.requireNonNull(ruleDescriptor, "ruleDescriptor cannot be null");
|
||||
return createRule(ruleDescriptor, JexlRule.DEFAULT_JEXL);
|
||||
}
|
||||
|
||||
public Rule createRule(Reader ruleDescriptor, JexlEngine jexl) throws Exception {
|
||||
Objects.requireNonNull(ruleDescriptor, "ruleDescriptor cannot be null");
|
||||
Objects.requireNonNull(jexl, "jexl cannot be null");
|
||||
List<RuleDefinition> ruleDefinitions = reader.read(ruleDescriptor);
|
||||
if (ruleDefinitions.isEmpty()) {
|
||||
throw new IllegalArgumentException("rule descriptor is empty");
|
||||
}
|
||||
return createRule(ruleDefinitions.get(0), jexl);
|
||||
}
|
||||
|
||||
public Rules createRules(Reader rulesDescriptor) throws Exception {
|
||||
Objects.requireNonNull(rulesDescriptor, "rulesDescriptor cannot be null");
|
||||
return createRules(rulesDescriptor, JexlRule.DEFAULT_JEXL);
|
||||
}
|
||||
|
||||
public Rules createRules(Reader rulesDescriptor, JexlEngine jexl) throws Exception {
|
||||
Objects.requireNonNull(rulesDescriptor, "rulesDescriptor cannot be null");
|
||||
Objects.requireNonNull(jexl, "jexl cannot be null");
|
||||
Rules rules = new Rules();
|
||||
List<RuleDefinition> ruleDefinitions = reader.read(rulesDescriptor);
|
||||
for (RuleDefinition ruleDefinition : ruleDefinitions) {
|
||||
rules.register(createRule(ruleDefinition, jexl));
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rule createSimpleRule(RuleDefinition ruleDefinition, JexlEngine jexl) {
|
||||
Objects.requireNonNull(ruleDefinition, "ruleDefinition cannot be null");
|
||||
Objects.requireNonNull(jexl, "jexl cannot be null");
|
||||
JexlRule rule = new JexlRule()
|
||||
.name(ruleDefinition.getName())
|
||||
.description(ruleDefinition.getDescription())
|
||||
.priority(ruleDefinition.getPriority())
|
||||
.when(ruleDefinition.getCondition(), jexl);
|
||||
for (String action : ruleDefinition.getActions()) {
|
||||
rule.then(action, jexl);
|
||||
}
|
||||
return rule;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2020, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* This package contains classes to support <a href="http://commons.apache.org/proper/commons-jexl/">JEXL</a>.
|
||||
*/
|
||||
package org.jeasy.rules.jexl;
|
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2020, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jeasy.rules.jexl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.jexl3.JexlBuilder;
|
||||
import org.apache.commons.jexl3.JexlEngine;
|
||||
import org.apache.commons.jexl3.JexlException;
|
||||
import org.apache.commons.jexl3.introspection.JexlSandbox;
|
||||
import org.jeasy.rules.api.Action;
|
||||
import org.jeasy.rules.api.Facts;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.contrib.java.lang.system.SystemOutRule;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
public class JexlActionTest {
|
||||
|
||||
@Rule
|
||||
public final SystemOutRule systemOutRule = new SystemOutRule().enableLog();
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Rule
|
||||
public final ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void testMVELActionExecution() throws Exception {
|
||||
// given
|
||||
Action markAsAdult = new JexlAction("person.setAdult(true);");
|
||||
Facts facts = new Facts();
|
||||
Person foo = new Person("foo", 20);
|
||||
facts.put("person", foo);
|
||||
|
||||
// when
|
||||
markAsAdult.execute(facts);
|
||||
|
||||
// then
|
||||
assertThat(foo.isAdult()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJexlFunctionExecution() throws Exception {
|
||||
// given
|
||||
Action printAction = new JexlAction("var hello = function() { System.out.println(\"Hello from JEXL!\"); }; hello();");
|
||||
Facts facts = new Facts();
|
||||
facts.put("System", System.class);
|
||||
|
||||
// when
|
||||
printAction.execute(facts);
|
||||
|
||||
// then
|
||||
assertThat(systemOutRule.getLog()).contains("Hello from JEXL!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMVELActionExecutionWithFailure() throws Exception {
|
||||
// given
|
||||
expectedException.expect(JexlException.Method.class);
|
||||
expectedException.expectMessage("org.jeasy.rules.jexl.JexlAction.<init>@1:7 unsolvable function/method 'setBlah'");
|
||||
Action action = new JexlAction("person.setBlah(true);");
|
||||
Facts facts = new Facts();
|
||||
Person foo = new Person("foo", 20);
|
||||
facts.put("person", foo);
|
||||
|
||||
// when
|
||||
action.execute(facts);
|
||||
|
||||
// then
|
||||
// excepted exception
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJexlActionWithExpressionAndFacts() throws Exception {
|
||||
// given
|
||||
JexlEngine jexl = new JexlBuilder()
|
||||
.create();
|
||||
Action printAction = new JexlAction(
|
||||
"var random = function() { System.out.println(\"Random from JEXL = \" + new('java.util.Random', 123).nextInt(10)); }; random();",
|
||||
jexl);
|
||||
Facts facts = new Facts();
|
||||
facts.put("System", System.class);
|
||||
|
||||
// when
|
||||
printAction.execute(facts);
|
||||
|
||||
// then
|
||||
assertThat(systemOutRule.getLog()).contains("Random from JEXL = 2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithBlackSanbox() throws Exception {
|
||||
JexlSandbox sandbox = new JexlSandbox(false);
|
||||
sandbox.white(System.class.getName()).execute("currentTimeMillis");
|
||||
JexlEngine jexl = new JexlBuilder()
|
||||
.sandbox(sandbox)
|
||||
.create();
|
||||
|
||||
Facts facts = new Facts();
|
||||
facts.put("result", null);
|
||||
facts.put("System", System.class);
|
||||
facts.put("UUID", UUID.class);
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
new JexlAction("result = System.currentTimeMillis()", jexl).execute(facts);
|
||||
Object result = facts.get("result");
|
||||
assertThat(result).isInstanceOf(Long.class);
|
||||
assertThat((long) result).isGreaterThanOrEqualTo(now);
|
||||
|
||||
try {
|
||||
new JexlAction("result = System.nanoTime()", jexl).execute(facts);
|
||||
fail("Exception expected");
|
||||
} catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(JexlException.Method.class);
|
||||
}
|
||||
|
||||
try {
|
||||
new JexlAction("result = new('java.lang.Double', 10)", jexl).execute(facts);
|
||||
fail("Exception expected");
|
||||
} catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(JexlException.Method.class);
|
||||
}
|
||||
|
||||
try {
|
||||
new JexlAction("result = new('java.io.File', '/tmp/jexl-sandbox-test')", jexl).execute(facts);
|
||||
fail("Exception expected");
|
||||
} catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(JexlException.Method.class);
|
||||
}
|
||||
|
||||
try {
|
||||
new JexlAction("result = UUID.randomUUID()", jexl).execute(facts);
|
||||
fail("Exception expected");
|
||||
} catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(JexlException.Method.class);
|
||||
}
|
||||
|
||||
try {
|
||||
new JexlAction("result = Math.PI", jexl).execute(facts);
|
||||
fail("Exception expected");
|
||||
} catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(JexlException.Variable.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithWhiteSanbox() throws Exception {
|
||||
JexlSandbox sandbox = new JexlSandbox(true);
|
||||
sandbox.black(System.class.getName()).execute("nanoTime");
|
||||
JexlEngine jexl = new JexlBuilder()
|
||||
.sandbox(sandbox)
|
||||
.create();
|
||||
|
||||
Facts facts = new Facts();
|
||||
facts.put("result", null);
|
||||
facts.put("System", System.class);
|
||||
facts.put("UUID", UUID.class);
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
new JexlAction("result = System.currentTimeMillis()", jexl).execute(facts);
|
||||
Object result = facts.get("result");
|
||||
assertThat(result).isInstanceOf(Long.class);
|
||||
assertThat((long) result).isGreaterThanOrEqualTo(now);
|
||||
|
||||
try {
|
||||
new JexlAction("result = System.nanoTime()", jexl).execute(facts);
|
||||
fail("Exception expected");
|
||||
} catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(JexlException.Method.class);
|
||||
}
|
||||
|
||||
new JexlAction("result = new('java.lang.Double', 10)", jexl).execute(facts);
|
||||
result = facts.get("result");
|
||||
assertThat(result).isInstanceOf(Double.class);
|
||||
assertThat((double) result).isEqualTo(10.0);
|
||||
|
||||
new JexlAction("result = new('java.io.File', '/tmp/jexl-sandbox-test')", jexl).execute(facts);
|
||||
result = facts.get("result");
|
||||
assertThat(result).isInstanceOf(File.class);
|
||||
assertThat(((File) result).exists()).isFalse();
|
||||
assertThat(((File) result).getName()).isEqualTo("jexl-sandbox-test");
|
||||
|
||||
new JexlAction("result = UUID.randomUUID()", jexl).execute(facts);
|
||||
result = facts.get("result");
|
||||
assertThat(result).isInstanceOf(UUID.class);
|
||||
|
||||
try {
|
||||
new JexlAction("result = Math.PI", jexl).execute(facts);
|
||||
fail("Exception expected");
|
||||
} catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(JexlException.Variable.class);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2020, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jeasy.rules.jexl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.jeasy.rules.api.Condition;
|
||||
import org.jeasy.rules.api.Facts;
|
||||
import org.junit.Test;
|
||||
|
||||
public class JexlConditionTest {
|
||||
|
||||
@Test
|
||||
public void testJexlExpressionEvaluation() {
|
||||
// given
|
||||
Condition isAdult = new JexlCondition("person.age > 18");
|
||||
Facts facts = new Facts();
|
||||
facts.put("person", new Person("foo", 20));
|
||||
|
||||
// when
|
||||
boolean evaluationResult = isAdult.evaluate(facts);
|
||||
|
||||
// then
|
||||
assertThat(evaluationResult).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDeclaredFactIsNotPresent_thenShouldReturnFalse() {
|
||||
// given
|
||||
Condition isHot = new JexlCondition("temperature > 30");
|
||||
Facts facts = new Facts();
|
||||
|
||||
// when
|
||||
boolean evaluationResult = isHot.evaluate(facts);
|
||||
|
||||
// then
|
||||
assertThat(evaluationResult).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJexlConditionWithFacts() {
|
||||
// given
|
||||
Condition condition = new JexlCondition("return rnd.nextBoolean();");
|
||||
Facts facts = new Facts();
|
||||
facts.put("rnd", new Random(123));
|
||||
|
||||
// when
|
||||
boolean evaluationResult = condition.evaluate(facts);
|
||||
|
||||
// then
|
||||
assertThat(evaluationResult).isTrue();
|
||||
}
|
||||
}
|
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2020, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jeasy.rules.jexl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.jeasy.rules.api.Rule;
|
||||
import org.jeasy.rules.api.Rules;
|
||||
import org.jeasy.rules.support.JsonRuleDefinitionReader;
|
||||
import org.jeasy.rules.support.UnitRuleGroup;
|
||||
import org.jeasy.rules.support.YamlRuleDefinitionReader;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameter;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class JexlRuleFactoryTest {
|
||||
|
||||
@Parameters
|
||||
public static Collection<Object[]> params() {
|
||||
return Arrays.asList(new Object[][] {
|
||||
{ new JexlRuleFactory(new YamlRuleDefinitionReader()), "yml" },
|
||||
{ new JexlRuleFactory(new JsonRuleDefinitionReader()), "json" },
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@org.junit.Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Parameter(0)
|
||||
public JexlRuleFactory factory;
|
||||
|
||||
@Parameter(1)
|
||||
public String ext;
|
||||
|
||||
@Test
|
||||
public void testRulesCreation() throws Exception {
|
||||
// given
|
||||
File rulesDescriptor = new File("src/test/resources/rules." + ext);
|
||||
|
||||
// when
|
||||
Rules rules = factory.createRules(new FileReader(rulesDescriptor));
|
||||
|
||||
// then
|
||||
assertThat(rules).hasSize(2);
|
||||
Iterator<Rule> iterator = rules.iterator();
|
||||
|
||||
Rule rule = iterator.next();
|
||||
assertThat(rule).isNotNull();
|
||||
assertThat(rule.getName()).isEqualTo("adult rule");
|
||||
assertThat(rule.getDescription()).isEqualTo("when age is greater then 18, then mark as adult");
|
||||
assertThat(rule.getPriority()).isEqualTo(1);
|
||||
|
||||
rule = iterator.next();
|
||||
assertThat(rule).isNotNull();
|
||||
assertThat(rule.getName()).isEqualTo("weather rule");
|
||||
assertThat(rule.getDescription()).isEqualTo("when it rains, then take an umbrella");
|
||||
assertThat(rule.getPriority()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleCreationFromFileReader() throws Exception {
|
||||
// given
|
||||
Reader adultRuleDescriptorAsReader = new FileReader("src/test/resources/adult-rule." + ext);
|
||||
|
||||
// when
|
||||
Rule adultRule = factory.createRule(adultRuleDescriptorAsReader);
|
||||
|
||||
// then
|
||||
assertThat(adultRule.getName()).isEqualTo("adult rule");
|
||||
assertThat(adultRule.getDescription()).isEqualTo("when age is greater then 18, then mark as adult");
|
||||
assertThat(adultRule.getPriority()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleCreationFromStringReader() throws Exception {
|
||||
// given
|
||||
Reader adultRuleDescriptorAsReader = new StringReader(new String(Files.readAllBytes(Paths.get("src/test/resources/adult-rule." + ext))));
|
||||
|
||||
// when
|
||||
Rule adultRule = factory.createRule(adultRuleDescriptorAsReader);
|
||||
|
||||
// then
|
||||
assertThat(adultRule.getName()).isEqualTo("adult rule");
|
||||
assertThat(adultRule.getDescription()).isEqualTo("when age is greater then 18, then mark as adult");
|
||||
assertThat(adultRule.getPriority()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleCreationFromFileReader_withCompositeRules() throws Exception {
|
||||
// given
|
||||
File rulesDescriptor = new File("src/test/resources/composite-rules." + ext);
|
||||
|
||||
// when
|
||||
Rules rules = factory.createRules(new FileReader(rulesDescriptor));
|
||||
|
||||
// then
|
||||
assertThat(rules).hasSize(2);
|
||||
Iterator<Rule> iterator = rules.iterator();
|
||||
|
||||
Rule rule = iterator.next();
|
||||
assertThat(rule).isNotNull();
|
||||
assertThat(rule.getName()).isEqualTo("Movie id rule");
|
||||
assertThat(rule.getDescription()).isEqualTo("description");
|
||||
assertThat(rule.getPriority()).isEqualTo(1);
|
||||
assertThat(rule).isInstanceOf(UnitRuleGroup.class);
|
||||
|
||||
rule = iterator.next();
|
||||
assertThat(rule).isNotNull();
|
||||
assertThat(rule.getName()).isEqualTo("weather rule");
|
||||
assertThat(rule.getDescription()).isEqualTo("when it rains, then take an umbrella");
|
||||
assertThat(rule.getPriority()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleCreationFromFileReader_withInvalidCompositeRuleType() throws Exception {
|
||||
// given
|
||||
expectedException.expect(IllegalArgumentException.class);
|
||||
expectedException.expectMessage("Invalid composite rule type, must be one of [UnitRuleGroup, ConditionalRuleGroup, ActivationRuleGroup]");
|
||||
File rulesDescriptor = new File("src/test/resources/composite-rule-invalid-composite-rule-type." + ext);
|
||||
|
||||
// when
|
||||
factory.createRule(new FileReader(rulesDescriptor));
|
||||
|
||||
// then
|
||||
// expected exception
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleCreationFromFileReader_withEmptyComposingRules() throws Exception {
|
||||
// given
|
||||
expectedException.expect(IllegalArgumentException.class);
|
||||
expectedException.expectMessage("Composite rules must have composing rules specified");
|
||||
File rulesDescriptor = new File("src/test/resources/composite-rule-invalid-empty-composing-rules." + ext);
|
||||
|
||||
// when
|
||||
factory.createRule(new FileReader(rulesDescriptor));
|
||||
|
||||
// then
|
||||
// expected exception
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleCreationFromFileReader_withNonCompositeRuleDeclaresComposingRules() throws Exception {
|
||||
// given
|
||||
expectedException.expect(IllegalArgumentException.class);
|
||||
expectedException.expectMessage("Non-composite rules cannot have composing rules");
|
||||
File rulesDescriptor = new File("src/test/resources/non-composite-rule-with-composing-rules." + ext);
|
||||
|
||||
// when
|
||||
factory.createRule(new FileReader(rulesDescriptor));
|
||||
|
||||
// then
|
||||
// expected exception
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2020, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jeasy.rules.jexl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.jeasy.rules.api.Facts;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class JexlRuleTest {
|
||||
|
||||
private Facts facts = new Facts();
|
||||
private JexlRule jexlRule = new JexlRule().name("name").description("description").priority(1);
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
jexlRule.when("person.age > 18");
|
||||
jexlRule.then("person.setAdult(true);");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenTheRuleIsTriggered_thenConditionShouldBeEvaluated() {
|
||||
// given
|
||||
facts.put("person", new Person("foo", 20));
|
||||
|
||||
// when
|
||||
boolean evaluationResult = jexlRule.evaluate(facts);
|
||||
|
||||
// then
|
||||
assertThat(evaluationResult).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenTheConditionIsTrue_thenActionsShouldBeExecuted() throws Exception {
|
||||
// given
|
||||
Person foo = new Person("foo", 20);
|
||||
facts.put("person", foo);
|
||||
|
||||
// when
|
||||
jexlRule.execute(facts);
|
||||
|
||||
// then
|
||||
assertThat(foo.isAdult()).isTrue();
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2020, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.jeasy.rules.jexl;
|
||||
|
||||
public class Person {
|
||||
|
||||
private String name;
|
||||
private int age;
|
||||
private boolean isAdult;
|
||||
|
||||
public Person(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public boolean isAdult() {
|
||||
return isAdult;
|
||||
}
|
||||
|
||||
public void setAdult(boolean adult) {
|
||||
isAdult = adult;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"name": "adult rule",
|
||||
"description": "when age is greater then 18, then mark as adult",
|
||||
"priority": 1,
|
||||
"condition": "person.age > 18",
|
||||
"actions": [
|
||||
"person.setAdult(true);"
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,6 @@
|
||||
name: adult rule
|
||||
description: when age is greater then 18, then mark as adult
|
||||
priority: 1
|
||||
condition: "person.age > 18"
|
||||
actions:
|
||||
- "person.setAdult(true);"
|
@ -0,0 +1,23 @@
|
||||
[
|
||||
{
|
||||
"name": "invalid rule",
|
||||
"compositeRuleType": "foo",
|
||||
"priority": 1,
|
||||
"composingRules": [
|
||||
{
|
||||
"name": "rule1",
|
||||
"condition": "true",
|
||||
"actions": [
|
||||
"System.out.println();"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule2",
|
||||
"condition": "false",
|
||||
"actions": [
|
||||
"System.out.println();"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,12 @@
|
||||
name: invalid rule
|
||||
compositeRuleType: foo
|
||||
priority: 1
|
||||
composingRules:
|
||||
- name: rule1
|
||||
condition: "true"
|
||||
actions:
|
||||
- "System.out.println();"
|
||||
- name: rule2
|
||||
condition: "false"
|
||||
actions:
|
||||
- "System.out.println();"
|
@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"name": "invalid rule",
|
||||
"compositeRuleType": "UnitRuleGroup",
|
||||
"priority": 1,
|
||||
"composingRules": []
|
||||
}
|
||||
]
|
@ -0,0 +1,4 @@
|
||||
name: invalid rule
|
||||
compositeRuleType: UnitRuleGroup
|
||||
priority: 1
|
||||
composingRules:
|
@ -0,0 +1,36 @@
|
||||
[
|
||||
{
|
||||
"name": "Movie id rule",
|
||||
"compositeRuleType": "UnitRuleGroup",
|
||||
"priority": 1,
|
||||
"composingRules": [
|
||||
{
|
||||
"name": "Time is evening",
|
||||
"description": "If it's later than 7pm",
|
||||
"priority": 1,
|
||||
"condition": "day.hour > 19",
|
||||
"actions": [
|
||||
"person.shouldProvideId(true);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Movie is rated R",
|
||||
"description": "If the movie is rated R",
|
||||
"priority": 1,
|
||||
"condition": "movie.rating == R",
|
||||
"actions": [
|
||||
"person.shouldProvideId(true);"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "weather rule",
|
||||
"description": "when it rains, then take an umbrella",
|
||||
"priority": 1,
|
||||
"condition": "rain == True",
|
||||
"actions": [
|
||||
"System.out.println(\"It rains, take an umbrella!\");"
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,23 @@
|
||||
name: Movie id rule
|
||||
compositeRuleType: UnitRuleGroup
|
||||
priority: 1
|
||||
composingRules:
|
||||
- name: Time is evening
|
||||
description: If it's later than 7pm
|
||||
priority: 1
|
||||
condition: "day.hour > 19"
|
||||
actions:
|
||||
- "person.shouldProvideId(true);"
|
||||
- name: Movie is rated R
|
||||
description: If the movie is rated R
|
||||
priority: 1
|
||||
condition: "movie.rating == R"
|
||||
actions:
|
||||
- "person.shouldProvideId(true);"
|
||||
---
|
||||
name: weather rule
|
||||
description: when it rains, then take an umbrella
|
||||
priority: 1
|
||||
condition: "rain == True"
|
||||
actions:
|
||||
- "System.out.println(\"It rains, take an umbrella!\");"
|
@ -0,0 +1,30 @@
|
||||
[
|
||||
{
|
||||
"name": "Movie id rule",
|
||||
"priority": 1,
|
||||
"condition": "true",
|
||||
"actions": [
|
||||
"System.out.println();"
|
||||
],
|
||||
"composingRules": [
|
||||
{
|
||||
"name": "Time is evening",
|
||||
"description": "If it's later than 7pm",
|
||||
"priority": 1,
|
||||
"condition": "day.hour > 19",
|
||||
"actions": [
|
||||
"person.shouldProvideId(true);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Movie is rated R",
|
||||
"description": "If the movie is rated R",
|
||||
"priority": 1,
|
||||
"condition": "movie.rating == R",
|
||||
"actions": [
|
||||
"person.shouldProvideId(true);"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,18 @@
|
||||
name: Movie id rule
|
||||
priority: 1
|
||||
condition: "true"
|
||||
actions:
|
||||
- "System.out.println();"
|
||||
composingRules:
|
||||
- name: Time is evening
|
||||
description: If it's later than 7pm
|
||||
priority: 1
|
||||
condition: "day.hour > 19"
|
||||
actions:
|
||||
- "person.shouldProvideId(true);"
|
||||
- name: Movie is rated R
|
||||
description: If the movie is rated R
|
||||
priority: 1
|
||||
condition: "movie.rating == R"
|
||||
actions:
|
||||
- "person.shouldProvideId(true);"
|
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"name": "adult rule",
|
||||
"description": "when age is greater then 18, then mark as adult",
|
||||
"priority": 1,
|
||||
"condition": "person.age > 18",
|
||||
"actions": [
|
||||
"person.setAdult(true);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "weather rule",
|
||||
"description": "when it rains, then take an umbrella",
|
||||
"priority": 2,
|
||||
"condition": "rain == true",
|
||||
"actions": [
|
||||
"System.out.println(\"It rains, take an umbrella!\");"
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
name: adult rule
|
||||
description: when age is greater then 18, then mark as adult
|
||||
priority: 1
|
||||
condition: "person.age > 18"
|
||||
actions:
|
||||
- "person.setAdult(true);"
|
||||
---
|
||||
name: weather rule
|
||||
description: when it rains, then take an umbrella
|
||||
priority: 2
|
||||
condition: "rain == true"
|
||||
actions:
|
||||
- "System.out.println(\"It rains, take an umbrella!\");"
|
Loading…
Reference in New Issue