Search code examples
drools

Drools boolean comparison


Why false == (cancelationCode == 'C') bahaves differently
from (cancelationCode == 'C') == false?

Is it bug in drools 6.5.0 or am I missing anything?


Here are the full story:

I'm using Drools DSL, and I have to implement a rule:

rule "my business rule"
    dialect "mvel"
    when
        There is a trade that
        - Supervised Trade
        ...
    then
        ...
end

I have these DSL definitions:

[when] Supervised Trade = 
    Customer Trade 
    AND NOT Canceled 

[when] Customer Trade = (recordTypeCode is equal to '910')
[when] Canceled = (cancellationCode is equal to 'C')

[when] is equal to = ==

[when] {var1}?(?<![\w'])\s*AND\s*(?![\w']){var2}? = {var1} && {var2}
[when] {var1}?(?<![\w'])\s*OR\s*(?![\w']){var2}? = {var1} || {var2}
[when] {var1}?(?<![\w'])\s*NOT\s*(?![\w']){var2}? = {var1} false == {var2}

The requirenments is to write reusable DSL statements in positive manner and have an ability to negate them.

Originally NOT was implemented as ! and it was working for current scenario. But it was not working for cases like buySellTypeCode in ('B', 'S'), which is working with false == statement though.

Rule is not triggered for the input object when it DSL is evaluated to

$trade: Trade((recordTypeCode == '910') && false == (cancellationCode == 'C'))    

and it is triggered for the same input object when DSL is evaluated to

$trade: Trade((recordTypeCode == '910') && (cancellationCode == 'C') == false)

Solution

  • It really behaves differently as it is parsed differently with DRL6 lexer.
    org.drools.compiler.compiler.DrlExprParser.parse takes these text snippets as is, but
    BaseDescr expr = parser.conditionalOrExpression(); reveals that ANTLR parser process those differently.

    When I changed false == (cancelationCode == 'C') to true ^ (cancelationCode == 'C') I got an error: "Predicate 'true ^ cancellationCode == 'C'' must be a Boolean expression". This reveals root cause of the problem - ANTLR parser strips braces around single statements, this is why

    false == cancelationCode == 'C' -> doesn't work as expected    
    cancelationCode == 'C' == false -> works as expected
    

    Iterestingly but braces are not stripped around complex statements, so both works as expected:

    false == (true && cancelationCode == 'C')
    (true && cancelationCode == 'C') == false
    

    I would say this 'optimization' is a bug.