From ad19dc5948620c2fc55e7e5fdc769e9f3c0a5d5a Mon Sep 17 00:00:00 2001 From: Matteo Mortari Date: Thu, 22 Jun 2023 17:29:49 +0200 Subject: [PATCH] DROOLS-7475 Proposed feature for ['key'] accessor (#5333) * DROOLS-7475 Proposed feature for ['key'] accessor see also https://github.com/kiegroup/drools-ansible-rulebook-integration/pull/56#discussion_r1235164928 make IndexableExpression interface so downstream can leverage this rather than specific concrete class * fix PrototypeDSL * implement code review feedback --------- Co-authored-by: mariofusco --- .../java/org/drools/model/PrototypeDSL.java | 23 ++++++------------- .../org/drools/model/PrototypeExpression.java | 17 ++++++++++---- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drools-model/drools-canonical-model/src/main/java/org/drools/model/PrototypeDSL.java b/drools-model/drools-canonical-model/src/main/java/org/drools/model/PrototypeDSL.java index dab43ff1e0f..aea97784cce 100644 --- a/drools-model/drools-canonical-model/src/main/java/org/drools/model/PrototypeDSL.java +++ b/drools-model/drools-canonical-model/src/main/java/org/drools/model/PrototypeDSL.java @@ -130,21 +130,18 @@ public PrototypePatternDef expr(PrototypeExpression left, ConstraintOperator ope } Prototype prototype = getPrototype(); - Function1 leftExtractor; + Function1 leftExtractor = left.asFunction(prototype); AlphaIndex alphaIndex = null; - if (left instanceof PrototypeExpression.PrototypeFieldValue && right instanceof PrototypeExpression.FixedValue && operator instanceof Index.ConstraintType) { - String fieldName = ((PrototypeExpression.PrototypeFieldValue) left).getFieldName(); + if (left.getIndexingKey().isPresent() && right instanceof PrototypeExpression.FixedValue && operator instanceof Index.ConstraintType) { + String fieldName = left.getIndexingKey().get(); Index.ConstraintType constraintType = (Index.ConstraintType) operator; Prototype.Field field = prototype.getField(fieldName); Object value = ((PrototypeExpression.FixedValue) right).getValue(); - leftExtractor = getFieldValueExtractor(prototype, fieldName); Class fieldClass = (Class) (field != null && field.isTyped() ? field.getType() : value != null ? value.getClass() : null); if (fieldClass != null) { alphaIndex = alphaIndexedBy(fieldClass, constraintType, getFieldIndex(prototype, fieldName, field), leftExtractor, value); } - } else { - leftExtractor = left.asFunction(prototype); } Set reactOnFields = new HashSet<>(); @@ -186,14 +183,12 @@ other, asPredicate2(left.asFunction(prototype), operator, right.asFunction(other } private BetaIndex createBetaIndex(PrototypeExpression left, ConstraintOperator operator, PrototypeExpression right, Prototype prototype, Prototype otherPrototype) { - if (left instanceof PrototypeExpression.PrototypeFieldValue && operator instanceof Index.ConstraintType && right instanceof PrototypeExpression.PrototypeFieldValue) { - String fieldName = ((PrototypeExpression.PrototypeFieldValue) left).getFieldName(); + if (left.getIndexingKey().isPresent() && operator instanceof Index.ConstraintType && right.getIndexingKey().isPresent()) { + String fieldName = left.getIndexingKey().get(); Index.ConstraintType constraintType = (Index.ConstraintType) operator; Prototype.Field field = prototype.getField(fieldName); - Function1 extractor = getFieldValueExtractor(prototype, fieldName); - - String otherFieldName = ((PrototypeExpression.PrototypeFieldValue) right).getFieldName(); - Function1 otherExtractor = getFieldValueExtractor(otherPrototype, otherFieldName); + Function1 extractor = left.asFunction(prototype); + Function1 otherExtractor = right.asFunction(otherPrototype); Class fieldClass = (Class) (field != null && field.isTyped() ? field.getType() : Object.class); return betaIndexedBy( fieldClass, constraintType, getFieldIndex(prototype, fieldName, field), extractor, otherExtractor ); @@ -272,10 +267,6 @@ private PrototypeVariable[] findRightPrototypeVariables(PrototypeExpression righ private static boolean evaluateConstraint(Object leftValue, ConstraintOperator operator, Object rightValue) { return leftValue != Prototype.UNDEFINED_VALUE && rightValue != Prototype.UNDEFINED_VALUE && operator.asPredicate().test(leftValue, rightValue); } - - private Function1 getFieldValueExtractor(Prototype prototype, String fieldName) { - return prototype.getFieldValueExtractor(fieldName)::apply; - } } public static class PrototypeSubPatternDefImpl extends PrototypePatternDefImpl { diff --git a/drools-model/drools-canonical-model/src/main/java/org/drools/model/PrototypeExpression.java b/drools-model/drools-canonical-model/src/main/java/org/drools/model/PrototypeExpression.java index da0192a9d74..07d88908148 100644 --- a/drools-model/drools-canonical-model/src/main/java/org/drools/model/PrototypeExpression.java +++ b/drools-model/drools-canonical-model/src/main/java/org/drools/model/PrototypeExpression.java @@ -21,6 +21,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import org.drools.model.functions.Function1; @@ -35,6 +36,13 @@ interface EvaluableExpression { Function1 asFunction(Prototype prototype); Collection getImpactedFields(); + + /** + * if indexable, return a key for alpha/beta indexing + */ + default Optional getIndexingKey() { + return Optional.empty(); + } static PrototypeExpression fixedValue(Object value) { return new FixedValue(value); @@ -150,8 +158,9 @@ public Function1 asFunction(Prototype prototype) { return prototype.getFieldValueExtractor(fieldName)::apply; } - public String getFieldName() { - return fieldName; + @Override + public Optional getIndexingKey() { + return Optional.of(fieldName); } @Override @@ -189,12 +198,12 @@ public Collection getPrototypeVariables() { @Override public Object evaluate(Map factsMap) { - return protoVar.getPrototype().getFieldValueExtractor(getFieldName()).apply(factsMap.get(protoVar)); + return protoVar.getPrototype().getFieldValueExtractor(getIndexingKey().get()).apply(factsMap.get(protoVar)); } @Override public String toString() { - return "PrototypeFieldValue{" + getFieldName() + " on " + protoVar + "}"; + return "PrototypeFieldValue{" + getIndexingKey() + " on " + protoVar + "}"; } }