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

jamesnetherton pushed a commit to branch camel-4.8.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-4.8.x by this push:
     new 393c9d28ce4 CAMEL-21357: Add ability to resolve JQ root scope from the 
registry
393c9d28ce4 is described below

commit 393c9d28ce49c4f3a528817af40a92648c97ac00
Author: James Netherton <[email protected]>
AuthorDate: Wed Oct 16 16:49:10 2024 +0100

    CAMEL-21357: Add ability to resolve JQ root scope from the registry
---
 .../org/apache/camel/language/jq/JqFunctions.java  |   5 +-
 .../org/apache/camel/language/jq/JqLanguage.java   |   6 +-
 .../camel/language/jq/JqCustomScopeTest.java       | 116 +++++++++++++++++++++
 3 files changed, 124 insertions(+), 3 deletions(-)

diff --git 
a/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqFunctions.java
 
b/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqFunctions.java
index 8589ed7eeeb..2c28a795d38 100644
--- 
a/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqFunctions.java
+++ 
b/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqFunctions.java
@@ -62,8 +62,6 @@ public final class JqFunctions {
                         Versions.JQ_1_6,
                         scope);
 
-        Map<String, Function> fromRegistry = 
camelContext.getRegistry().findByTypeWithName(Function.class);
-
         if (fromServiceLoader != null) {
             LOGGER.debug("Loading {} jq functions from ServiceLoader", 
fromServiceLoader.size());
             fromServiceLoader.forEach(scope::addFunction);
@@ -73,7 +71,10 @@ public final class JqFunctions {
             LOGGER.debug("Loading {} jq functions from Json JQ", 
fromJq.size());
             fromJq.forEach(scope::addFunction);
         }
+    }
 
+    public static void loadFromRegistry(CamelContext camelContext, Scope 
scope) {
+        Map<String, Function> fromRegistry = 
camelContext.getRegistry().findByTypeWithName(Function.class);
         if (fromRegistry != null) {
             LOGGER.debug("Loading {} jq functions from Registry", 
fromRegistry.size());
             fromRegistry.forEach(scope::addFunction);
diff --git 
a/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java
 
b/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java
index 2686e84b437..4363ae94070 100644
--- 
a/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java
+++ 
b/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java
@@ -21,6 +21,7 @@ import 
net.thisptr.jackson.jq.module.loaders.BuiltinModuleLoader;
 import org.apache.camel.Expression;
 import org.apache.camel.StaticService;
 import org.apache.camel.spi.annotations.Language;
+import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.SingleInputTypedLanguageSupport;
 import org.apache.camel.util.ObjectHelper;
 
@@ -33,12 +34,15 @@ public class JqLanguage extends 
SingleInputTypedLanguageSupport implements Stati
     public void init() {
         ObjectHelper.notNull(getCamelContext(), "CamelContext", this);
 
+        this.rootScope = 
CamelContextHelper.findSingleByType(getCamelContext(), Scope.class);
         if (this.rootScope == null) {
             this.rootScope = Scope.newEmptyScope();
             this.rootScope.setModuleLoader(BuiltinModuleLoader.getInstance());
             JqFunctions.load(getCamelContext(), rootScope);
-            JqFunctions.loadLocal(rootScope);
         }
+
+        JqFunctions.loadFromRegistry(getCamelContext(), rootScope);
+        JqFunctions.loadLocal(rootScope);
     }
 
     public Scope getRootScope() {
diff --git 
a/components/camel-jq/src/test/java/org/apache/camel/language/jq/JqCustomScopeTest.java
 
b/components/camel-jq/src/test/java/org/apache/camel/language/jq/JqCustomScopeTest.java
new file mode 100644
index 00000000000..388b0c42972
--- /dev/null
+++ 
b/components/camel-jq/src/test/java/org/apache/camel/language/jq/JqCustomScopeTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.jq;
+
+import java.util.List;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.BooleanNode;
+import net.thisptr.jackson.jq.Expression;
+import net.thisptr.jackson.jq.Function;
+import net.thisptr.jackson.jq.PathOutput;
+import net.thisptr.jackson.jq.Scope;
+import net.thisptr.jackson.jq.Version;
+import net.thisptr.jackson.jq.exception.JsonQueryException;
+import net.thisptr.jackson.jq.path.Path;
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+
+public class JqCustomScopeTest extends JqTestSupport {
+
+    @Test
+    public void testCustomScopeFunction() throws Exception {
+        
getMockEndpoint("mock:result").expectedBodiesReceived(MAPPER.createObjectNode().put("foo",
 "camel bar"));
+
+        template.sendBody("direct:containsCamel", 
MAPPER.createObjectNode().put("foo", "baz"));
+        template.sendBody("direct:containsCamel", 
MAPPER.createObjectNode().put("foo", "camel bar"));
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    @Test
+    public void testCustomScopeFunctionFromRegistry() throws Exception {
+        
getMockEndpoint("mock:result").expectedBodiesReceived(MAPPER.createObjectNode().put("foo",
 "beer"));
+
+        template.sendBody("direct:containsBeer", 
MAPPER.createObjectNode().put("foo", "baz"));
+        template.sendBody("direct:containsBeer", 
MAPPER.createObjectNode().put("foo", "beer"));
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    @Test
+    public void testCustomScopeBuiltInFunction() throws Exception {
+        
getMockEndpoint("mock:result").expectedBodiesReceived(MAPPER.createObjectNode().put("foo",
 "123456"));
+
+        template.sendBody("direct:builtInFunction", 
MAPPER.createObjectNode().put("foo", "12345"));
+        template.sendBody("direct:builtInFunction", 
MAPPER.createObjectNode().put("foo", "123456"));
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    @BindToRegistry
+    public Scope customScope() {
+        Scope scope = Scope.newEmptyScope();
+        JqFunctions.load(context, scope);
+        scope.addFunction("containsCamel", new Function() {
+            @Override
+            public void apply(Scope scope, List<Expression> args, JsonNode in, 
Path path, PathOutput output, Version version)
+                    throws JsonQueryException {
+                args.get(0).apply(scope, in, (value) -> {
+                    
output.emit(BooleanNode.valueOf(value.asText().contains("camel")), null);
+                });
+            }
+        });
+        return scope;
+    }
+
+    @BindToRegistry
+    public Function containsBeer() {
+        return new Function() {
+            @Override
+            public void apply(Scope scope, List<Expression> args, JsonNode in, 
Path path, PathOutput output, Version version)
+                    throws JsonQueryException {
+                args.get(0).apply(scope, in, (value) -> {
+                    
output.emit(BooleanNode.valueOf(value.asText().contains("beer")), null);
+                });
+            }
+        };
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:containsCamel")
+                        .filter().jq("containsCamel(.foo)")
+                        .to("mock:result");
+
+                from("direct:containsBeer")
+                        .filter().jq("containsBeer(.foo)")
+                        .to("mock:result");
+
+                from("direct:builtInFunction")
+                        .filter().jq(".foo | length > 5")
+                        .to("mock:result");
+
+            }
+        };
+    }
+}

Reply via email to