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 bd4549977db6 CAMEL-22894: Extract Simple functions into dedicated
factories
bd4549977db6 is described below
commit bd4549977db65dc4cb928e7cce978eef2dce6e41
Author: Adriano Machado <[email protected]>
AuthorDate: Wed May 27 02:12:16 2026 -0400
CAMEL-22894: Extract Simple functions into dedicated factories
Extract six more function families from the monolithic
SimpleFunctionExpression into dedicated SimpleLanguageFunctionFactory
implementations: SystemFunctionFactory (sys/env), DateFunctionFactory,
PropertiesFunctionFactory (properties/ref), TypeFunctionFactory,
MessageFunctionFactory, and OutputFunctionFactory (pretty/toJson).
Remove unused deprecated tryCreate() and tryCreateCode() methods.
Tests moved to per-factory test classes.
Closes #23544
---
.../language/simple/SimpleFunctionDispatcher.java | 40 +--
.../simple/ast/SimpleFunctionExpression.java | 239 ------------------
.../simple/functions/DateFunctionFactory.java | 87 +++++++
.../simple/functions/MessageFunctionFactory.java | 58 +++++
.../simple/functions/OutputFunctionFactory.java | 71 ++++++
.../functions/PropertiesFunctionFactory.java | 85 +++++++
.../simple/functions/SystemFunctionFactory.java | 80 ++++++
.../simple/functions/TypeFunctionFactory.java | 64 +++++
core/camel-core/pom.xml | 6 +
.../apache/camel/language/simple/SimpleTest.java | 267 ---------------------
.../simple/functions/DateFunctionFactoryTest.java | 158 ++++++++++++
.../functions/MessageFunctionFactoryTest.java | 58 +++++
.../functions/OutputFunctionFactoryTest.java | 88 +++++++
.../functions/PropertiesFunctionFactoryTest.java | 95 ++++++++
.../functions/SystemFunctionFactoryTest.java | 105 ++++++++
.../simple/functions/TypeFunctionFactoryTest.java | 73 ++++++
16 files changed, 1041 insertions(+), 533 deletions(-)
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleFunctionDispatcher.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleFunctionDispatcher.java
index 2080ac72c648..3f5c2256a6a4 100644
---
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleFunctionDispatcher.java
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleFunctionDispatcher.java
@@ -24,13 +24,19 @@ import org.apache.camel.Expression;
import org.apache.camel.language.simple.functions.BodyFunctionFactory;
import org.apache.camel.language.simple.functions.CollateFunctionFactory;
import org.apache.camel.language.simple.functions.CollectionFunctionFactory;
+import org.apache.camel.language.simple.functions.DateFunctionFactory;
import org.apache.camel.language.simple.functions.HeaderFunctionFactory;
import org.apache.camel.language.simple.functions.JoinFunctionFactory;
import org.apache.camel.language.simple.functions.MathFunctionFactory;
+import org.apache.camel.language.simple.functions.MessageFunctionFactory;
import org.apache.camel.language.simple.functions.MiscFunctionFactory;
+import org.apache.camel.language.simple.functions.OutputFunctionFactory;
+import org.apache.camel.language.simple.functions.PropertiesFunctionFactory;
import org.apache.camel.language.simple.functions.RandomFunctionFactory;
import org.apache.camel.language.simple.functions.SkipFunctionFactory;
import org.apache.camel.language.simple.functions.StringFunctionFactory;
+import org.apache.camel.language.simple.functions.SystemFunctionFactory;
+import org.apache.camel.language.simple.functions.TypeFunctionFactory;
import org.apache.camel.language.simple.functions.VariableFunctionFactory;
import org.apache.camel.spi.SimpleLanguageFunctionFactory;
import org.apache.camel.support.ResolverHelper;
@@ -65,7 +71,13 @@ public final class SimpleFunctionDispatcher {
new MathFunctionFactory(),
new StringFunctionFactory(),
new CollectionFunctionFactory(),
- new MiscFunctionFactory());
+ new MiscFunctionFactory(),
+ new SystemFunctionFactory(),
+ new PropertiesFunctionFactory(),
+ new TypeFunctionFactory(),
+ new DateFunctionFactory(),
+ new MessageFunctionFactory(),
+ new OutputFunctionFactory());
private static final List<Entry> EXPRESSION_ENTRIES = List.of(
new Entry("camel-attachments",
SimpleFunctionDispatcher::isAttachmentFunction),
@@ -83,19 +95,6 @@ public final class SimpleFunctionDispatcher {
private SimpleFunctionDispatcher() {
}
- /**
- * Migrated as-is from main; not currently called. Candidate for removal
once all Simple functions are extracted
- * into dedicated {@link SimpleLanguageFunctionFactory} implementations
(CAMEL-22894).
- */
- @Deprecated(forRemoval = true)
- public static Expression tryCreate(CamelContext camelContext, String
function, int index) {
- Expression answer = tryCreateBuiltIn(camelContext, function, index);
- if (answer != null) {
- return answer;
- }
- return tryCreateExternal(camelContext, function, index);
- }
-
public static Expression tryCreateBuiltIn(CamelContext camelContext,
String function, int index) {
for (SimpleLanguageFunctionFactory factory : BUILT_INS) {
Expression answer = factory.createFunction(camelContext, function,
index);
@@ -120,19 +119,6 @@ public final class SimpleFunctionDispatcher {
return null;
}
- /**
- * Migrated as-is from main; not currently called. Candidate for removal
once all Simple functions are extracted
- * into dedicated {@link SimpleLanguageFunctionFactory} implementations
(CAMEL-22894).
- */
- @Deprecated(forRemoval = true)
- public static String tryCreateCode(CamelContext camelContext, String
function, int index) {
- String code = tryCreateCodeBuiltIn(camelContext, function, index);
- if (code != null) {
- return code;
- }
- return tryCreateCodeExternal(camelContext, function, index);
- }
-
public static String tryCreateCodeBuiltIn(CamelContext camelContext,
String function, int index) {
for (SimpleLanguageFunctionFactory factory : BUILT_INS) {
@SuppressWarnings("deprecation")
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
index 5708f1850500..408897ceff38 100644
---
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
@@ -112,12 +112,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return answer;
}
- // message first
- answer = createSimpleExpressionMessage(camelContext, function, strict);
- if (answer != null) {
- return answer;
- }
-
// custom functions
answer = createSimpleCustomFunction(camelContext, function, strict);
if (answer != null) {
@@ -177,25 +171,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
}
}
- // system property
- remainder = ifStartsWithReturnRemainder("sys.", function);
- if (remainder != null) {
- return ExpressionBuilder.systemPropertyExpression(remainder);
- }
- remainder = ifStartsWithReturnRemainder("sysenv.", function);
- if (remainder == null) {
- remainder = ifStartsWithReturnRemainder("sysenv:", function);
- }
- if (remainder == null) {
- remainder = ifStartsWithReturnRemainder("env.", function);
- }
- if (remainder == null) {
- remainder = ifStartsWithReturnRemainder("env:", function);
- }
- if (remainder != null) {
- return ExpressionBuilder.systemEnvironmentExpression(remainder);
- }
-
// exchange OGNL
remainder = ifStartsWithReturnRemainder("exchange", function);
if (remainder != null) {
@@ -206,41 +181,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return SimpleExpressionBuilder.exchangeOgnlExpression(remainder);
}
- // pretty
- remainder = ifStartsWithReturnRemainder("pretty(", function);
- if (remainder != null) {
- String exp = StringHelper.beforeLast(remainder, ")");
- if (exp == null) {
- throw new SimpleParserException("Valid syntax: ${pretty(exp)}
was: " + function, token.getIndex());
- }
- exp = StringHelper.removeLeadingAndEndingQuotes(exp);
- Expression inlined =
camelContext.resolveLanguage("simple").createExpression(exp);
- return ExpressionBuilder.prettyExpression(inlined);
- }
-
- // toJson
- remainder = ifStartsWithReturnRemainder("toJson(", function);
- if (remainder != null) {
- String exp = StringHelper.beforeLast(remainder, ")");
- if (exp == null) {
- throw new SimpleParserException("Valid syntax: ${toJson(exp)}
was: " + function, token.getIndex());
- }
- exp = StringHelper.removeLeadingAndEndingQuotes(exp);
- Expression inlined =
camelContext.resolveLanguage("simple").createExpression(exp);
- return ExpressionBuilder.toJsonExpression(inlined, false);
- }
- // toPrettyJson
- remainder = ifStartsWithReturnRemainder("toPrettyJson(", function);
- if (remainder != null) {
- String exp = StringHelper.beforeLast(remainder, ")");
- if (exp == null) {
- throw new SimpleParserException("Valid syntax:
${toPrettyJson(exp)} was: " + function, token.getIndex());
- }
- exp = StringHelper.removeLeadingAndEndingQuotes(exp);
- Expression inlined =
camelContext.resolveLanguage("simple").createExpression(exp);
- return ExpressionBuilder.toJsonExpression(inlined, true);
- }
-
// file: prefix
remainder = ifStartsWithReturnRemainder("file:", function);
if (remainder != null) {
@@ -256,28 +196,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
}
}
- // date: prefix
- remainder = ifStartsWithReturnRemainder("date:", function);
- if (remainder != null) {
- String[] parts = remainder.split(":", 2);
- if (parts.length == 1) {
- return SimpleExpressionBuilder.dateExpression(parts[0]);
- } else if (parts.length == 2) {
- return SimpleExpressionBuilder.dateExpression(parts[0],
parts[1]);
- }
- }
-
- // date-with-timezone: prefix
- remainder = ifStartsWithReturnRemainder("date-with-timezone:",
function);
- if (remainder != null) {
- String[] parts = remainder.split(":", 3);
- if (parts.length < 3) {
- throw new SimpleParserException(
- "Valid syntax:
${date-with-timezone:command:timezone:pattern} was: " + function,
token.getIndex());
- }
- return SimpleExpressionBuilder.dateExpression(parts[0], parts[1],
parts[2]);
- }
-
// bean: prefix
remainder = ifStartsWithReturnRemainder("bean:", function);
if (remainder != null) {
@@ -333,51 +251,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return bean.createExpression(null, properties);
}
- // properties-exist: prefix
- remainder = ifStartsWithReturnRemainder("propertiesExist:", function);
- if (remainder != null) {
- String[] parts = remainder.split(":", 2);
- if (parts.length > 2) {
- throw new SimpleParserException("Valid syntax:
${propertiesExist:key} was: " + function, token.getIndex());
- }
- String key = parts[0];
- boolean negate = key != null && key.startsWith("!");
- if (negate) {
- key = key.substring(1);
- }
- return ExpressionBuilder.propertiesComponentExist(key, negate);
- }
-
- // properties: prefix
- remainder = ifStartsWithReturnRemainder("properties:", function);
- if (remainder != null) {
- String[] parts = remainder.split(":", 2);
- if (parts.length > 2) {
- throw new SimpleParserException("Valid syntax:
${properties:key[:default]} was: " + function, token.getIndex());
- }
- String defaultValue = null;
- if (parts.length >= 2) {
- defaultValue = parts[1];
- }
- String key = parts[0];
- return ExpressionBuilder.propertiesComponentExpression(key,
defaultValue);
- }
-
- // ref: prefix
- remainder = ifStartsWithReturnRemainder("ref:", function);
- if (remainder != null) {
- return ExpressionBuilder.refExpression(remainder);
- }
-
- // type: prefix
- remainder = ifStartsWithReturnRemainder("type:", function);
- if (remainder != null) {
- Expression exp = SimpleExpressionBuilder.typeExpression(remainder);
- exp.init(camelContext);
- // we want to cache this expression, so we won't re-evaluate it as
the type/constant won't change
- return SimpleExpressionBuilder.cacheExpression(exp);
- }
-
// miscellaneous and other built-in functions
Expression builtIn =
SimpleFunctionDispatcher.tryCreateBuiltIn(camelContext, function,
token.getIndex());
if (builtIn != null) {
@@ -412,31 +285,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
}
}
- private Expression createSimpleExpressionMessage(CamelContext
camelContext, String function, boolean strict) {
- // messageAs
- String remainder = ifStartsWithReturnRemainder("messageAs(", function);
- if (remainder != null) {
- String type = StringHelper.before(remainder, ")");
- if (type == null) {
- throw new SimpleParserException("Valid syntax:
${messageAs(type)} was: " + function, token.getIndex());
- }
- type = StringHelper.removeQuotes(type);
- remainder = StringHelper.after(remainder, ")");
-
- if (ObjectHelper.isNotEmpty(remainder)) {
- boolean invalid =
OgnlHelper.isInvalidValidOgnlExpression(remainder);
- if (invalid) {
- throw new SimpleParserException("Valid syntax:
${messageAs(type).OGNL} was: " + function, token.getIndex());
- }
- return SimpleExpressionBuilder.messageOgnlExpression(type,
remainder);
- } else {
- return ExpressionBuilder.messageExpression(type);
- }
- }
-
- return null;
- }
-
private Expression createSimpleCustomFunction(CamelContext camelContext,
String function, boolean strict) {
String remainder = ifStartsWithReturnRemainder("function(", function);
if (remainder != null) {
@@ -657,25 +505,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return "exception(exchange)" + ognlCodeMethods(remainder, null);
}
- // system property
- remainder = ifStartsWithReturnRemainder("sys.", function);
- if (remainder != null) {
- return "sys(\"" + remainder + "\")";
- }
- remainder = ifStartsWithReturnRemainder("sysenv.", function);
- if (remainder == null) {
- remainder = ifStartsWithReturnRemainder("sysenv:", function);
- }
- if (remainder == null) {
- remainder = ifStartsWithReturnRemainder("env.", function);
- }
- if (remainder == null) {
- remainder = ifStartsWithReturnRemainder("env:", function);
- }
- if (remainder != null) {
- return "sysenv(\"" + remainder + "\")";
- }
-
// exchange OGNL
remainder = ifStartsWithReturnRemainder("exchange", function);
if (remainder != null) {
@@ -692,31 +521,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
return createCodeFileExpression(remainder);
}
- if ("date:millis".equals(function)) {
- return "System.currentTimeMillis()";
- }
- // date: prefix
- remainder = ifStartsWithReturnRemainder("date:", function);
- if (remainder != null) {
- String[] parts = remainder.split(":", 2);
- if (parts.length == 1) {
- return "date(exchange, \"" + parts[0] + "\")";
- } else if (parts.length == 2) {
- return "date(exchange, \"" + parts[0] + "\", null, \"" +
parts[1] + "\")";
- }
- }
-
- // date-with-timezone: prefix
- remainder = ifStartsWithReturnRemainder("date-with-timezone:",
function);
- if (remainder != null) {
- String[] parts = remainder.split(":", 3);
- if (parts.length < 3) {
- throw new SimpleParserException(
- "Valid syntax:
${date-with-timezone:command:timezone:pattern} was: " + function,
token.getIndex());
- }
- return "date(exchange, \"" + parts[0] + "\", \"" + parts[1] + "\",
\"" + parts[2] + "\")";
- }
-
// bean: prefix
remainder = ifStartsWithReturnRemainder("bean:", function);
if (remainder != null) {
@@ -761,49 +565,6 @@ public class SimpleFunctionExpression extends
LiteralExpression {
}
}
- // properties: prefix
- remainder = ifStartsWithReturnRemainder("properties:", function);
- if (remainder != null) {
- String[] parts = remainder.split(":", 2);
- if (parts.length > 2) {
- throw new SimpleParserException("Valid syntax:
${properties:key[:default]} was: " + function, token.getIndex());
- }
- String defaultValue = null;
- if (parts.length >= 2) {
- defaultValue = parts[1];
- }
- String key = parts[0];
- key = key.trim();
- if (defaultValue != null) {
- return "properties(exchange, \"" + key + "\", \"" +
defaultValue.trim() + "\")";
- } else {
- return "properties(exchange, \"" + key + "\")";
- }
- }
-
- // ref: prefix
- remainder = ifStartsWithReturnRemainder("ref:", function);
- if (remainder != null) {
- return "ref(exchange, \"" + remainder + "\")";
- }
-
- // type: prefix
- remainder = ifStartsWithReturnRemainder("type:", function);
- if (remainder != null) {
- int pos = remainder.lastIndexOf('.');
- String type = pos != -1 ? remainder.substring(0, pos) : remainder;
- String field = pos != -1 ? remainder.substring(pos + 1) : null;
- if (!type.endsWith(".class")) {
- type += ".class";
- }
- type = type.replace('$', '.');
- if (field != null) {
- return "type(exchange, " + type + ", \"" + field + "\")";
- } else {
- return "type(exchange, " + type + ")";
- }
- }
-
// miscellaneous and other built-in functions
String builtIn =
SimpleFunctionDispatcher.tryCreateCodeBuiltIn(camelContext, function,
token.getIndex());
if (builtIn != null) {
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/DateFunctionFactory.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/DateFunctionFactory.java
new file mode 100644
index 000000000000..25a41f131a67
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/DateFunctionFactory.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleExpressionBuilder;
+import org.apache.camel.language.simple.types.SimpleParserException;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+
+import static
org.apache.camel.language.simple.SimpleFunctionHelper.ifStartsWithReturnRemainder;
+
+/**
+ * Built-in Simple functions for date/time: {@code ${date:command}}, {@code
${date:command:pattern}},
+ * {@code ${date-with-timezone:command:timezone:pattern}}.
+ */
+public final class DateFunctionFactory implements
SimpleLanguageFunctionFactory {
+
+ @Override
+ public Expression createFunction(CamelContext camelContext, String
function, int index) {
+ String remainder = ifStartsWithReturnRemainder("date-with-timezone:",
function);
+ if (remainder != null) {
+ String[] parts = remainder.split(":", 3);
+ if (parts.length < 3) {
+ throw new SimpleParserException(
+ "Valid syntax:
${date-with-timezone:command:timezone:pattern} was: " + function, index);
+ }
+ return SimpleExpressionBuilder.dateExpression(parts[0], parts[1],
parts[2]);
+ }
+
+ remainder = ifStartsWithReturnRemainder("date:", function);
+ if (remainder != null) {
+ String[] parts = remainder.split(":", 2);
+ if (parts.length == 1) {
+ return SimpleExpressionBuilder.dateExpression(parts[0]);
+ } else {
+ return SimpleExpressionBuilder.dateExpression(parts[0],
parts[1]);
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public String createCode(CamelContext camelContext, String function, int
index) {
+ if ("date:millis".equals(function)) {
+ return "System.currentTimeMillis()";
+ }
+
+ String remainder = ifStartsWithReturnRemainder("date-with-timezone:",
function);
+ if (remainder != null) {
+ String[] parts = remainder.split(":", 3);
+ if (parts.length < 3) {
+ throw new SimpleParserException(
+ "Valid syntax:
${date-with-timezone:command:timezone:pattern} was: " + function, index);
+ }
+ return "date(exchange, \"" + parts[0] + "\", \"" + parts[1] + "\",
\"" + parts[2] + "\")";
+ }
+
+ remainder = ifStartsWithReturnRemainder("date:", function);
+ if (remainder != null) {
+ String[] parts = remainder.split(":", 2);
+ if (parts.length == 1) {
+ return "date(exchange, \"" + parts[0] + "\")";
+ } else {
+ return "date(exchange, \"" + parts[0] + "\", null, \"" +
parts[1] + "\")";
+ }
+ }
+
+ return null;
+ }
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/MessageFunctionFactory.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/MessageFunctionFactory.java
new file mode 100644
index 000000000000..9d6c0ff6e7cd
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/MessageFunctionFactory.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleExpressionBuilder;
+import org.apache.camel.language.simple.types.SimpleParserException;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.support.builder.ExpressionBuilder;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.OgnlHelper;
+import org.apache.camel.util.StringHelper;
+
+import static
org.apache.camel.language.simple.SimpleFunctionHelper.ifStartsWithReturnRemainder;
+
+/**
+ * Built-in Simple function for typed message access: {@code
${messageAs(type)}}, {@code ${messageAs(type).OGNL}}.
+ */
+public final class MessageFunctionFactory implements
SimpleLanguageFunctionFactory {
+
+ @Override
+ public Expression createFunction(CamelContext camelContext, String
function, int index) {
+ String remainder = ifStartsWithReturnRemainder("messageAs(", function);
+ if (remainder != null) {
+ String type = StringHelper.before(remainder, ")");
+ if (type == null) {
+ throw new SimpleParserException("Valid syntax:
${messageAs(type)} was: " + function, index);
+ }
+ type = StringHelper.removeQuotes(type);
+ remainder = StringHelper.after(remainder, ")");
+ if (ObjectHelper.isNotEmpty(remainder)) {
+ boolean invalid =
OgnlHelper.isInvalidValidOgnlExpression(remainder);
+ if (invalid) {
+ throw new SimpleParserException("Valid syntax:
${messageAs(type).OGNL} was: " + function, index);
+ }
+ return SimpleExpressionBuilder.messageOgnlExpression(type,
remainder);
+ } else {
+ return ExpressionBuilder.messageExpression(type);
+ }
+ }
+ return null;
+ }
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/OutputFunctionFactory.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/OutputFunctionFactory.java
new file mode 100644
index 000000000000..6f3d59b6b1e7
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/OutputFunctionFactory.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.types.SimpleParserException;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.support.builder.ExpressionBuilder;
+import org.apache.camel.util.StringHelper;
+
+import static
org.apache.camel.language.simple.SimpleFunctionHelper.ifStartsWithReturnRemainder;
+
+/**
+ * Built-in Simple functions for formatted output: {@code ${pretty(exp)}},
{@code ${toJson(exp)}},
+ * {@code ${toPrettyJson(exp)}}.
+ */
+public final class OutputFunctionFactory implements
SimpleLanguageFunctionFactory {
+
+ @Override
+ public Expression createFunction(CamelContext camelContext, String
function, int index) {
+ String remainder = ifStartsWithReturnRemainder("pretty(", function);
+ if (remainder != null) {
+ String exp = StringHelper.beforeLast(remainder, ")");
+ if (exp == null) {
+ throw new SimpleParserException("Valid syntax: ${pretty(exp)}
was: " + function, index);
+ }
+ exp = StringHelper.removeLeadingAndEndingQuotes(exp);
+ Expression inlined =
camelContext.resolveLanguage("simple").createExpression(exp);
+ return ExpressionBuilder.prettyExpression(inlined);
+ }
+
+ remainder = ifStartsWithReturnRemainder("toPrettyJson(", function);
+ if (remainder != null) {
+ String exp = StringHelper.beforeLast(remainder, ")");
+ if (exp == null) {
+ throw new SimpleParserException("Valid syntax:
${toPrettyJson(exp)} was: " + function, index);
+ }
+ exp = StringHelper.removeLeadingAndEndingQuotes(exp);
+ Expression inlined =
camelContext.resolveLanguage("simple").createExpression(exp);
+ return ExpressionBuilder.toJsonExpression(inlined, true);
+ }
+
+ remainder = ifStartsWithReturnRemainder("toJson(", function);
+ if (remainder != null) {
+ String exp = StringHelper.beforeLast(remainder, ")");
+ if (exp == null) {
+ throw new SimpleParserException("Valid syntax: ${toJson(exp)}
was: " + function, index);
+ }
+ exp = StringHelper.removeLeadingAndEndingQuotes(exp);
+ Expression inlined =
camelContext.resolveLanguage("simple").createExpression(exp);
+ return ExpressionBuilder.toJsonExpression(inlined, false);
+ }
+
+ return null;
+ }
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/PropertiesFunctionFactory.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/PropertiesFunctionFactory.java
new file mode 100644
index 000000000000..ccbff2b776ce
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/PropertiesFunctionFactory.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.types.SimpleParserException;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.support.builder.ExpressionBuilder;
+
+import static
org.apache.camel.language.simple.SimpleFunctionHelper.ifStartsWithReturnRemainder;
+
+/**
+ * Built-in Simple functions for properties component and registry references:
{@code ${propertiesExist:key}},
+ * {@code ${propertiesExist:!key}}, {@code ${properties:key}}, {@code
${properties:key:default}}, {@code ${ref:name}}.
+ */
+public final class PropertiesFunctionFactory implements
SimpleLanguageFunctionFactory {
+
+ @Override
+ public Expression createFunction(CamelContext camelContext, String
function, int index) {
+ String remainder = ifStartsWithReturnRemainder("propertiesExist:",
function);
+ if (remainder != null) {
+ String[] parts = remainder.split(":", 2);
+ String key = parts[0];
+ boolean negate = key != null && key.startsWith("!");
+ if (negate) {
+ key = key.substring(1);
+ }
+ return ExpressionBuilder.propertiesComponentExist(key, negate);
+ }
+
+ remainder = ifStartsWithReturnRemainder("properties:", function);
+ if (remainder != null) {
+ String[] parts = remainder.split(":", 2);
+ String defaultValue = parts.length >= 2 ? parts[1] : null;
+ return ExpressionBuilder.propertiesComponentExpression(parts[0],
defaultValue);
+ }
+
+ remainder = ifStartsWithReturnRemainder("ref:", function);
+ if (remainder != null) {
+ return ExpressionBuilder.refExpression(remainder);
+ }
+
+ return null;
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public String createCode(CamelContext camelContext, String function, int
index) {
+ String remainder = ifStartsWithReturnRemainder("properties:",
function);
+ if (remainder != null) {
+ String[] parts = remainder.split(":", 2);
+ if (parts.length > 2) {
+ throw new SimpleParserException("Valid syntax:
${properties:key[:default]} was: " + function, index);
+ }
+ String key = parts[0].trim();
+ if (parts.length >= 2) {
+ return "properties(exchange, \"" + key + "\", \"" +
parts[1].trim() + "\")";
+ } else {
+ return "properties(exchange, \"" + key + "\")";
+ }
+ }
+
+ remainder = ifStartsWithReturnRemainder("ref:", function);
+ if (remainder != null) {
+ return "ref(exchange, \"" + remainder + "\")";
+ }
+
+ return null;
+ }
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/SystemFunctionFactory.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/SystemFunctionFactory.java
new file mode 100644
index 000000000000..afd634d58347
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/SystemFunctionFactory.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.support.builder.ExpressionBuilder;
+
+import static
org.apache.camel.language.simple.SimpleFunctionHelper.ifStartsWithReturnRemainder;
+
+/**
+ * Built-in Simple functions for system properties and environment variables:
{@code ${sys.name}},
+ * {@code ${sysenv.name}}, {@code ${sysenv:name}}, {@code ${env.name}}, {@code
${env:name}}.
+ */
+public final class SystemFunctionFactory implements
SimpleLanguageFunctionFactory {
+
+ @Override
+ public Expression createFunction(CamelContext camelContext, String
function, int index) {
+ String remainder = ifStartsWithReturnRemainder("sys.", function);
+ if (remainder != null) {
+ return ExpressionBuilder.systemPropertyExpression(remainder);
+ }
+
+ remainder = ifStartsWithReturnRemainder("sysenv.", function);
+ if (remainder == null) {
+ remainder = ifStartsWithReturnRemainder("sysenv:", function);
+ }
+ if (remainder == null) {
+ remainder = ifStartsWithReturnRemainder("env.", function);
+ }
+ if (remainder == null) {
+ remainder = ifStartsWithReturnRemainder("env:", function);
+ }
+ if (remainder != null) {
+ return ExpressionBuilder.systemEnvironmentExpression(remainder);
+ }
+
+ return null;
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public String createCode(CamelContext camelContext, String function, int
index) {
+ String remainder = ifStartsWithReturnRemainder("sys.", function);
+ if (remainder != null) {
+ return "sys(\"" + remainder + "\")";
+ }
+
+ remainder = ifStartsWithReturnRemainder("sysenv.", function);
+ if (remainder == null) {
+ remainder = ifStartsWithReturnRemainder("sysenv:", function);
+ }
+ if (remainder == null) {
+ remainder = ifStartsWithReturnRemainder("env.", function);
+ }
+ if (remainder == null) {
+ remainder = ifStartsWithReturnRemainder("env:", function);
+ }
+ if (remainder != null) {
+ return "sysenv(\"" + remainder + "\")";
+ }
+
+ return null;
+ }
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/TypeFunctionFactory.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/TypeFunctionFactory.java
new file mode 100644
index 000000000000..09151c9f63a1
--- /dev/null
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/TypeFunctionFactory.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.SimpleExpressionBuilder;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+
+import static
org.apache.camel.language.simple.SimpleFunctionHelper.appendClass;
+import static
org.apache.camel.language.simple.SimpleFunctionHelper.ifStartsWithReturnRemainder;
+
+/**
+ * Built-in Simple function for type literal access: {@code ${type:fqn}},
{@code ${type:fqn.FIELD}}.
+ *
+ * <p>
+ * The expression is eagerly initialized and cached because type references
are constant.
+ */
+public final class TypeFunctionFactory implements
SimpleLanguageFunctionFactory {
+
+ @Override
+ public Expression createFunction(CamelContext camelContext, String
function, int index) {
+ String remainder = ifStartsWithReturnRemainder("type:", function);
+ if (remainder != null) {
+ Expression exp = SimpleExpressionBuilder.typeExpression(remainder);
+ exp.init(camelContext);
+ return SimpleExpressionBuilder.cacheExpression(exp);
+ }
+ return null;
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public String createCode(CamelContext camelContext, String function, int
index) {
+ String remainder = ifStartsWithReturnRemainder("type:", function);
+ if (remainder != null) {
+ int pos = remainder.lastIndexOf('.');
+ String type = pos != -1 ? remainder.substring(0, pos) : remainder;
+ String field = pos != -1 ? remainder.substring(pos + 1) : null;
+ type = appendClass(type);
+ type = type.replace('$', '.');
+ if (field != null) {
+ return "type(exchange, " + type + ", \"" + field + "\")";
+ } else {
+ return "type(exchange, " + type + ")";
+ }
+ }
+ return null;
+ }
+}
diff --git a/core/camel-core/pom.xml b/core/camel-core/pom.xml
index 2b0148d43e0d..7f5e87177061 100644
--- a/core/camel-core/pom.xml
+++ b/core/camel-core/pom.xml
@@ -250,6 +250,12 @@
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit-pioneer</groupId>
+ <artifactId>junit-pioneer</artifactId>
+ <version>${junit-pioneer-version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
index 7255773cf3f2..5f55e5515849 100644
---
a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
@@ -22,7 +22,6 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.ArrayList;
-import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@@ -30,12 +29,10 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.TimeZone;
import org.apache.camel.CamelAuthorizationException;
import org.apache.camel.CamelExecutionException;
import org.apache.camel.Exchange;
-import org.apache.camel.ExchangePattern;
import org.apache.camel.Expression;
import org.apache.camel.ExpressionIllegalSyntaxException;
import org.apache.camel.InvalidPayloadException;
@@ -45,11 +42,9 @@ import org.apache.camel.StreamCache;
import org.apache.camel.component.bean.MethodNotFoundException;
import org.apache.camel.converter.stream.FileInputStreamCache;
import org.apache.camel.language.bean.RuntimeBeanExpressionException;
-import org.apache.camel.language.simple.myconverter.MyCustomDate;
import org.apache.camel.language.simple.types.SimpleIllegalSyntaxException;
import org.apache.camel.spi.ExchangeFormatter;
import org.apache.camel.spi.Language;
-import org.apache.camel.spi.PropertiesComponent;
import org.apache.camel.spi.Registry;
import org.apache.camel.spi.UuidGenerator;
import org.apache.camel.spi.VariableRepository;
@@ -61,10 +56,7 @@ import org.apache.camel.util.InetAddressUtil;
import org.apache.camel.util.StringHelper;
import org.apache.camel.util.json.JsonArray;
import org.apache.camel.util.json.JsonObject;
-import org.apache.camel.util.json.Jsoner;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.parallel.ResourceLock;
-import org.junit.jupiter.api.parallel.Resources;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -148,16 +140,6 @@ public class SimpleTest extends LanguageTestSupport {
assertNull(context.resolveLanguage("simple").createExpression("${header.unknown}").evaluate(exchange,
String.class));
}
- @Test
- public void testRefExpression() {
- assertExpressionResultInstanceOf("${ref:myAnimal}", Animal.class);
-
- assertExpression("${ref:myAnimal}", "Donkey");
- assertExpression("${ref:unknown}", null);
- assertExpression("Hello ${ref:myAnimal}", "Hello Donkey");
- assertExpression("Hello ${ref:unknown}", "Hello ");
- }
-
@Test
public void testConstantExpression() {
assertExpression("Hello World", "Hello World");
@@ -333,46 +315,6 @@ public class SimpleTest extends LanguageTestSupport {
assertExpression("${exchangeProperty:medal}", "gold");
}
- @Test
- @ResourceLock(Resources.SYSTEM_PROPERTIES)
- public void testSimpleSystemPropertyExpressions() {
- System.setProperty("who", "I was here");
- assertExpression("${sys.who}", "I was here");
- }
-
- @Test
- public void testSimpleSystemEnvironmentExpressions() {
- String path = System.getenv("PATH");
- if (path != null) {
- assertExpression("${sysenv.PATH}", path);
- assertExpression("${sysenv:PATH}", path);
- assertExpression("${env.PATH}", path);
- assertExpression("${env:PATH}", path);
- }
- }
-
- @Test
- public void testSimpleSystemEnvironmentExpressionsIfDash() {
- String foo = System.getenv("FOO_SERVICE_HOST");
- if (foo != null) {
- assertExpression("${sysenv.FOO-SERVICE-HOST}", foo);
- assertExpression("${sysenv:FOO-SERVICE-HOST}", foo);
- assertExpression("${env.FOO-SERVICE-HOST}", foo);
- assertExpression("${env:FOO-SERVICE-HOST}", foo);
- }
- }
-
- @Test
- public void testSimpleSystemEnvironmentExpressionsIfLowercase() {
- String path = System.getenv("PATH");
- if (path != null) {
- assertExpression("${sysenv.path}", path);
- assertExpression("${sysenv:path}", path);
- assertExpression("${env.path}", path);
- assertExpression("${env:path}", path);
- }
- }
-
@Test
public void testSimpleCamelId() {
assertExpression("${camelId}", context.getName());
@@ -622,108 +564,6 @@ public class SimpleTest extends LanguageTestSupport {
assertPredicate("${header.beer.trim()} == \"\"", true);
}
- @Test
- public void testDateExpressions() {
- Calendar inHeaderCalendar = Calendar.getInstance();
- inHeaderCalendar.set(1974, Calendar.APRIL, 20);
- exchange.getIn().setHeader("birthday", inHeaderCalendar.getTime());
-
- Calendar propertyCalendar = Calendar.getInstance();
- propertyCalendar.set(1976, Calendar.JUNE, 22);
- exchange.setProperty("birthday", propertyCalendar.getTime());
-
- assertExpression("${date:header.birthday}",
inHeaderCalendar.getTime());
- assertExpression("${date:header.birthday:yyyyMMdd}", "19740420");
- assertExpression("${date:header.birthday+24h:yyyyMMdd}", "19740421");
-
- // long
- assertExpression("${date:exchangeProperty.birthday}",
propertyCalendar.getTime().getTime());
- // date
- assertExpression("${date:exchangeProperty.birthday}",
propertyCalendar.getTime());
- assertExpression("${date:exchangeProperty.birthday:yyyyMMdd}",
"19760622");
- assertExpression("${date:exchangeProperty.birthday+24h:yyyyMMdd}",
"19760623");
-
- IllegalArgumentException e =
assertThrows(IllegalArgumentException.class,
- () -> assertExpression("${date:yyyyMMdd}", "19740420"),
- "Should thrown an exception");
-
- assertEquals("Command not supported for dateExpression: yyyyMMdd",
e.getMessage());
- }
-
- @Test
- public void testDateAndTimeExpressions() {
- Calendar cal = Calendar.getInstance();
- cal.set(1974, Calendar.APRIL, 20, 8, 55, 47);
- cal.set(Calendar.MILLISECOND, 123);
- exchange.getIn().setHeader("birthday", cal.getTime());
-
- assertExpression("${date:header.birthday -
10s:yyyy-MM-dd'T'HH:mm:ss:SSS}", "1974-04-20T08:55:37:123");
- assertExpression("${date:header.birthday:yyyy-MM-dd'T'HH:mm:ss:SSS}",
"1974-04-20T08:55:47:123");
- }
-
- @Test
- public void testDateWithConverterExpressions() {
- exchange.getIn().setHeader("birthday", new MyCustomDate(1974,
Calendar.APRIL, 20));
- exchange.setProperty("birthday", new MyCustomDate(1974,
Calendar.APRIL, 20));
- exchange.getIn().setHeader("other", new ArrayList<>());
-
- assertExpression("${date:header.birthday:yyyyMMdd}", "19740420");
- assertExpression("${date:exchangeProperty.birthday:yyyyMMdd}",
"19740420");
-
- IllegalArgumentException e =
assertThrows(IllegalArgumentException.class,
- () -> assertExpression("${date:header.other:yyyyMMdd}",
"19740420"),
- "Should thrown an exception");
-
- assertEquals("Cannot find Date/long object at command: header.other",
e.getMessage());
- }
-
- @Test
- public void testDateWithTimezone() {
- Calendar cal = Calendar.getInstance();
- cal.setTimeZone(TimeZone.getTimeZone("GMT+8"));
- cal.set(1974, Calendar.APRIL, 20, 8, 55, 47);
- cal.set(Calendar.MILLISECOND, 123);
- exchange.getIn().setHeader("birthday", cal.getTime());
-
-
assertExpression("${date-with-timezone:header.birthday:GMT+8:yyyy-MM-dd'T'HH:mm:ss:SSS}",
"1974-04-20T08:55:47:123");
-
assertExpression("${date-with-timezone:header.birthday:GMT:yyyy-MM-dd'T'HH:mm:ss:SSS}",
"1974-04-20T00:55:47:123");
- }
-
- @Test
- public void testDateNow() {
- Object out = evaluateExpression("${date:now}", null);
- assertNotNull(out);
- assertIsInstanceOf(Date.class, out);
-
- out = evaluateExpression("${date:now:hh:mm:ss a}", null);
- assertNotNull(out);
- out = evaluateExpression("${date:now:hh:mm:ss}", null);
- assertNotNull(out);
- out = evaluateExpression("${date:now-2h:hh:mm:ss}", null);
- assertNotNull(out);
- }
-
- @Test
- public void testDateMillis() {
- Object out = evaluateExpression("${date:millis}", null);
- assertNotNull(out);
- assertIsInstanceOf(Long.class, out);
- }
-
- @Test
- public void testDateExchangeCreated() {
- Object out
- = evaluateExpression("${date:exchangeCreated:hh:mm:ss a}", (""
+ exchange.getClock().getCreated()).getClass());
- assertNotNull(out);
- }
-
- @Test
- public void testDatePredicates() {
- assertPredicate("${date:now} < ${date:now+60s}");
- assertPredicate("${date:now-5s} < ${date:now}");
- assertPredicate("${date:now+5s} > ${date:now}");
- }
-
@Test
public void testLanguagesInContext() {
// evaluate so we know there is 1 language in the context
@@ -813,21 +653,6 @@ public class SimpleTest extends LanguageTestSupport {
assertEquals("Just testing", out.getMessage());
}
- @Test
- public void testMessageAs() {
- // should be false as message is default
-
assertPredicate("${messageAs(org.apache.camel.language.simple.MyAttachmentMessage).hasAttachments}",
false);
-
assertPredicate("${messageAs(org.apache.camel.language.simple.MyAttachmentMessage)?.hasAttachments}",
false);
-
- MyAttachmentMessage msg = new MyAttachmentMessage(exchange);
- msg.setBody("<hello id='m123'>world!</hello>");
- exchange.setMessage(msg);
-
-
assertPredicate("${messageAs(org.apache.camel.language.simple.MyAttachmentMessage).hasAttachments}",
true);
-
assertPredicate("${messageAs(org.apache.camel.language.simple.MyAttachmentMessage)?.hasAttachments}",
true);
-
assertExpression("${messageAs(org.apache.camel.language.simple.MyAttachmentMessage).size}",
"42");
- }
-
@Test
public void testBodyAs() {
assertExpression("${bodyAs(String)}", "<hello
id='m123'>world!</hello>");
@@ -1864,31 +1689,6 @@ public class SimpleTest extends LanguageTestSupport {
assertExpression("${camelContext.version}", context.getVersion());
}
- @Test
- public void testTypeConstant() {
- assertExpression("${type:org.apache.camel.Exchange.FILE_NAME}",
Exchange.FILE_NAME);
- assertExpression("${type:org.apache.camel.ExchangePattern.InOut}",
ExchangePattern.InOut);
-
- // non existing fields
- Exception e1 = assertThrows(Exception.class,
- () ->
assertExpression("${type:org.apache.camel.ExchangePattern.}", null),
- "Should throw exception");
-
- assertIsInstanceOf(ClassNotFoundException.class, e1.getCause());
-
- Exception e2 = assertThrows(Exception.class,
- () ->
assertExpression("${type:org.apache.camel.ExchangePattern.UNKNOWN}", null),
- "Should throw exception");
-
- assertIsInstanceOf(ClassNotFoundException.class, e2.getCause());
- }
-
- @Test
- public void testTypeConstantInnerClass() {
-
assertExpression("${type:org.apache.camel.language.simple.Constants$MyInnerStuff.FOO}",
123);
-
assertExpression("${type:org.apache.camel.language.simple.Constants.BAR}", 456);
- }
-
@Test
public void testStringArrayLength() {
exchange.getIn().setBody(new String[] { "foo", "bar" });
@@ -2345,22 +2145,6 @@ public class SimpleTest extends LanguageTestSupport {
assertExpression("${body.replace(\"((\", \"--\").replace(\"((((\",
\"----\")}", "Hello -- World ---- Again");
}
- @Test
- public void testPropertiesExist() {
- PropertiesComponent pc = context.getPropertiesComponent();
-
- assertExpression("${propertiesExist:myKey}", "false");
- assertExpression("${propertiesExist:!myKey}", "true");
- assertPredicate("${propertiesExist:myKey}", false);
- assertPredicate("${propertiesExist:!myKey}", true);
-
- pc.addInitialProperty("myKey", "abc");
- assertExpression("${propertiesExist:myKey}", "true");
- assertExpression("${propertiesExist:!myKey}", "false");
- assertPredicate("${propertiesExist:myKey}", true);
- assertPredicate("${propertiesExist:!myKey}", false);
- }
-
@Test
public void testUuid() {
Expression expression =
context.resolveLanguage("simple").createExpression("${uuid}");
@@ -3171,57 +2955,6 @@ public class SimpleTest extends LanguageTestSupport {
assertThrows(IllegalArgumentException.class, () ->
evaluateExpression("${newEmpty(unknownType)}", null));
}
- @Test
- public void testPretty() {
- assertExpression(exchange, "${pretty('Hello')}", "Hello");
- assertExpression(exchange, "${pretty(${body})}", "<hello
id=\"m123\">\n</hello>");
-
- exchange.getMessage().setBody("{\"name\": \"Jack\", \"id\": 123}");
- assertExpression(exchange, "${pretty(${body})}", "{\n\t\"name\":
\"Jack\",\n\t\"id\": 123\n}\n");
- }
-
- @Test
- public void testToJson() {
- // string body is returned as-is
- exchange.getMessage().setBody("Hello");
- assertExpression(exchange, "${toJson(${body})}", "Hello");
- assertExpression(exchange, "${toJsonBody}", "Hello");
-
- // map body is serialized to JSON
- Map<String, Object> map = new LinkedHashMap<>();
- map.put("name", "Jack");
- map.put("id", 123);
- exchange.getMessage().setBody(map);
- assertExpression(exchange, "${toJson(${body})}",
"{\"name\":\"Jack\",\"id\":123}");
- assertExpression(exchange, "${toJsonBody}",
"{\"name\":\"Jack\",\"id\":123}");
- // pretty mode
- String pretty = Jsoner.prettyPrint("{\"name\":\"Jack\",\"id\":123}");
- assertExpression(exchange, "${toPrettyJson(${body})}", pretty);
- assertExpression(exchange, "${toPrettyJsonBody}", pretty);
-
- // list body is serialized to JSON array
- exchange.getMessage().setBody(List.of("a", "b", "c"));
- assertExpression(exchange, "${toJson(${body})}",
"[\"a\",\"b\",\"c\"]");
- // pretty mode
- pretty = Jsoner.prettyPrint("[\"a\",\"b\",\"c\"]");
- assertExpression(exchange, "${toPrettyJson(${body})}", pretty);
- assertExpression(exchange, "${toPrettyJsonBody}", pretty);
-
- // null body
- exchange.getMessage().setBody(null);
- assertExpression(exchange, "${toJsonBody}", null);
- assertExpression(exchange, "${toJson(${body})}", null);
- // pretty mode
- assertExpression(exchange, "${toPrettyJsonBody}", null);
- assertExpression(exchange, "${toPrettyJson(${body})}", null);
-
- // toJson with a header expression
- exchange.getMessage().setHeader("myNum", 42);
- assertExpression(exchange, "${toJson(${header.myNum})}", "42");
- // pretty mode
- assertExpression(exchange, "${toPrettyJson(${header.myNum})}", "42");
- }
-
@Test
public void testTrimResult() {
exchange.getMessage().setBody("Camel ");
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/DateFunctionFactoryTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/DateFunctionFactoryTest.java
new file mode 100644
index 000000000000..9e79ab846e86
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/DateFunctionFactoryTest.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.apache.camel.language.simple.myconverter.MyCustomDate;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class DateFunctionFactoryTest extends
AbstractSimpleFunctionFactoryTestSupport {
+
+ @Override
+ protected SimpleLanguageFunctionFactory createFactory() {
+ return new DateFunctionFactory();
+ }
+
+ // --- date: ---
+
+ @Test
+ public void testDateExpressions() {
+ Calendar inHeaderCalendar = Calendar.getInstance();
+ inHeaderCalendar.set(1974, Calendar.APRIL, 20);
+ exchange.getIn().setHeader("birthday", inHeaderCalendar.getTime());
+
+ Calendar propertyCalendar = Calendar.getInstance();
+ propertyCalendar.set(1976, Calendar.JUNE, 22);
+ exchange.setProperty("birthday", propertyCalendar.getTime());
+
+ assertEquals(inHeaderCalendar.getTime(),
evaluate("date:header.birthday", Date.class));
+ assertEquals("19740420", evaluate("date:header.birthday:yyyyMMdd",
String.class));
+ assertEquals("19740421", evaluate("date:header.birthday+24h:yyyyMMdd",
String.class));
+
+ // as long
+ assertEquals(propertyCalendar.getTime().getTime(),
evaluate("date:exchangeProperty.birthday", Long.class));
+ // as date
+ assertEquals(propertyCalendar.getTime(),
evaluate("date:exchangeProperty.birthday", Date.class));
+ assertEquals("19760622",
evaluate("date:exchangeProperty.birthday:yyyyMMdd", String.class));
+ assertEquals("19760623",
evaluate("date:exchangeProperty.birthday+24h:yyyyMMdd", String.class));
+
+ IllegalArgumentException e =
assertThrows(IllegalArgumentException.class,
+ () -> evaluate("date:yyyyMMdd", String.class));
+ assertEquals("Command not supported for dateExpression: yyyyMMdd",
e.getMessage());
+ }
+
+ @Test
+ public void testDateAndTimeExpressions() {
+ Calendar cal = Calendar.getInstance();
+ cal.set(1974, Calendar.APRIL, 20, 8, 55, 47);
+ cal.set(Calendar.MILLISECOND, 123);
+ exchange.getIn().setHeader("birthday", cal.getTime());
+
+ assertEquals("1974-04-20T08:55:37:123", evaluate("date:header.birthday
- 10s:yyyy-MM-dd'T'HH:mm:ss:SSS", String.class));
+ assertEquals("1974-04-20T08:55:47:123",
evaluate("date:header.birthday:yyyy-MM-dd'T'HH:mm:ss:SSS", String.class));
+ }
+
+ @Test
+ public void testDateWithConverterExpressions() {
+ exchange.getIn().setHeader("birthday", new MyCustomDate(1974,
Calendar.APRIL, 20));
+ exchange.setProperty("birthday", new MyCustomDate(1974,
Calendar.APRIL, 20));
+ exchange.getIn().setHeader("other", new ArrayList<>());
+
+ assertEquals("19740420", evaluate("date:header.birthday:yyyyMMdd",
String.class));
+ assertEquals("19740420",
evaluate("date:exchangeProperty.birthday:yyyyMMdd", String.class));
+
+ IllegalArgumentException e =
assertThrows(IllegalArgumentException.class,
+ () -> evaluate("date:header.other:yyyyMMdd", String.class));
+ assertEquals("Cannot find Date/long object at command: header.other",
e.getMessage());
+ }
+
+ @Test
+ public void testDateWithTimezone() {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(TimeZone.getTimeZone("GMT+8"));
+ cal.set(1974, Calendar.APRIL, 20, 8, 55, 47);
+ cal.set(Calendar.MILLISECOND, 123);
+ exchange.getIn().setHeader("birthday", cal.getTime());
+
+ assertEquals("1974-04-20T08:55:47:123",
+
evaluate("date-with-timezone:header.birthday:GMT+8:yyyy-MM-dd'T'HH:mm:ss:SSS",
String.class));
+ assertEquals("1974-04-20T00:55:47:123",
+
evaluate("date-with-timezone:header.birthday:GMT:yyyy-MM-dd'T'HH:mm:ss:SSS",
String.class));
+ }
+
+ @Test
+ public void testDateNow() {
+ Object out = evaluate("date:now", Object.class);
+ assertNotNull(out);
+ assertIsInstanceOf(Date.class, out);
+
+ assertNotNull(evaluate("date:now:hh:mm:ss a", Object.class));
+ assertNotNull(evaluate("date:now:hh:mm:ss", Object.class));
+ assertNotNull(evaluate("date:now-2h:hh:mm:ss", Object.class));
+ }
+
+ @Test
+ public void testDateMillis() {
+ Object out = evaluate("date:millis", Object.class);
+ assertNotNull(out);
+ assertIsInstanceOf(Long.class, out);
+ }
+
+ @Test
+ public void testDateExchangeCreated() {
+ Object out = evaluate("date:exchangeCreated:hh:mm:ss a", String.class);
+ assertNotNull(out);
+ }
+
+ // --- date-with-timezone: code generation ---
+
+ @Test
+ public void testCreateCodeDateMillis() {
+ assertEquals("System.currentTimeMillis()", createCode("date:millis"));
+ }
+
+ @Test
+ public void testCreateCodeDateNoPattern() {
+ assertEquals("date(exchange, \"now\")", createCode("date:now"));
+ }
+
+ @Test
+ public void testCreateCodeDateWithPattern() {
+ assertEquals("date(exchange, \"now\", null, \"yyyy-MM-dd\")",
createCode("date:now:yyyy-MM-dd"));
+ }
+
+ @Test
+ public void testCreateCodeDateWithTimezone() {
+ assertEquals("date(exchange, \"now\", \"UTC\", \"yyyy-MM-dd\")",
+ createCode("date-with-timezone:now:UTC:yyyy-MM-dd"));
+ }
+
+ @Test
+ public void testCreateCodeUnknown() {
+ assertNull(createFactory().createCode(context, "unknown", 0));
+ }
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/MessageFunctionFactoryTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/MessageFunctionFactoryTest.java
new file mode 100644
index 000000000000..0014923d6f4e
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/MessageFunctionFactoryTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import org.apache.camel.language.simple.MyAttachmentMessage;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class MessageFunctionFactoryTest extends
AbstractSimpleFunctionFactoryTestSupport {
+
+ @Override
+ protected SimpleLanguageFunctionFactory createFactory() {
+ return new MessageFunctionFactory();
+ }
+
+ // --- messageAs( ---
+
+ @Test
+ public void testMessageAs() {
+ // exchange.getMessage(MyAttachmentMessage.class) returns null when
the current message is
+ // a DefaultMessage (no type-converter exists). messageOgnlExpression
short-circuits on null
+ // and returns null without invoking OGNL. The original SimpleTest
used assertPredicate(...,
+ // false) which passed because the Simple predicate engine coerces
null to false; the raw
+ // expression value itself is null, not Boolean.FALSE.
+
assertNull(evaluate("messageAs(org.apache.camel.language.simple.MyAttachmentMessage).hasAttachments",
+ Boolean.class));
+
assertNull(evaluate("messageAs(org.apache.camel.language.simple.MyAttachmentMessage)?.hasAttachments",
+ Boolean.class));
+
+ MyAttachmentMessage msg = new MyAttachmentMessage(exchange);
+ msg.setBody("<hello id='m123'>world!</hello>");
+ exchange.setMessage(msg);
+
+ assertEquals(true,
+
evaluate("messageAs(org.apache.camel.language.simple.MyAttachmentMessage).hasAttachments",
Boolean.class));
+ assertEquals(true,
+
evaluate("messageAs(org.apache.camel.language.simple.MyAttachmentMessage)?.hasAttachments",
Boolean.class));
+ assertEquals("42",
+
evaluate("messageAs(org.apache.camel.language.simple.MyAttachmentMessage).size",
String.class));
+ }
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/OutputFunctionFactoryTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/OutputFunctionFactoryTest.java
new file mode 100644
index 000000000000..01f6e2b979f8
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/OutputFunctionFactoryTest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.util.json.Jsoner;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class OutputFunctionFactoryTest extends
AbstractSimpleFunctionFactoryTestSupport {
+
+ @Override
+ protected SimpleLanguageFunctionFactory createFactory() {
+ return new OutputFunctionFactory();
+ }
+
+ // --- pretty( ---
+
+ @Test
+ public void testPretty() {
+ assertEquals("Hello", evaluate("pretty('Hello')", String.class));
+
+ // XmlPrettyPrinter only emits text content when indent > 1 (i.e.,
inside a nested element).
+ // Text directly inside the root element is silently dropped, so
"world!" does not appear.
+ assertEquals("<hello id=\"m123\">\n</hello>",
evaluate("pretty(${body})", String.class));
+
+ exchange.getMessage().setBody("{\"name\": \"Jack\", \"id\": 123}");
+ assertEquals("{\n\t\"name\": \"Jack\",\n\t\"id\": 123\n}\n",
evaluate("pretty(${body})", String.class));
+ }
+
+ // --- toJson( / toPrettyJson( ---
+
+ @Test
+ public void testToJson() {
+ // string body is returned as-is
+ exchange.getMessage().setBody("Hello");
+ assertEquals("Hello", evaluate("toJson(${body})", String.class));
+
+ // map body is serialized to JSON
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("name", "Jack");
+ map.put("id", 123);
+ exchange.getMessage().setBody(map);
+ assertEquals("{\"name\":\"Jack\",\"id\":123}",
evaluate("toJson(${body})", String.class));
+ // pretty mode
+ String pretty = Jsoner.prettyPrint("{\"name\":\"Jack\",\"id\":123}");
+ assertEquals(pretty, evaluate("toPrettyJson(${body})", String.class));
+
+ // list body is serialized to JSON array
+ exchange.getMessage().setBody(List.of("a", "b", "c"));
+ assertEquals("[\"a\",\"b\",\"c\"]", evaluate("toJson(${body})",
String.class));
+ // pretty mode
+ pretty = Jsoner.prettyPrint("[\"a\",\"b\",\"c\"]");
+ assertEquals(pretty, evaluate("toPrettyJson(${body})", String.class));
+
+ // null body
+ exchange.getMessage().setBody(null);
+ assertNull(evaluate("toJson(${body})", Object.class));
+ // pretty mode
+ assertNull(evaluate("toPrettyJson(${body})", Object.class));
+
+ // toJson with a header expression
+ exchange.getMessage().setHeader("myNum", 42);
+ assertEquals("42", evaluate("toJson(${header.myNum})", String.class));
+ // pretty mode
+ assertEquals("42", evaluate("toPrettyJson(${header.myNum})",
String.class));
+ }
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/PropertiesFunctionFactoryTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/PropertiesFunctionFactoryTest.java
new file mode 100644
index 000000000000..7d1eb2dc9a34
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/PropertiesFunctionFactoryTest.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import org.apache.camel.spi.PropertiesComponent;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class PropertiesFunctionFactoryTest extends
AbstractSimpleFunctionFactoryTestSupport {
+
+ @Override
+ protected SimpleLanguageFunctionFactory createFactory() {
+ return new PropertiesFunctionFactory();
+ }
+
+ @Override
+ protected Registry createCamelRegistry() throws Exception {
+ Registry registry = super.createCamelRegistry();
+ registry.bind("myAnimal", "Donkey");
+ return registry;
+ }
+
+ // --- ref: ---
+
+ @Test
+ public void testRefExpression() {
+ assertIsInstanceOf(String.class, evaluate("ref:myAnimal",
Object.class));
+ assertEquals("Donkey", evaluate("ref:myAnimal", String.class));
+ assertNull(evaluate("ref:unknown", Object.class));
+ }
+
+ @Test
+ public void testCreateCodeRef() {
+ assertEquals("ref(exchange, \"myBean\")", createCode("ref:myBean"));
+ }
+
+ // --- propertiesExist: ---
+
+ @Test
+ public void testPropertiesExist() {
+ PropertiesComponent pc = context.getPropertiesComponent();
+
+ assertEquals("false", evaluate("propertiesExist:myKey", String.class));
+ assertEquals("true", evaluate("propertiesExist:!myKey", String.class));
+ assertEquals(false, evaluate("propertiesExist:myKey", Boolean.class));
+ assertEquals(true, evaluate("propertiesExist:!myKey", Boolean.class));
+
+ pc.addInitialProperty("myKey", "abc");
+ assertEquals("true", evaluate("propertiesExist:myKey", String.class));
+ assertEquals("false", evaluate("propertiesExist:!myKey",
String.class));
+ assertEquals(true, evaluate("propertiesExist:myKey", Boolean.class));
+ assertEquals(false, evaluate("propertiesExist:!myKey", Boolean.class));
+ }
+
+ @Test
+ public void testPropertiesExistHasNoCodeGeneration() {
+ // propertiesExist: is handled at runtime only; CSimple has no
code-gen path for it
+ assertNull(createFactory().createCode(context,
"propertiesExist:myKey", 0));
+ }
+
+ // --- properties: ---
+
+ @Test
+ public void testCreateCodePropertiesNoDefault() {
+ assertEquals("properties(exchange, \"myKey\")",
createCode("properties:myKey"));
+ }
+
+ @Test
+ public void testCreateCodePropertiesWithDefault() {
+ assertEquals("properties(exchange, \"myKey\", \"myDefault\")",
createCode("properties:myKey:myDefault"));
+ }
+
+ @Test
+ public void testCreateCodeUnknown() {
+ assertNull(createFactory().createCode(context, "unknown", 0));
+ }
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/SystemFunctionFactoryTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/SystemFunctionFactoryTest.java
new file mode 100644
index 000000000000..31d668095278
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/SystemFunctionFactoryTest.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.junit.jupiter.api.Test;
+import org.junitpioneer.jupiter.SetSystemProperty;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class SystemFunctionFactoryTest extends
AbstractSimpleFunctionFactoryTestSupport {
+
+ @Override
+ protected SimpleLanguageFunctionFactory createFactory() {
+ return new SystemFunctionFactory();
+ }
+
+ // --- sys. ---
+
+ @Test
+ @SetSystemProperty(key = "who", value = "I was here")
+ public void testSimpleSystemPropertyExpressions() {
+ assertEquals("I was here", evaluate("sys.who", String.class));
+ }
+
+ @Test
+ public void testCreateCodeSys() {
+ assertEquals("sys(\"java.version\")", createCode("sys.java.version"));
+ }
+
+ // --- sysenv. / sysenv: / env. / env: ---
+
+ @Test
+ public void testSimpleSystemEnvironmentExpressions() {
+ String path = System.getenv("PATH");
+ if (path != null) {
+ assertEquals(path, evaluate("sysenv.PATH", String.class));
+ assertEquals(path, evaluate("sysenv:PATH", String.class));
+ assertEquals(path, evaluate("env.PATH", String.class));
+ assertEquals(path, evaluate("env:PATH", String.class));
+ }
+ }
+
+ @Test
+ public void testSimpleSystemEnvironmentExpressionsIfDash() {
+ String foo = System.getenv("FOO_SERVICE_HOST");
+ if (foo != null) {
+ assertEquals(foo, evaluate("sysenv.FOO-SERVICE-HOST",
String.class));
+ assertEquals(foo, evaluate("sysenv:FOO-SERVICE-HOST",
String.class));
+ assertEquals(foo, evaluate("env.FOO-SERVICE-HOST", String.class));
+ assertEquals(foo, evaluate("env:FOO-SERVICE-HOST", String.class));
+ }
+ }
+
+ @Test
+ public void testSimpleSystemEnvironmentExpressionsIfLowercase() {
+ String path = System.getenv("PATH");
+ if (path != null) {
+ assertEquals(path, evaluate("sysenv.path", String.class));
+ assertEquals(path, evaluate("sysenv:path", String.class));
+ assertEquals(path, evaluate("env.path", String.class));
+ assertEquals(path, evaluate("env:path", String.class));
+ }
+ }
+
+ @Test
+ public void testCreateCodeSysenvDot() {
+ assertEquals("sysenv(\"MY_VAR\")", createCode("sysenv.MY_VAR"));
+ }
+
+ @Test
+ public void testCreateCodeSysenvColon() {
+ assertEquals("sysenv(\"MY_VAR\")", createCode("sysenv:MY_VAR"));
+ }
+
+ @Test
+ public void testCreateCodeEnvDot() {
+ assertEquals("sysenv(\"MY_VAR\")", createCode("env.MY_VAR"));
+ }
+
+ @Test
+ public void testCreateCodeEnvColon() {
+ assertEquals("sysenv(\"MY_VAR\")", createCode("env:MY_VAR"));
+ }
+
+ @Test
+ public void testCreateCodeUnknown() {
+ assertNull(createFactory().createCode(context, "unknown", 0));
+ }
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/TypeFunctionFactoryTest.java
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/TypeFunctionFactoryTest.java
new file mode 100644
index 000000000000..ed1b11c913f7
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/language/simple/functions/TypeFunctionFactoryTest.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.language.simple.functions;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class TypeFunctionFactoryTest extends
AbstractSimpleFunctionFactoryTestSupport {
+
+ @Override
+ protected SimpleLanguageFunctionFactory createFactory() {
+ return new TypeFunctionFactory();
+ }
+
+ // --- type: ---
+
+ @Test
+ public void testTypeConstant() {
+ assertEquals(Exchange.FILE_NAME,
evaluate("type:org.apache.camel.Exchange.FILE_NAME", String.class));
+ assertEquals(ExchangePattern.InOut,
evaluate("type:org.apache.camel.ExchangePattern.InOut", ExchangePattern.class));
+
+ Exception e1 = assertThrows(Exception.class,
+ () -> evaluate("type:org.apache.camel.ExchangePattern.",
Object.class));
+ assertIsInstanceOf(ClassNotFoundException.class, e1.getCause());
+
+ Exception e2 = assertThrows(Exception.class,
+ () ->
evaluate("type:org.apache.camel.ExchangePattern.UNKNOWN", Object.class));
+ assertIsInstanceOf(ClassNotFoundException.class, e2.getCause());
+ }
+
+ @Test
+ public void testTypeConstantInnerClass() {
+ assertEquals(123,
evaluate("type:org.apache.camel.language.simple.Constants$MyInnerStuff.FOO",
Integer.class));
+ assertEquals(456,
evaluate("type:org.apache.camel.language.simple.Constants.BAR", Integer.class));
+ }
+
+ @Test
+ public void testCreateCodeTypeWithField() {
+ assertEquals("type(exchange, java.lang.Integer.class, \"MAX_VALUE\")",
+ createCode("type:java.lang.Integer.MAX_VALUE"));
+ }
+
+ @Test
+ public void testCreateCodeTypeNoField() {
+ // no dots in the remainder -> field is null, only class emitted
+ assertEquals("type(exchange, String.class)",
createCode("type:String"));
+ }
+
+ @Test
+ public void testCreateCodeUnknown() {
+ assertNull(createFactory().createCode(context, "unknown", 0));
+ }
+}