Claus Ibsen created CAMEL-24984:
-----------------------------------

             Summary: camel-core: simple - support ! as a negation prefix in a 
predicate
                 Key: CAMEL-24984
                 URL: https://issues.apache.org/jira/browse/CAMEL-24984
             Project: Camel
          Issue Type: Improvement
          Components: camel-core
            Reporter: Claus Ibsen


Simple has no boolean {{!}} prefix. {{${body != null && !body.isEmpty()}}} and 
{{${body != null && !${body.isEmpty()}}}} both fail; the comparison has to be 
written out as {{${body.isEmpty()} == false}}. Every language a Camel user 
comes from has {{!}}, and it is one of the forms a local model writes 
unprompted (seen in three separate benchmark series).

h3. Why the risk is smaller than it looks

Simple only interprets operators in *predicate* context. An expression - the 
log messages people worry about - never tokenizes an operator at all:

{noformat}
"Hello ${body}! how are you"  ->  Hello World! how are you
"!aaa! is a weird text"       ->  !aaa! is a weird text
"${body} != 'x'"              ->  World != 'x'     (even != is literal text in 
an expression)
{noformat}

Quoted literals inside a predicate are also already safe, since the tokenizer 
takes a quoted string as one unit: {{${body} == 'Hello!'}}, {{${body} contains 
'!'}} and {{${body} != 'x!'}} all evaluate correctly today.

So the blast radius is an unquoted {{!}} at an operand position inside a 
predicate.

h3. The sharp edge

A bare {{!}} has to be told apart from the nine operators that already start 
with one: {{!=}}, {{!contains}}, {{!endsWith}}, {{!equals}}, {{!in}}, {{!is}}, 
{{!range}}, {{!regex}}, {{!startsWith}}. They are a known, finite set, so the 
cases can be enumerated in tests, but the ordering logic in the tokenizer is 
where a regression would hide.

h3. What it touches

# {{UnaryOperatorType}} - a NOT alongside INC and DEC.
# {{SimpleTokenizer}} - {{!}} as a token. {{evalUnary}} today requires the 
previous character to be {{\}}} and the next to be whitespace, which is the 
*postfix* rule for {{++}} and {{--}}; a prefix needs the inverse, so that 
method has to branch per operator or a new token type is needed.
# {{UnaryExpression}} applies to the node on its left ({{acceptLeft}}) and 
{{prepareUnaryExpressions}} stacks leftward; a prefix form applies to the node 
on its right.
# {{createExpression}} there handles numeric {{++}}/{{--}}; NOT needs boolean 
semantics and must produce a Predicate.
# {{SimpleSyntaxHints.wrapFunctions}} (CAMEL-24921) splits on {{&&}} and {{||}} 
and must keep a leading {{!}} attached to its operand.
# the simple language documentation, and the message added for the unsupported 
case, which would then be wrong.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to