This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new ba5fe898dc3f CAMEL-22868: camel-core - Add not variant to startsWith 
and endsWith operator in simple language (#20862)
ba5fe898dc3f is described below

commit ba5fe898dc3f4422ba53afa6224a823074363de0
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Jan 17 18:05:37 2026 +0100

    CAMEL-22868: camel-core - Add not variant to startsWith and endsWith 
operator in simple language (#20862)
---
 .../csimple/joor/OriginalSimpleOperatorTest.java   | 27 ++++++++++++++++++++++
 .../modules/languages/pages/simple-language.adoc   | 13 ++++++-----
 .../camel/language/simple/SimpleTokenizer.java     | 20 ++++++++--------
 .../language/simple/ast/BinaryExpression.java      | 10 ++++++++
 .../language/simple/types/BinaryOperatorType.java  | 16 ++++++++++---
 .../camel/language/simple/SimpleOperatorTest.java  | 27 ++++++++++++++++++++++
 6 files changed, 95 insertions(+), 18 deletions(-)

diff --git 
a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleOperatorTest.java
 
b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleOperatorTest.java
index 51f1cef4ec9a..9e11a8ed20fd 100644
--- 
a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleOperatorTest.java
+++ 
b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleOperatorTest.java
@@ -761,6 +761,20 @@ public class OriginalSimpleOperatorTest extends 
LanguageTestSupport {
         assertPredicate("${in.body} startsWith 'Hi'", false);
     }
 
+    @Test
+    public void testNotStartsWith() {
+        exchange.getIn().setBody("Hello there");
+        assertPredicate("${in.body} !startsWith 'Bye'", true);
+        assertPredicate("${in.body} !startsWith 'Hello'", false);
+        assertPredicate("${in.body} !startsWith 'B'", true);
+        assertPredicate("${in.body} !startsWith 'H'", false);
+        assertPredicate("${in.body} !startsWith 'Bye there'", true);
+        assertPredicate("${in.body} !startsWith 'Hello there'", false);
+        assertPredicate("${in.body} !startsWith 'Hello ther'", false);
+        assertPredicate("${in.body} !startsWith 'ello there'", true);
+        assertPredicate("${in.body} !startsWith 'Hi'", true);
+    }
+
     @Test
     public void testEndsWith() {
         exchange.getIn().setBody("Hello there");
@@ -778,6 +792,19 @@ public class OriginalSimpleOperatorTest extends 
LanguageTestSupport {
         assertPredicate("${in.body} endsWith 'Hi'", false);
     }
 
+    @Test
+    public void testNotEndsWith() {
+        exchange.getIn().setBody("Hello there");
+        assertPredicate("${in.body} !endsWith 'B'", true);
+        assertPredicate("${in.body} !endsWith 'world'", true);
+        assertPredicate("${in.body} !endsWith 'there'", false);
+        assertPredicate("${in.body} !endsWith 're'", false);
+        assertPredicate("${in.body} !endsWith ' there'", false);
+        assertPredicate("${in.body} !endsWith 'Hello there'", false);
+        assertPredicate("${in.body} !endsWith 'Hello ther'", true);
+        assertPredicate("${in.body} !endsWith 'Hi'", true);
+    }
+
     @Override
     protected String getLanguageName() {
         return "csimple";
diff --git 
a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
 
b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
index f8bacd5dfa01..1be00ca5da83 100644
--- 
a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
+++ 
b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
@@ -629,16 +629,17 @@ is a set of four values with an empty value and then the 
three medals.
 |!is |For matching if the left-hand side type is not an instance of the value.
 
 |range |For matching if the left-hand side is within a range of values defined
-as numbers: `from..to`..
+as numbers: `from..to`.
 
 |!range |For matching if the left-hand side is not within a range of values
-defined as numbers: `from..to`. .
+defined as numbers: `from..to`.
 
-|startsWith |For testing if the left-hand side string starts
-with the right-hand string.
+|startsWith |For testing if the left-hand side string starts with the 
right-hand string.
+|!startsWith |For testing if the left-hand side string does not start with the 
right-hand string.
+
+|endsWith |For testing if the left-hand side string ends with the right-hand 
string.
+|!endsWith |For testing if the left-hand side string does not end with the 
right-hand string.
 
-|endsWith |For testing if the left-hand side string ends with
-the right-hand string.
 |===
 
 And the following unary operators can be used:
diff --git 
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java
 
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java
index 506e07fbfa0b..bbaf198ab832 100644
--- 
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java
+++ 
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleTokenizer.java
@@ -27,7 +27,7 @@ import org.apache.camel.util.ObjectHelper;
 public final class SimpleTokenizer {
 
     // keep this number in sync with tokens list
-    private static final int NUMBER_OF_TOKENS = 47;
+    private static final int NUMBER_OF_TOKENS = 49;
 
     private static final SimpleTokenType[] KNOWN_TOKENS = new 
SimpleTokenType[NUMBER_OF_TOKENS];
 
@@ -79,22 +79,24 @@ public final class SimpleTokenizer {
         KNOWN_TOKENS[36] = new SimpleTokenType(TokenType.binaryOperator, 
"!range");
         KNOWN_TOKENS[37] = new SimpleTokenType(TokenType.binaryOperator, 
"range");
         KNOWN_TOKENS[38] = new SimpleTokenType(TokenType.binaryOperator, 
"startsWith");
-        KNOWN_TOKENS[39] = new SimpleTokenType(TokenType.binaryOperator, 
"starts with"); // deprecated
-        KNOWN_TOKENS[40] = new SimpleTokenType(TokenType.binaryOperator, 
"endsWith");
-        KNOWN_TOKENS[41] = new SimpleTokenType(TokenType.binaryOperator, "ends 
with"); // deprecated
+        KNOWN_TOKENS[39] = new SimpleTokenType(TokenType.binaryOperator, 
"starts with");
+        KNOWN_TOKENS[40] = new SimpleTokenType(TokenType.binaryOperator, 
"!startsWith");
+        KNOWN_TOKENS[41] = new SimpleTokenType(TokenType.binaryOperator, 
"endsWith");
+        KNOWN_TOKENS[42] = new SimpleTokenType(TokenType.binaryOperator, "ends 
with");
+        KNOWN_TOKENS[43] = new SimpleTokenType(TokenType.binaryOperator, 
"!endsWith");
 
         // unary operators
-        KNOWN_TOKENS[42] = new SimpleTokenType(TokenType.unaryOperator, "++");
-        KNOWN_TOKENS[43] = new SimpleTokenType(TokenType.unaryOperator, "--");
+        KNOWN_TOKENS[44] = new SimpleTokenType(TokenType.unaryOperator, "++");
+        KNOWN_TOKENS[45] = new SimpleTokenType(TokenType.unaryOperator, "--");
 
         // logical operators
-        KNOWN_TOKENS[44] = new SimpleTokenType(TokenType.logicalOperator, 
"&&");
-        KNOWN_TOKENS[45] = new SimpleTokenType(TokenType.logicalOperator, 
"||");
+        KNOWN_TOKENS[46] = new SimpleTokenType(TokenType.logicalOperator, 
"&&");
+        KNOWN_TOKENS[47] = new SimpleTokenType(TokenType.logicalOperator, 
"||");
 
         //binary operator
         // it is added as the last item because unary -- has the priority
         // if unary not found it is highly possible - operator is run into.
-        KNOWN_TOKENS[46] = new SimpleTokenType(TokenType.minusValue, "-");
+        KNOWN_TOKENS[48] = new SimpleTokenType(TokenType.minusValue, "-");
     }
 
     private SimpleTokenizer() {
diff --git 
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/BinaryExpression.java
 
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/BinaryExpression.java
index 64fec4a9d5b4..559ad32bc6be 100644
--- 
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/BinaryExpression.java
+++ 
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/BinaryExpression.java
@@ -127,8 +127,14 @@ public class BinaryExpression extends BaseSimpleNode {
             return createRangeExpression(camelContext, expression, leftExp, 
rightExp);
         } else if (operator == BinaryOperatorType.STARTS_WITH) {
             return createExpression(camelContext, leftExp, rightExp, 
PredicateBuilder.startsWith(leftExp, rightExp));
+        } else if (operator == BinaryOperatorType.NOT_STARTS_WITH) {
+            return createExpression(camelContext, leftExp, rightExp,
+                    PredicateBuilder.not(PredicateBuilder.startsWith(leftExp, 
rightExp)));
         } else if (operator == BinaryOperatorType.ENDS_WITH) {
             return createExpression(camelContext, leftExp, rightExp, 
PredicateBuilder.endsWith(leftExp, rightExp));
+        } else if (operator == BinaryOperatorType.NOT_ENDS_WITH) {
+            return createExpression(camelContext, leftExp, rightExp,
+                    PredicateBuilder.not(PredicateBuilder.endsWith(leftExp, 
rightExp)));
         }
 
         throw new SimpleParserException("Unknown binary operator " + operator, 
token.getIndex());
@@ -351,8 +357,12 @@ public class BinaryExpression extends BaseSimpleNode {
             return "!range(exchange, " + leftExp + ", " + rightExp + ")";
         } else if (operator == BinaryOperatorType.STARTS_WITH) {
             return "startsWith(exchange, " + leftExp + ", " + rightExp + ")";
+        } else if (operator == BinaryOperatorType.NOT_STARTS_WITH) {
+            return "!startsWith(exchange, " + leftExp + ", " + rightExp + ")";
         } else if (operator == BinaryOperatorType.ENDS_WITH) {
             return "endsWith(exchange, " + leftExp + ", " + rightExp + ")";
+        } else if (operator == BinaryOperatorType.NOT_ENDS_WITH) {
+            return "!endsWith(exchange, " + leftExp + ", " + rightExp + ")";
         }
 
         throw new SimpleParserException("Unknown binary operator " + operator, 
token.getIndex());
diff --git 
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/types/BinaryOperatorType.java
 
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/types/BinaryOperatorType.java
index c0b8dca08267..fb82fc584a0e 100644
--- 
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/types/BinaryOperatorType.java
+++ 
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/types/BinaryOperatorType.java
@@ -45,7 +45,9 @@ public enum BinaryOperatorType {
     RANGE,
     NOT_RANGE,
     STARTS_WITH,
-    ENDS_WITH;
+    NOT_STARTS_WITH,
+    ENDS_WITH,
+    NOT_ENDS_WITH;
 
     private static final Logger LOG = 
LoggerFactory.getLogger(BinaryOperatorType.class);
 
@@ -115,6 +117,10 @@ public enum BinaryOperatorType {
         } else if ("ends with".equals(text)) {
             LOG.warn("Simple operator `ends with` is deprecated, use 
`endsWith` instead");
             return ENDS_WITH;
+        } else if ("!startsWith".equals(text)) {
+            return NOT_STARTS_WITH;
+        } else if ("!endsWith".equals(text)) {
+            return NOT_ENDS_WITH;
         }
         throw new IllegalArgumentException("Operator not supported: " + text);
     }
@@ -162,8 +168,12 @@ public enum BinaryOperatorType {
             return "!range";
         } else if (operator == STARTS_WITH) {
             return "startsWith";
+        } else if (operator == NOT_STARTS_WITH) {
+            return "!startsWith";
         } else if (operator == ENDS_WITH) {
             return "endsWith";
+        } else if (operator == NOT_ENDS_WITH) {
+            return "!endsWith";
         }
         return "";
     }
@@ -264,9 +274,9 @@ public enum BinaryOperatorType {
             return new ParameterType[] { ParameterType.LiteralWithFunction, 
ParameterType.Function };
         } else if (operator == NOT_RANGE) {
             return new ParameterType[] { ParameterType.LiteralWithFunction, 
ParameterType.Function };
-        } else if (operator == STARTS_WITH) {
+        } else if (operator == STARTS_WITH || operator == NOT_STARTS_WITH) {
             return null;
-        } else if (operator == ENDS_WITH) {
+        } else if (operator == ENDS_WITH || operator == NOT_ENDS_WITH) {
             return null;
         }
         return null;
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleOperatorTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleOperatorTest.java
index b0973f552e87..8360f656447e 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleOperatorTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleOperatorTest.java
@@ -783,6 +783,20 @@ public class SimpleOperatorTest extends 
LanguageTestSupport {
         assertPredicate("${in.body} starts with 01234", false);
     }
 
+    @Test
+    public void testNotStartsWith() {
+        exchange.getIn().setBody("Hello there");
+        assertPredicate("${in.body} !startsWith 'Bye'", true);
+        assertPredicate("${in.body} !startsWith 'Hello'", false);
+        assertPredicate("${in.body} !startsWith 'B'", true);
+        assertPredicate("${in.body} !startsWith 'H'", false);
+        assertPredicate("${in.body} !startsWith 'Bye there'", true);
+        assertPredicate("${in.body} !startsWith 'Hello there'", false);
+        assertPredicate("${in.body} !startsWith 'Hello ther'", false);
+        assertPredicate("${in.body} !startsWith 'ello there'", true);
+        assertPredicate("${in.body} !startsWith 'Hi'", true);
+    }
+
     @Test
     public void testEndsWith() {
         exchange.getIn().setBody("Hello there");
@@ -800,6 +814,19 @@ public class SimpleOperatorTest extends 
LanguageTestSupport {
         assertPredicate("${in.body} endsWith 'Hi'", false);
     }
 
+    @Test
+    public void testNotEndsWith() {
+        exchange.getIn().setBody("Hello there");
+        assertPredicate("${in.body} !endsWith 'B'", true);
+        assertPredicate("${in.body} !endsWith 'world'", true);
+        assertPredicate("${in.body} !endsWith 'there'", false);
+        assertPredicate("${in.body} !endsWith 're'", false);
+        assertPredicate("${in.body} !endsWith ' there'", false);
+        assertPredicate("${in.body} !endsWith 'Hello there'", false);
+        assertPredicate("${in.body} !endsWith 'Hello ther'", true);
+        assertPredicate("${in.body} !endsWith 'Hi'", true);
+    }
+
     @Override
     protected String getLanguageName() {
         return "simple";

Reply via email to