davsclaus commented on code in PR #23263:
URL: https://github.com/apache/camel/pull/23263#discussion_r3265531601


##########
core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleFunctionDispatcher.java:
##########
@@ -0,0 +1,148 @@
+/*
+ * 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;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.language.simple.functions.CollateFunctionFactory;
+import org.apache.camel.language.simple.functions.JoinFunctionFactory;
+import org.apache.camel.language.simple.functions.RandomFunctionFactory;
+import org.apache.camel.language.simple.functions.SkipFunctionFactory;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.support.ResolverHelper;
+
+import static 
org.apache.camel.language.simple.ast.SimpleFunctionExpression.ifStartsWithReturnRemainder;
+
+/**
+ * Resolves {@link SimpleLanguageFunctionFactory} implementations shipped by 
external Camel components (currently
+ * camel-attachments, camel-base64, camel-jsoup) and delegates Simple/CSimple 
function lookup to whichever one claims
+ * the function string.
+ * <p>
+ * Each entry carries a gate that decides whether its factory is consulted for 
a given function string; gates mirror the
+ * inline checks that previously lived in {@code SimpleFunctionExpression}, so 
a function belonging to a missing
+ * component still surfaces the "add the JAR to your classpath" error from
+ * {@link ResolverHelper#resolveMandatoryBootstrapService}. Factory resolution 
is cached by the bootstrap factory
+ * finder, so repeated dispatch is cheap.
+ */
+public final class SimpleFunctionDispatcher {
+
+    /**
+     * Built-in factories shipped by camel-core-languages itself. Iterated 
before {@link #EXPRESSION_ENTRIES}, matching
+     * the original priority of these functions inside {@code 
SimpleFunctionExpression}. Each factory returns
+     * {@code null} for inputs it does not recognise, so no gating predicate 
is needed.
+     */
+    private static final List<SimpleLanguageFunctionFactory> BUILT_INS = 
List.of(
+            new RandomFunctionFactory(),
+            new SkipFunctionFactory(),
+            new CollateFunctionFactory(),
+            new JoinFunctionFactory());
+
+    private static final List<Entry> EXPRESSION_ENTRIES = List.of(
+            new Entry("camel-attachments", 
SimpleFunctionDispatcher::isAttachmentFunction),
+            new Entry("camel-base64", 
SimpleFunctionDispatcher::isBase64Function),
+            new Entry("camel-jsoup", 
SimpleFunctionDispatcher::isHtmlFunction));
+
+    /**
+     * Code-generation entries exclude camel-jsoup deliberately: it has no 
csimple support and its {@code createCode}
+     * throws.
+     */
+    private static final List<Entry> CODE_ENTRIES = List.of(
+            new Entry("camel-attachments", 
SimpleFunctionDispatcher::isAttachmentFunction),
+            new Entry("camel-base64", 
SimpleFunctionDispatcher::isBase64Function));
+
+    private SimpleFunctionDispatcher() {
+    }
+
+    public static Expression tryCreate(CamelContext camelContext, String 
function, int index) {
+        for (SimpleLanguageFunctionFactory factory : BUILT_INS) {
+            Expression answer = factory.createFunction(camelContext, function, 
index);
+            if (answer != null) {
+                return answer;
+            }
+        }
+        for (Entry entry : EXPRESSION_ENTRIES) {
+            if (!entry.claims.test(function)) {
+                continue;
+            }
+            SimpleLanguageFunctionFactory factory = resolve(camelContext, 
entry.jarName);
+            Expression answer = factory.createFunction(camelContext, function, 
index);
+            if (answer != null) {
+                return answer;

Review Comment:
   Minor observation: built-in factories (`random`, `skip`, `collate`, `join`) 
were previously evaluated inside `createSimpleExpressionMisc()` which runs 
*before* `createSimpleExpressionMath()`. Now they are evaluated here, *after* 
math. Since these function prefixes don't overlap with math patterns, this is 
safe — but the PR description's claim of "Behaviour preserved exactly" should 
note this ordering shift.



##########
core/camel-core-languages/src/main/java/org/apache/camel/language/simple/functions/JoinFunctionFactory.java:
##########
@@ -0,0 +1,107 @@
+/*
+ * 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.ast.SimpleFunctionExpression;
+import org.apache.camel.language.simple.types.SimpleParserException;
+import org.apache.camel.spi.SimpleLanguageFunctionFactory;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
+import org.apache.camel.util.StringQuoteHelper;
+
+import static 
org.apache.camel.language.simple.ast.SimpleFunctionExpression.ifStartsWithReturnRemainder;
+
+/**
+ * Built-in Simple function: {@code ${join()}} / {@code ${join(separator)}} / 
{@code ${join(separator,prefix)}} /
+ * {@code ${join(separator,prefix,expression)}}.
+ */
+public final class JoinFunctionFactory implements 
SimpleLanguageFunctionFactory {
+
+    @Override
+    public Expression createFunction(CamelContext camelContext, String 
function, int index) {
+        String remainder = ifStartsWithReturnRemainder("join(", function);
+        if (remainder == null) {
+            return null;
+        }
+        String values = StringHelper.beforeLast(remainder, ")");
+        String separator = ",";
+        String prefix = null;
+        String exp = "${body}";
+        if (ObjectHelper.isNotEmpty(values)) {
+            String[] tokens = StringQuoteHelper.splitSafeQuote(values, ',', 
false);
+            if (tokens.length > 3) {
+                throw new SimpleParserException(
+                        "Valid syntax: ${join(separator,prefix,expression)} 
was: " + function, index);
+            }
+            if (tokens.length == 3) {
+                separator = tokens[0];
+                prefix = tokens[1];
+                exp = tokens[2];
+            } else if (tokens.length == 2) {
+                separator = tokens[0];
+                prefix = tokens[1];
+            } else {
+                separator = tokens[0];
+            }
+        }
+        return SimpleExpressionBuilder.joinExpression(exp, separator, prefix);
+    }

Review Comment:
   Nit for follow-up: this creates a coupling back to the class being 
decomposed. As more factories are extracted, `codeSplitSafe` is a good 
candidate to move into a shared utility class.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to