Skip to content

Commit

Permalink
set MVEL as default expression lang
Browse files Browse the repository at this point in the history
  • Loading branch information
Rikkola committed May 7, 2024
1 parent 10edbeb commit 2424aab
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 36 deletions.
9 changes: 9 additions & 0 deletions kie-yard/kie-yard-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
<groupId>ch.obermuhlner</groupId>
<artifactId>jshell-scriptengine</artifactId>
</dependency>
<dependency>
<groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
Expand All @@ -58,6 +62,11 @@
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,31 @@
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class LiteralExpressionInterpreter implements Firable {
public class JShellLiteralExpressionInterpreter implements Firable {

private final String name;
private final QuotedExprParsed quoted;
private final ScriptEngine engine;
private final CompiledScript compiledScript;

public LiteralExpressionInterpreter(String nameString, QuotedExprParsed quotedExprParsed) {
public JShellLiteralExpressionInterpreter(final String nameString,
final QuotedExprParsed quotedExprParsed) {
this.name = nameString;
this.quoted = quotedExprParsed;
try {
ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngineManager manager = new ScriptEngineManager();
engine = manager.getEngineByName("jshell");
Compilable compiler = (Compilable) engine;
final Compilable compiler = (Compilable) engine;
compiledScript = compiler.compile(quoted.getRewrittenExpression());
} catch (Exception e) {
throw new IllegalArgumentException("parse error", e);
}
}

@Override
public int fire(Map<String, Object> context, YaRDDefinitions units) {
Bindings bindings = engine.createBindings();
public int fire(final Map<String, Object> context,
final YaRDDefinitions units) {
final Bindings bindings = engine.createBindings();
// deliberately escape all symbols; a normal symbol will
// never be in the detected-by-unquoting set, so this
// set can't be used to selectively put in scope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,33 @@

import org.kie.yard.api.model.LiteralExpression;

import java.util.Objects;

public class LiteralExpressionBuilder {

private final String expressionLang;
private final YaRDDefinitions definitions;
private final String name;
private final LiteralExpression decisionLogic;

public LiteralExpressionBuilder(YaRDDefinitions definitions, String name, LiteralExpression decisionLogic) {
public LiteralExpressionBuilder(final String expressionLang,
final YaRDDefinitions definitions,
final String name,
final LiteralExpression decisionLogic) {
this.expressionLang = expressionLang;
this.definitions = definitions;
this.name = name;
this.decisionLogic = decisionLogic;
}

public Firable build() {
String expr = decisionLogic.getExpression();
final String expr = decisionLogic.getExpression();
definitions.outputs().put(name, StoreHandle.empty(Object.class));
return new LiteralExpressionInterpreter(name, QuotedExprParsed.from(expr));
if(Objects.equals(expressionLang, "jshell")){
return new JShellLiteralExpressionInterpreter(name, QuotedExprParsed.from(expr));
}
else {
return new MVELLiteralExpressionInterpreter(name,QuotedExprParsed.from(expr));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.kie.yard.core;

import org.drools.base.util.MVELExecutor;
import org.mvel2.MVEL;

import javax.script.Bindings;
import java.util.HashMap;
import java.util.Map;

public class MVELLiteralExpressionInterpreter implements Firable {
private final String name;
private final QuotedExprParsed expr;

public MVELLiteralExpressionInterpreter(final String name,
final QuotedExprParsed expr) {
this.name = name;
this.expr = expr;
}

@Override
public int fire(final Map<String, Object> context,
final YaRDDefinitions units) {
final Map<String, Object> internalContext = new HashMap<>();
internalContext.putAll(context);

for (Map.Entry<String, StoreHandle<Object>> outKV : units.outputs().entrySet()) {
if (!outKV.getValue().isValuePresent()) {
continue;
}
internalContext.put(QuotedExprParsed.escapeIdentifier(outKV.getKey()), outKV.getValue().get());
}

try {
String rewrittenExpression = expr.getRewrittenExpression();
final Object result = MVEL.eval(rewrittenExpression, internalContext);
units.outputs().get(name).set(result);
return 1;
} catch (Exception e) {
throw new RuntimeException("interpretation failed at runtime", e);
// TODO why throw and not return 0?
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,6 @@ private YaRD getModel(String yaml) throws IOException {

private YaRDDefinitions parse(String yaml) throws IOException {
final YaRD sd = new YaRD_YamlMapperImpl().read(yaml);
if (!Objects.equals(sd.getExpressionLang(), "jshell")) {
throw new IllegalArgumentException("Only `jshell` is supported as an expression language");
}
appendInputs(sd.getInputs());
appendUnits(sd.getElements());
return definitions;
Expand All @@ -107,7 +104,7 @@ private Firable createDecisionLogic(String nameString, DecisionLogic decisionLog
if (decisionLogic instanceof org.kie.yard.api.model.DecisionTable decisionTable) {
return new SyntheticRuleUnitWrapper(new DTableUnitBuilder(definitions, nameString, decisionTable).build());
} else if (decisionLogic instanceof org.kie.yard.api.model.LiteralExpression literalExpression) {
return new LiteralExpressionBuilder(definitions, nameString, literalExpression).build();
return new LiteralExpressionBuilder(model.getExpressionLang(), definitions, nameString, literalExpression).build();
} else {
throw new UnsupportedOperationException("Not implemented.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void testScenario1() throws Exception {
""";
Map<String, Object> outputJSONasMap = evaluate(CTX, FILE_NAME);
assertThat(outputJSONasMap).hasFieldOrPropertyWithValue("Base price", 500);
assertThat(outputJSONasMap).hasFieldOrPropertyWithValue("Downpayment", 50.0);
assertThat(outputJSONasMap).hasFieldOrPropertyWithValue("Downpayment", 50);
}

@Test
Expand All @@ -52,6 +52,6 @@ public void testScenario2() throws Exception {
""";
Map<String, Object> outputJSONasMap = evaluate(CTX, FILE_NAME);
assertThat(outputJSONasMap).hasFieldOrPropertyWithValue("Base price", 1000);
assertThat(outputJSONasMap).hasFieldOrPropertyWithValue("Downpayment", 70.0);
assertThat(outputJSONasMap).hasFieldOrPropertyWithValue("Downpayment", 70);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package org.kie.yard.core;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;

public class MVELLiteralExpressionInterpreterTest {


private MVELLiteralExpressionInterpreter sum;
private YaRDDefinitions yardDefinitions;

void setUp(final String expression) {
sum = new MVELLiteralExpressionInterpreter("sum", QuotedExprParsed.from(expression));

final Map<String, StoreHandle<Object>> outputs = new HashMap<>();
outputs.put("C", StoreHandle.of(5));
outputs.put("sum", StoreHandle.empty(Object.class));
yardDefinitions = new YaRDDefinitions(Collections.emptyMap(), Collections.EMPTY_LIST, outputs);

}

@Test
public void testSum() {

setUp("1+1");

final int fire = sum.fire(Collections.emptyMap(), yardDefinitions);

assertEquals(1, fire);
assertEquals(2, yardDefinitions.outputs().get("sum").get());
}

@Test
public void testOutputVar() {

setUp("Math.max(C, 1)");

final int fire = sum.fire(Collections.emptyMap(), yardDefinitions);

assertEquals(1, fire);
assertEquals(5, yardDefinitions.outputs().get("sum").get());
}

@Test
public void testContext() {

setUp("A+B");

final Map<String, Object> context = new HashMap<>();
context.put("A", 1);
context.put("B", 2);
final int fire = sum.fire(context, yardDefinitions);

assertEquals(1, fire);
assertEquals(3, yardDefinitions.outputs().get("sum").get());
}

@Test
public void testMaps() {

setUp("person.address.street + ' ' + person.address.number");

final Map<String, Object> context = new HashMap<>();
final Map<String, Object> person = new HashMap<>();
final Map<String, Object> address = new HashMap<>();
address.put("street", "My Street");
address.put("number", 12);
person.put("address", address);
context.put("person", person);
final int fire = sum.fire(context, yardDefinitions);

assertEquals(1, fire);
assertEquals("My Street 12", yardDefinitions.outputs().get("sum").get());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
specVersion: alpha
kind: YaRD
name: "Traffic Violation"
expressionLang: jshell
inputs:
- name: "Length"
type: integer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
specVersion: alpha
kind: YaRD
name: 'BasePrice'
expressionLang: jshell
inputs:
- name: 'Age'
type: number
Expand Down
18 changes: 0 additions & 18 deletions kie-yard/kie-yard-core/src/test/resources/logback-test.xml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
specVersion: alpha
kind: YaRD
name: "Traffic Violation"
expressionLang: jshell
inputs:
- name: "Tickets"
type: List
Expand Down

0 comments on commit 2424aab

Please sign in to comment.