From d4a3d352fc1cc0a0e948dc2fc5b216f05f5d3538 Mon Sep 17 00:00:00 2001 From: Toshiya Kobayashi Date: Fri, 27 Sep 2024 18:12:06 +0900 Subject: [PATCH] - support alpha index - support node sharing (but not merging error messages) - WIP: need more assertions --- .../RulebookConstraintOperator.java | 57 +++++---- .../domain/constraints/RulebookOperator.java | 21 ++-- .../integration/api/TypeMismatchTest.java | 110 +++++++++++++++++- 3 files changed, 148 insertions(+), 40 deletions(-) diff --git a/drools-ansible-rulebook-integration-api/src/main/java/org/drools/ansible/rulebook/integration/api/domain/constraints/RulebookConstraintOperator.java b/drools-ansible-rulebook-integration-api/src/main/java/org/drools/ansible/rulebook/integration/api/domain/constraints/RulebookConstraintOperator.java index 2f3410e..258f20a 100644 --- a/drools-ansible-rulebook-integration-api/src/main/java/org/drools/ansible/rulebook/integration/api/domain/constraints/RulebookConstraintOperator.java +++ b/drools-ansible-rulebook-integration-api/src/main/java/org/drools/ansible/rulebook/integration/api/domain/constraints/RulebookConstraintOperator.java @@ -5,6 +5,7 @@ import org.drools.ansible.rulebook.integration.api.domain.RuleGenerationContext; import org.drools.model.ConstraintOperator; +import org.drools.model.Index; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,23 +14,13 @@ public class RulebookConstraintOperator implements ConstraintOperator { - enum RulebookConstraintOperatorType { - EQUAL, - NOT_EQUAL, - GREATER_THAN, - GREATER_OR_EQUAL, - LESS_THAN, - LESS_OR_EQUAL, - UNKNOWN; - } - private static final Logger LOG = LoggerFactory.getLogger(RulebookConstraintOperator.class); - private RulebookConstraintOperatorType type; + private Index.ConstraintType type; private ConditionContext conditionContext; private boolean typeCheckLogged = false; - public RulebookConstraintOperator(RulebookConstraintOperatorType type) { + public RulebookConstraintOperator(Index.ConstraintType type) { this.type = type; } @@ -37,28 +28,38 @@ public void setConditionContext(RuleGenerationContext ruleContext, Map exp this.conditionContext = new ConditionContext(ruleContext.getRuleSetName(), ruleContext.getRuleName(), expression.toString()); } + @Override + public boolean containsConstraintType() { + return true; + } + + @Override + public Index.ConstraintType getConstraintType() { + return type; + } + public RulebookConstraintOperator negate() { switch (this.type) { case EQUAL: - this.type = RulebookConstraintOperatorType.NOT_EQUAL; + this.type = Index.ConstraintType.NOT_EQUAL; return this; case NOT_EQUAL: - this.type = RulebookConstraintOperatorType.EQUAL; + this.type = Index.ConstraintType.EQUAL; return this; case GREATER_THAN: - this.type = RulebookConstraintOperatorType.LESS_OR_EQUAL; + this.type = Index.ConstraintType.LESS_OR_EQUAL; return this; case GREATER_OR_EQUAL: - this.type = RulebookConstraintOperatorType.LESS_THAN; + this.type = Index.ConstraintType.LESS_THAN; return this; case LESS_OR_EQUAL: - this.type = RulebookConstraintOperatorType.GREATER_THAN; + this.type = Index.ConstraintType.GREATER_THAN; return this; case LESS_THAN: - this.type = RulebookConstraintOperatorType.GREATER_OR_EQUAL; + this.type = Index.ConstraintType.GREATER_OR_EQUAL; return this; } - this.type = RulebookConstraintOperatorType.UNKNOWN; + this.type = Index.ConstraintType.UNKNOWN; return this; } @@ -124,16 +125,16 @@ private boolean predicateWithTypeCheck(T t, V v, BiPredicate predic public RulebookConstraintOperator inverse() { switch (this.type) { case GREATER_THAN: - this.type = RulebookConstraintOperatorType.LESS_THAN; + this.type = Index.ConstraintType.LESS_THAN; return this; case GREATER_OR_EQUAL: - this.type = RulebookConstraintOperatorType.LESS_OR_EQUAL; + this.type = Index.ConstraintType.LESS_OR_EQUAL; return this; case LESS_THAN: - this.type = RulebookConstraintOperatorType.GREATER_THAN; + this.type = Index.ConstraintType.GREATER_THAN; return this; case LESS_OR_EQUAL: - this.type = RulebookConstraintOperatorType.GREATER_OR_EQUAL; + this.type = Index.ConstraintType.GREATER_OR_EQUAL; return this; default: return this; @@ -145,11 +146,11 @@ public boolean isComparison() { } public boolean isAscending() { - return this.type == RulebookConstraintOperatorType.GREATER_THAN || this.type == RulebookConstraintOperatorType.GREATER_OR_EQUAL; + return this.type == Index.ConstraintType.GREATER_THAN || this.type == Index.ConstraintType.GREATER_OR_EQUAL; } public boolean isDescending() { - return this.type == RulebookConstraintOperatorType.LESS_THAN || this.type == RulebookConstraintOperatorType.LESS_OR_EQUAL; + return this.type == Index.ConstraintType.LESS_THAN || this.type == Index.ConstraintType.LESS_OR_EQUAL; } private class ConditionContext { @@ -176,4 +177,10 @@ public String getConditionExpression() { return conditionExpression; } } + + @Override + public String toString() { + // works for node sharing + return type.toString(); + } } diff --git a/drools-ansible-rulebook-integration-api/src/main/java/org/drools/ansible/rulebook/integration/api/domain/constraints/RulebookOperator.java b/drools-ansible-rulebook-integration-api/src/main/java/org/drools/ansible/rulebook/integration/api/domain/constraints/RulebookOperator.java index 6e4f094..5b383fa 100644 --- a/drools-ansible-rulebook-integration-api/src/main/java/org/drools/ansible/rulebook/integration/api/domain/constraints/RulebookOperator.java +++ b/drools-ansible-rulebook-integration-api/src/main/java/org/drools/ansible/rulebook/integration/api/domain/constraints/RulebookOperator.java @@ -1,11 +1,12 @@ package org.drools.ansible.rulebook.integration.api.domain.constraints; -import org.drools.ansible.rulebook.integration.api.domain.RuleGenerationContext; -import org.drools.model.ConstraintOperator; - import java.util.Map; import java.util.function.BiPredicate; +import org.drools.ansible.rulebook.integration.api.domain.RuleGenerationContext; +import org.drools.model.ConstraintOperator; +import org.drools.model.Index; + public interface RulebookOperator extends ConstraintOperator { default boolean canInverse() { @@ -21,27 +22,27 @@ default ConstraintOperator asConstraintOperator() { } static RulebookOperator newEqual() { - return new OperatorWrapper(new RulebookConstraintOperator(RulebookConstraintOperator.RulebookConstraintOperatorType.EQUAL)); + return new OperatorWrapper(new RulebookConstraintOperator(Index.ConstraintType.EQUAL)); } static RulebookOperator newNotEqual() { - return new OperatorWrapper(new RulebookConstraintOperator(RulebookConstraintOperator.RulebookConstraintOperatorType.NOT_EQUAL)); + return new OperatorWrapper(new RulebookConstraintOperator(Index.ConstraintType.NOT_EQUAL)); } static RulebookOperator newGreaterThan() { - return new OperatorWrapper(new RulebookConstraintOperator(RulebookConstraintOperator.RulebookConstraintOperatorType.GREATER_THAN)); + return new OperatorWrapper(new RulebookConstraintOperator(Index.ConstraintType.GREATER_THAN)); } static RulebookOperator newGreaterOrEqual() { - return new OperatorWrapper(new RulebookConstraintOperator(RulebookConstraintOperator.RulebookConstraintOperatorType.GREATER_OR_EQUAL)); + return new OperatorWrapper(new RulebookConstraintOperator(Index.ConstraintType.GREATER_OR_EQUAL)); } static RulebookOperator newLessThan() { - return new OperatorWrapper(new RulebookConstraintOperator(RulebookConstraintOperator.RulebookConstraintOperatorType.LESS_THAN)); + return new OperatorWrapper(new RulebookConstraintOperator(Index.ConstraintType.LESS_THAN)); } static RulebookOperator newLessOrEqual() { - return new OperatorWrapper(new RulebookConstraintOperator(RulebookConstraintOperator.RulebookConstraintOperatorType.LESS_OR_EQUAL)); + return new OperatorWrapper(new RulebookConstraintOperator(Index.ConstraintType.LESS_OR_EQUAL)); } default void setConditionContext(RuleGenerationContext ruleContext, Map expression) { @@ -49,7 +50,6 @@ default void setConditionContext(RuleGenerationContext ruleContext, Map ex operatorWrapper.setConditionContext(ruleContext, expression); } else { // do nothing - return; } } @@ -80,6 +80,7 @@ public ConstraintOperator asConstraintOperator() { return delegate; } + @Override public void setConditionContext(RuleGenerationContext ruleContext, Map expression) { delegate.setConditionContext(ruleContext, expression); } diff --git a/drools-ansible-rulebook-integration-api/src/test/java/org/drools/ansible/rulebook/integration/api/TypeMismatchTest.java b/drools-ansible-rulebook-integration-api/src/test/java/org/drools/ansible/rulebook/integration/api/TypeMismatchTest.java index fe6d9af..16ae46a 100644 --- a/drools-ansible-rulebook-integration-api/src/test/java/org/drools/ansible/rulebook/integration/api/TypeMismatchTest.java +++ b/drools-ansible-rulebook-integration-api/src/test/java/org/drools/ansible/rulebook/integration/api/TypeMismatchTest.java @@ -1,16 +1,11 @@ package org.drools.ansible.rulebook.integration.api; -import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; -import org.drools.base.reteoo.InitialFactImpl; import org.junit.Test; -import org.kie.api.prototype.PrototypeFactInstance; import org.kie.api.runtime.rule.Match; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; public class TypeMismatchTest { @@ -86,6 +81,7 @@ public void mapAndString() { // mera.headers is a map, not a string List matchedRules = rulesExecutor.processEvents("{ \"meta\": {\"headers\": {\"Content-Length\": \"36\"}} } }").join(); // When comparing mismatched types, the rule should not match (even r2). Logs error for 2 rules. + // TODO: Add log assertion assertEquals(0, matchedRules.size()); // One more time @@ -143,4 +139,108 @@ public void stringAndInteger() { rulesExecutor.dispose(); } + + + @Test + public void typeMismatchWithNodeSharing() { + String json = + """ + { + "rules": [ + { + "Rule": { + "name": "r1", + "condition": { + "AllCondition": [ + { + "AndExpression": { + "lhs": { + "EqualsExpression": { + "lhs": { + "Event": "i" + }, + "rhs": { + "Integer": 1 + } + } + }, + "rhs": { + "EqualsExpression": { + "lhs": { + "Event": "j" + }, + "rhs": { + "Integer": 1 + } + } + } + } + } + ] + }, + "actions": [ + { + "Action": { + "action": "debug", + "action_args": {} + } + } + ], + "enabled": true + } + }, + { + "Rule": { + "name": "r2", + "condition": { + "AllCondition": [ + { + "AndExpression": { + "lhs": { + "EqualsExpression": { + "lhs": { + "Event": "i" + }, + "rhs": { + "Integer": 1 + } + } + }, + "rhs": { + "EqualsExpression": { + "lhs": { + "Event": "j" + }, + "rhs": { + "Integer": 2 + } + } + } + } + } + ] + }, + "actions": [ + { + "Action": { + "action": "debug", + "action_args": {} + } + } + ], + "enabled": true + } + } + ] + } + """; + + RulesExecutor rulesExecutor = RulesExecutorFactory.createFromJson(json); + + // TODO: add node sharing assertion + + // i is a string, not an integer + List matchedRules = rulesExecutor.processEvents("{ \"i\": \"1\", \"j\": 1 }").join(); + assertEquals(0, matchedRules.size()); + } } \ No newline at end of file