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 99decfa68bb CAMEL-20929: properties function with fine grained control 
whether a property is optional or not. (#14679)
99decfa68bb is described below

commit 99decfa68bbbbead49bab7a428eeece9ec9c615e
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Jun 30 07:55:40 2024 +0200

    CAMEL-20929: properties function with fine grained control whether a 
property is optional or not. (#14679)
---
 .../org/apache/camel/spi/PropertiesFunction.java   | 10 +++
 .../properties/DefaultPropertiesParser.java        | 12 ++--
 ...rtyFunctionOptionalPropertyPlaceholderTest.java | 79 ++++++++++++++++++++++
 3 files changed, 97 insertions(+), 4 deletions(-)

diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java
index 6e3482db6d6..f995a496308 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java
@@ -46,4 +46,14 @@ public interface PropertiesFunction {
         return false;
     }
 
+    /**
+     * If the property value cannot be found should the property be regarded 
as optional and ignore missing value.
+     *
+     * @param  remainder the remainder value
+     * @return           true to make this property as optional
+     */
+    default boolean optional(String remainder) {
+        return false;
+    }
+
 }
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
 
b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
index 40840041e48..ef7286d8e6c 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
@@ -321,10 +321,10 @@ public class DefaultPropertiesParser implements 
PropertiesParser {
                 PropertiesFunction function = 
propertiesComponent.getPropertiesFunction(prefix);
                 if (function != null) {
                     String remainder = StringHelper.after(key, ":");
+                    boolean remainderOptional = 
remainder.startsWith(OPTIONAL_TOKEN);
                     if (function.lookupFirst(remainder)) {
-                        boolean functionOptional = 
remainder.startsWith(OPTIONAL_TOKEN);
                         String value = getPropertyValue(remainder, input);
-                        if (functionOptional && value == null) {
+                        if (value == null && (remainderOptional || 
function.optional(remainder))) {
                             return null;
                         }
                         // it was not possible to resolve
@@ -337,11 +337,15 @@ public class DefaultPropertiesParser implements 
PropertiesParser {
                     log.debug("Property with key [{}] is applied by function 
[{}]", key, function.getName());
                     String value = function.apply(remainder);
                     if (value == null) {
-                        if (!optional && propertiesComponent != null && 
propertiesComponent.isIgnoreMissingProperty()) {
+                        if (!remainderOptional) {
+                            remainderOptional = function.optional(remainder);
+                        }
+                        if (!remainderOptional && propertiesComponent != null
+                                && 
propertiesComponent.isIgnoreMissingProperty()) {
                             // property is missing, but we should ignore this 
and return the placeholder unresolved
                             return UNRESOLVED_PREFIX_TOKEN + key + 
UNRESOLVED_SUFFIX_TOKEN;
                         }
-                        if (!optional) {
+                        if (!remainderOptional) {
                             throw new IllegalArgumentException(
                                     "Property with key [" + key + "] using 
function [" + function.getName() + "]"
                                                                + " returned 
null value which is not allowed, from input: "
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertyFunctionOptionalPropertyPlaceholderTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertyFunctionOptionalPropertyPlaceholderTest.java
index 44e91c2be5a..790c5ea8142 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertyFunctionOptionalPropertyPlaceholderTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertyFunctionOptionalPropertyPlaceholderTest.java
@@ -107,6 +107,52 @@ public class 
PropertyFunctionOptionalPropertyPlaceholderTest extends ContextTest
         assertEquals(2, 
getMockEndpoint("mock:result").getReceivedExchanges().size());
     }
 
+    @Test
+    public void testFunctionMagic() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start")
+                        .setBody().constant("{{magic:myMagic}}")
+                        .to("mock:result");
+            }
+        });
+        context.start();
+
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        getMockEndpoint("mock:result").allMessages().body().isEqualTo("magic");
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start", "Bye World");
+
+        assertMockEndpointsSatisfied();
+
+        assertEquals(2, 
getMockEndpoint("mock:result").getReceivedExchanges().size());
+    }
+
+    @Test
+    public void testFunctionMagicOptional() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start")
+                        .setBody().constant("{{magic:myOptional}}")
+                        .to("mock:result");
+            }
+        });
+        context.start();
+
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        getMockEndpoint("mock:result").allMessages().body().isNull();
+
+        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:start", "Bye World");
+
+        assertMockEndpointsSatisfied();
+
+        assertEquals(2, 
getMockEndpoint("mock:result").getReceivedExchanges().size());
+    }
+
     @Test
     public void testFunctionPresent() throws Exception {
         Properties prop = new Properties();
@@ -188,6 +234,9 @@ public class 
PropertyFunctionOptionalPropertyPlaceholderTest extends ContextTest
         ReverseFunction func = new ReverseFunction();
         func.setCamelContext(context);
         context.getPropertiesComponent().addPropertiesFunction(func);
+        MagicFunction func2 = new MagicFunction();
+        func2.setCamelContext(context);
+        context.getPropertiesComponent().addPropertiesFunction(func2);
         return context;
     }
 
@@ -225,4 +274,34 @@ public class 
PropertyFunctionOptionalPropertyPlaceholderTest extends ContextTest
         }
     }
 
+    private static class MagicFunction implements PropertiesFunction, 
CamelContextAware {
+
+        private CamelContext camelContext;
+
+        @Override
+        public CamelContext getCamelContext() {
+            return camelContext;
+        }
+
+        @Override
+        public void setCamelContext(CamelContext camelContext) {
+            this.camelContext = camelContext;
+        }
+
+        @Override
+        public String getName() {
+            return "magic";
+        }
+
+        @Override
+        public String apply(String remainder) {
+            return "myMagic".equals(remainder) ? "magic" : null;
+        }
+
+        @Override
+        public boolean optional(String remainder) {
+            return "myOptional".equals(remainder);
+        }
+    }
+
 }

Reply via email to