0

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)
Mike
  • 20,010
  • 25
  • 97
  • 140
  • Maybe it's because you have one L in the first `cancelationCode` but two in the second? – JJJ Dec 31 '18 at 16:42
  • no it's just my typo, I put simplified expression here to open a discussion ) – Mike Dec 31 '18 at 16:57
  • You'll have to show a complete example ([mcve]) that demonstrates the issue, and explain what "bahaves differently" means. What is the value of `cancelationCode` and what is the result of those comparisons? It's very likely that the problem is somewhere else in the code. – JJJ Dec 31 '18 at 17:00
  • Sorry, I was thinking its ='C'. – I_Al-thamary Dec 31 '18 at 17:10
  • 'behaves differently' means that for the same input object one statement triggers the rule but another doesn't – Mike Dec 31 '18 at 17:17
  • See this: http://www.jbug.jp/trans/jboss-rules3.0.2/ja/html/ch01s03.html. I think the problem is related to `First Order Logic (FOL)` – I_Al-thamary Dec 31 '18 at 17:17
  • I went through documentation, could you explain what could be wrong with `First Order Logic (FOL)`? – Mike Dec 31 '18 at 17:32
  • First order logic ensures rules will only be matched when no other keywords are present. In this example, the rule turns the sprinkler off when the fire is extinguished: https://access.redhat.com/documentation/en-us/jboss_enterprise_soa_platform/5/html-single/jboss_rules_5_reference_guide/index#First_Order_Logic – I_Al-thamary Jan 01 '19 at 12:59
  • https://en.wikipedia.org/wiki/First-order_logic – I_Al-thamary Jan 01 '19 at 13:01
  • As a long-time coder who just tapped on the link as i have never heard of drools before, my first thought in reading this question is why even have such a logic construction in the first place? It seems very redundant. – drew.. Jan 04 '19 at 12:54
  • this is generated code, result of DSL processing. The goal is DSL to be human readable and concise. Generated code must work – Mike Jan 07 '19 at 04:26

1 Answers1

1

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.

Mike
  • 20,010
  • 25
  • 97
  • 140