Skip to content

Commit

Permalink
[DROOLS-7289] Implement accumulate (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
tkobayas authored and rgdoliveira committed Oct 24, 2024
1 parent c346cfc commit baaa0c1
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ DRL_NOT : 'not';
DRL_IN : 'in';
DRL_FROM : 'from';
DRL_MATCHES : 'matches';
DRL_ACCUMULATE : 'accumulate' | 'acc';
DRL_INIT : 'init';
DRL_ACTION : 'action';
DRL_REVERSE : 'reverse';
DRL_RESULT : 'result';

DRL_SALIENCE : 'salience';
DRL_ENABLED : 'enabled';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ lhsExpression : LPAREN lhsExpression RPAREN #lhsExpressionEnclosed
| lhsExpression (DRL_OR lhsExpression)+ #lhsOr
;

// and is accepted for accumulate
lhsAndForAccumulate : lhsUnary (DRL_AND lhsUnary)+
| LPAREN DRL_AND lhsUnary+ RPAREN
;

/*
lhsUnary : ( lhsExists namedConsequence?
| lhsNot namedConsequence?
Expand All @@ -61,6 +66,7 @@ lhsUnary : (
lhsExists
| lhsNot
| lhsPatternBind
| lhsAccumulate
) ;

lhsPatternBind : label? ( LPAREN lhsPattern (DRL_OR lhsPattern)* RPAREN | lhsPattern ) ;
Expand Down Expand Up @@ -257,9 +263,35 @@ mapEntry
| fromWindow
| fromExpression )
*/
patternSource : fromExpression ;
patternSource : fromExpression
| fromAccumulate
;

fromExpression : conditionalOrExpression ;


/*
fromAccumulate := ACCUMULATE LEFT_PAREN lhsAnd (COMMA|SEMICOLON)
( INIT chunk_(_) COMMA ACTION chunk_(_) COMMA
( REVERSE chunk_(_) COMMA)? RESULT chunk_(_)
| accumulateFunction
) RIGHT_PAREN
*/
fromAccumulate : DRL_ACCUMULATE LPAREN lhsAndForAccumulate (COMMA|SEMI)
( DRL_INIT LPAREN initBlockStatements=blockStatements RPAREN COMMA DRL_ACTION LPAREN actionBlockStatements=blockStatements RPAREN COMMA ( DRL_REVERSE LPAREN reverseBlockStatements=blockStatements RPAREN COMMA)? DRL_RESULT LPAREN expression RPAREN
| accumulateFunction
)
RPAREN (SEMI)?
;

blockStatements : blockStatement* ;

/*
accumulateFunction := label? ID parameters
*/
accumulateFunction : label? IDENTIFIER LPAREN drlExpression RPAREN;


/*
lhsExists := EXISTS
( (LEFT_PAREN (or_key|and_key))=> lhsOr // prevents '((' for prefixed and/or
Expand All @@ -277,6 +309,19 @@ lhsExists : DRL_EXISTS lhsPatternBind ;
*/
lhsNot : DRL_NOT lhsPatternBind ;

/**
* lhsAccumulate := (ACCUMULATE|ACC) LEFT_PAREN lhsAnd (COMMA|SEMICOLON)
* accumulateFunctionBinding (COMMA accumulateFunctionBinding)*
* (SEMICOLON constraints)?
* RIGHT_PAREN SEMICOLON?
*/

lhsAccumulate : DRL_ACCUMULATE LPAREN lhsAndForAccumulate (COMMA|SEMI)
accumulateFunction (COMMA accumulateFunction)*
(SEMI constraints)?
RPAREN (SEMI)?
;

rhs : DRL_THEN consequence ;

consequence : RHS_CHUNK* ;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.RuleNode;
import org.drools.drl.ast.descr.AccumulateDescr;
import org.drools.drl.ast.descr.AndDescr;
import org.drools.drl.ast.descr.AnnotationDescr;
import org.drools.drl.ast.descr.AttributeDescr;
Expand All @@ -25,6 +26,7 @@
import org.drools.drl.ast.descr.OrDescr;
import org.drools.drl.ast.descr.PackageDescr;
import org.drools.drl.ast.descr.PatternDescr;
import org.drools.drl.ast.descr.PatternSourceDescr;
import org.drools.drl.ast.descr.RuleDescr;
import org.drools.drl.ast.descr.UnitDescr;

Expand Down Expand Up @@ -234,17 +236,66 @@ private OrDescr getOrDescrWithMultiplePatternDescr(DRLParser.LhsPatternBindConte
public PatternDescr visitLhsPattern(DRLParser.LhsPatternContext ctx) {
PatternDescr patternDescr = new PatternDescr(ctx.objectType.getText());
if (ctx.patternSource() != null) {
String expression = ctx.patternSource().getText();
FromDescr from = new FromDescr();
from.setDataSource(new MVELExprDescr(expression));
from.setResource(patternDescr.getResource());
patternDescr.setSource(from);
PatternSourceDescr patternSourceDescr = (PatternSourceDescr) visitPatternSource(ctx.patternSource());
patternSourceDescr.setResource(patternDescr.getResource());
patternDescr.setSource(patternSourceDescr);
}
List<ExprConstraintDescr> constraintDescrList = visitConstraints(ctx.constraints());
constraintDescrList.forEach(patternDescr::addConstraint);
return patternDescr;
}

@Override
public PatternDescr visitLhsAccumulate(DRLParser.LhsAccumulateContext ctx) {
AccumulateDescr accumulateDescr = new AccumulateDescr();
accumulateDescr.setInput(visitLhsAndForAccumulate(ctx.lhsAndForAccumulate()));

// accumulate function
for (DRLParser.AccumulateFunctionContext accumulateFunctionContext : ctx.accumulateFunction()) {
accumulateDescr.addFunction(visitAccumulateFunction(accumulateFunctionContext));
}

PatternDescr patternDescr = new PatternDescr("Object");
patternDescr.setSource(accumulateDescr);
List<ExprConstraintDescr> constraintDescrList = visitConstraints(ctx.constraints());
constraintDescrList.forEach(patternDescr::addConstraint);
return patternDescr;
}

@Override
public FromDescr visitFromExpression(DRLParser.FromExpressionContext ctx) {
FromDescr fromDescr = new FromDescr();
fromDescr.setDataSource(new MVELExprDescr(ctx.getText()));
return fromDescr;
}

@Override
public AccumulateDescr visitFromAccumulate(DRLParser.FromAccumulateContext ctx) {
AccumulateDescr accumulateDescr = new AccumulateDescr();
accumulateDescr.setInput(visitLhsAndForAccumulate(ctx.lhsAndForAccumulate()));
if (ctx.DRL_INIT() != null) {
// inline custom accumulate
accumulateDescr.setInitCode(getTextPreservingWhitespace(ctx.initBlockStatements));
accumulateDescr.setActionCode(getTextPreservingWhitespace(ctx.actionBlockStatements));
if (ctx.DRL_REVERSE() != null) {
accumulateDescr.setReverseCode(getTextPreservingWhitespace(ctx.reverseBlockStatements));
}
accumulateDescr.setResultCode(ctx.expression().getText());
} else {
// accumulate function
accumulateDescr.addFunction(visitAccumulateFunction(ctx.accumulateFunction()));
}
return accumulateDescr;
}

@Override
public AccumulateDescr.AccumulateFunctionCallDescr visitAccumulateFunction(DRLParser.AccumulateFunctionContext ctx) {
String function = ctx.IDENTIFIER().getText();
String bind = ctx.label() == null ? null : ctx.label().IDENTIFIER().getText();
String[] params = new String[]{getTextPreservingWhitespace(ctx.drlExpression())};
return new AccumulateDescr.AccumulateFunctionCallDescr(function, bind, false, params);
}

@Override
public List<ExprConstraintDescr> visitConstraints(DRLParser.ConstraintsContext ctx) {
if (ctx == null) {
Expand Down Expand Up @@ -304,12 +355,20 @@ public BaseDescr visitLhsOr(DRLParser.LhsOrContext ctx) {

@Override
public BaseDescr visitLhsAnd(DRLParser.LhsAndContext ctx) {
return createAndDescr(visitDescrChildren(ctx));
}

private AndDescr createAndDescr(List<BaseDescr> descrList) {
AndDescr andDescr = new AndDescr();
List<BaseDescr> descrList = visitDescrChildren(ctx);
descrList.forEach(andDescr::addDescr);
return andDescr;
}

@Override
public BaseDescr visitLhsAndForAccumulate(DRLParser.LhsAndForAccumulateContext ctx) {
return createAndDescr(visitDescrChildren(ctx));
}

@Override
public BaseDescr visitLhsUnary(DRLParser.LhsUnaryContext ctx) {
return (BaseDescr) visitChildren(ctx);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ void parse_fromWithInlineListMethod() {
" System.err.println(\"Invalid customer id found!\"); \n" +
" o.addError(\"Invalid customer id\"); \n" +
"end \n";
System.out.println(source);
PackageDescr pkg = parser.parse(source);
assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse();

Expand Down Expand Up @@ -2011,7 +2010,6 @@ public void parse_QualifiedClassname() throws Exception {
assertThat(p.getObjectType()).isEqualTo("com.cheeseco.Cheese");
}

@Disabled("Priority : High | Implement accumulate")
@Test
public void parse_Accumulate() throws Exception {
final PackageDescr pkg = parseAndGetPackageDescrFromFile(
Expand All @@ -2034,7 +2032,6 @@ public void parse_Accumulate() throws Exception {
assertThat(pattern.getObjectType()).isEqualTo("Person");
}

@Disabled("Priority : High | Implement accumulate")
@Test
public void parse_AccumulateWithBindings() throws Exception {
final PackageDescr pkg = parseAndGetPackageDescrFromFile(
Expand Down Expand Up @@ -2356,7 +2353,6 @@ public void parse_Eval() throws Exception {
assertThat(rule1.getLhs().getDescrs().size()).isEqualTo(1);
}

@Disabled("Priority : High | Implement accumulate")
@Test
public void parse_AccumulateReverse() throws Exception {
final PackageDescr pkg = parseAndGetPackageDescrFromFile(
Expand All @@ -2382,7 +2378,6 @@ public void parse_AccumulateReverse() throws Exception {
assertThat(pattern.getObjectType()).isEqualTo("Person");
}

@Disabled("Priority : High | Implement accumulate")
@Test
public void parse_AccumulateExternalFunction() throws Exception {
final PackageDescr pkg = parseAndGetPackageDescrFromFile(
Expand Down Expand Up @@ -2426,7 +2421,7 @@ public void parse_CollectWithNestedFrom() throws Exception {
assertThat(people.getObjectType()).isEqualTo("People");
}

@Disabled("Priority : High | Implement accumulate")
@Disabled("Priority : High | Implement accumulate and Implement from collect")
@Test
public void parse_AccumulateWithNestedFrom() throws Exception {
final PackageDescr pkg = parseAndGetPackageDescrFromFile(
Expand All @@ -2448,7 +2443,6 @@ public void parse_AccumulateWithNestedFrom() throws Exception {
assertThat(people.getObjectType()).isEqualTo("People");
}

@Disabled("Priority : High | Implement accumulate")
@Test
public void parse_AccumulateMultipleFunctions() throws Exception {
final PackageDescr pkg = parseAndGetPackageDescrFromFile(
Expand Down Expand Up @@ -2482,7 +2476,6 @@ public void parse_AccumulateMultipleFunctions() throws Exception {
assertThat(pattern.getObjectType()).isEqualTo("Cheese");
}

@Disabled("Priority : High | Implement accumulate")
@Test
public void parse_AccumulateMnemonic() throws Exception {
String drl = "package org.drools.mvel.compiler\n" +
Expand Down Expand Up @@ -2515,7 +2508,6 @@ public void parse_AccumulateMnemonic() throws Exception {
assertThat(pattern.getObjectType()).isEqualTo("Cheese");
}

@Disabled("Priority : High | Implement accumulate")
@Test
public void parse_AccumulateMnemonic2() throws Exception {
String drl = "package org.drools.mvel.compiler\n" +
Expand Down Expand Up @@ -2596,7 +2588,6 @@ public void parse_ImportAccumulate() throws Exception {
assertThat(pattern.getObjectType()).isEqualTo("Cheese");
}

@Disabled("Priority : High | Implement accumulate")
@Test
public void parse_AccumulateMultipleFunctionsConstraint() throws Exception {
final PackageDescr pkg = parseAndGetPackageDescrFromFile(
Expand Down Expand Up @@ -2701,7 +2692,6 @@ public void parse_RuleParseLhs3() throws Exception {

}

@Disabled("Priority : High | Implement accumulate")
@Test
public void parse_AccumulateMultiPattern() throws Exception {
final PackageDescr pkg = parseAndGetPackageDescrFromFile(
Expand Down

0 comments on commit baaa0c1

Please sign in to comment.