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)
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.