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 cf1b5e60592b CAMEL-25202: camel-jbang - camel transform route reads 
Java routes without compiling them (#27150)
cf1b5e60592b is described below

commit cf1b5e60592bd6864c7ab5c878619882903c9494
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Oct 1 09:14:55 2026 +0200

    CAMEL-25202: camel-jbang - camel transform route reads Java routes without 
compiling them (#27150)
    
    When all files are Java and every route can be read completely, the Java DSL
    parser reads them into the model and the dump strategy of a running Camel
    writes them, in a CamelContext that is never started: the same YAML or XML 
as
    compiling them, in milliseconds instead of seconds, and no code of the 
project
    runs. A route with a lambda or a value known only at runtime, or
    --resolve-placeholders, compiles them as before; --compile forces it.
    camel-jbang-core depends on camel-yaml-io for the YAML writer.
    
    CAMEL-25202: the Java DSL parser design says camel transform route uses it
    
    …es it
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 design/java-dsl-parser.adoc                        |   7 +-
 .../ROOT/pages/camel-jbang-transforming.adoc       |  17 +++
 .../camel-jbang-transform-route.adoc               |   1 +
 dsl/camel-jbang/camel-jbang-core/pom.xml           |   5 +
 .../META-INF/camel-jbang-commands-metadata.json    |   2 +-
 .../jbang/core/commands/TransformJavaRoutes.java   | 140 +++++++++++++++++
 .../dsl/jbang/core/commands/TransformRoute.java    |  25 +++-
 .../core/commands/TransformJavaRoutesTest.java     | 165 +++++++++++++++++++++
 8 files changed, 356 insertions(+), 6 deletions(-)

diff --git a/design/java-dsl-parser.adoc b/design/java-dsl-parser.adoc
index 1a9c187194b9..80ee524bbfd2 100644
--- a/design/java-dsl-parser.adoc
+++ b/design/java-dsl-parser.adoc
@@ -102,6 +102,12 @@ camel-jbang reads Java routes with the parser only; the 
pattern matching on stri
   consume, with constants, formats and the endpoint DSL resolved;
 * the jump links between routes in the TUI Source tab.
 
+=== Transforming Java routes
+
+`camel transform route` reads Java routes with the parser by default and 
writes them with the dump strategy of a
+running Camel, in a CamelContext that is never started (CAMEL-25202); it 
compiles the routes only when one cannot be
+read completely, or with `--compile`.
+
 == Security
 
 The parser reads sources nobody vetted: a cloned example opened in the TUI, 
documentation, a project an AI agent
@@ -145,7 +151,6 @@ points a tool at. What it guarantees, and how each is 
enforced:
 == Future Work
 
 * Checking the Java examples of the documentation in the build, as the YAML 
and XML ones are.
-* `camel transform` reading Java without compiling by default, compiling when 
a route is partial.
 * Plain-language labels for the decision points of routes in the AI project 
overview (CAMEL-25161).
 * A Java DSL for Camel 5 designed with what the parser found hard (end() 
scoping, expression clauses, a class or its
   name for the same option, varargs options), with this replay as the bridge 
from the current Java DSL: the findings
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-transforming.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang-transforming.adoc
index fc46c1663b84..c136c90d73d8 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-transforming.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-transforming.adoc
@@ -495,3 +495,20 @@ Output:
 ----
 
 TIP: When all input files share the same extension (e.g., `.yaml`), the target 
format defaults to the other DSL (XML) and vice versa.
+
+=== Transforming Java routes
+
+Java DSL routes are transformed to YAML or XML the same way:
+
+[source,bash]
+----
+camel transform route --format=yaml src/main/java/com/acme/OrderRoute.java
+----
+
+The Java sources are read without compiling or running them: the routes are 
read into the model by the Java DSL
+parser, with the constants of the other classes in the same folder, 
`String.format` and the Endpoint DSL resolved, and
+written as a running Camel would dump them. This takes a fraction of a second, 
and no code of the project runs.
+
+When a route cannot be read completely that way, for example a processor 
written as a lambda or a value only known
+at runtime, the routes are compiled and started to dump them, which takes a 
few seconds and may download dependencies.
+The same happens with `--resolve-placeholders`. Use `--compile` to always 
compile and start the routes.
diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-transform-route.adoc
 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-transform-route.adoc
index 4db629cee52f..ff61e758b31c 100644
--- 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-transform-route.adoc
+++ 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-transform-route.adoc
@@ -19,6 +19,7 @@ camel transform route [options]
 [cols="2,5,1,2",options="header"]
 |===
 | Option | Description | Default | Type
+| `--compile` | Compile and run Java routes to transform them. By default Java 
routes are read without compiling them, and compiled only when a route cannot 
be read that way | false | boolean
 | `--download` | Whether to allow automatic downloading JAR dependencies (over 
the internet) | true | boolean
 | `--format` | Output format (xml, yaml), if only yaml files are provided, the 
format defaults to xml and vice versa |  | String
 | `--fresh` | Make sure we use fresh (i.e. non-cached) resources | false | 
boolean
diff --git a/dsl/camel-jbang/camel-jbang-core/pom.xml 
b/dsl/camel-jbang/camel-jbang-core/pom.xml
index a0156fec1c5c..29fc9e7c400f 100644
--- a/dsl/camel-jbang/camel-jbang-core/pom.xml
+++ b/dsl/camel-jbang/camel-jbang-core/pom.xml
@@ -74,6 +74,11 @@
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-java-io</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <!-- camel transform route writes YAML from Java routes read 
without compiling them -->
+            <artifactId>camel-yaml-io</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-xml-io-util</artifactId>
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
index d17551956db8..3fe53a77e6ec 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
@@ -34,7 +34,7 @@
     { "name": "stop", "fullName": "stop", "description": "Shuts down running 
Camel integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.StopProcess", "options": [ { 
"names": "--kill", "description": "To force killing the process (SIGKILL)", 
"javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", 
"description": "Display the help and sub-commands", "javaType": "boolean", 
"type": "boolean" } ] },
     { "name": "top", "fullName": "top", "description": "Top status of Camel 
integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.CamelTop", "options": [ { 
"names": "--watch", "description": "Execute periodically and showing output 
fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ], "subcommands": [ { "name": "context", 
"fullName": "top  [...]
     { "name": "trace", "fullName": "trace", "description": "Tail message 
traces from running Camel integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.action.CamelTraceAction", "options": 
[ { "names": "--action", "description": "Action to start, stop, clear, list 
status, or dump traces", "defaultValue": "status", "javaType": 
"java.lang.String", "type": "string" }, { "names": "--ago", "description": "Use 
ago instead of yyyy-MM-dd HH:mm:ss in timestamp.", "javaType": "b [...]
-    { "name": "transform", "fullName": "transform", "description": "Transform 
message or Camel routes", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.TransformCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"dataweave", "fullName": "transform dataweave", "description": "Convert 
DataWeave scripts to DataSonnet format", "sourceClass": "org.apache.camel.dsl. 
[...]
+    { "name": "transform", "fullName": "transform", "description": "Transform 
message or Camel routes", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.TransformCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"dataweave", "fullName": "transform dataweave", "description": "Convert 
DataWeave scripts to DataSonnet format", "sourceClass": "org.apache.camel.dsl. 
[...]
     { "name": "update", "fullName": "update", "description": "Update Camel 
project", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.update.UpdateCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"list", "fullName": "update list", "description": "List available update 
versions for Camel and its runtime variants", "sourceClass": 
"org.apache.camel.dsl.jbang.cor [...]
     { "name": "version", "fullName": "version", "description": "Manage Camel 
versions", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.version.VersionCommand", "options": [ 
{ "names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "get", 
"fullName": "version get", "description": "Displays current Camel version", 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.version.VersionGet", 
[...]
     { "name": "wrapper", "fullName": "wrapper", "description": "Install Camel 
wrapper scripts for version pinning", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.WrapperCommand", "options": [ { 
"names": "--camel-version", "description": "Camel version to pin (defaults to 
current version)", "javaType": "java.lang.String", "type": "string" }, { 
"names": "--command-name", "description": "The name of the command to use 
(camel or camelw)", "defaultValue": "camel", "javaType": "java [...]
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformJavaRoutes.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformJavaRoutes.java
new file mode 100644
index 000000000000..1172cf28159d
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformJavaRoutes.java
@@ -0,0 +1,140 @@
+/*
+ * 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.dsl.jbang.core.commands;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import org.apache.camel.catalog.CamelCatalog;
+import org.apache.camel.catalog.DefaultCamelCatalog;
+import org.apache.camel.dsl.jbang.core.commands.ai.ProjectRoutes;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.DefaultDumpRoutesStrategy;
+import org.apache.camel.java.in.JavaParseResult;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.support.ResourceHelper;
+
+/**
+ * {@code camel transform route} for Java routes without compiling them 
(CAMEL-25202): the sources are read into the
+ * model by the Java DSL parser of camel-java-io, and dumped as YAML or XML by 
the same dump strategy a running Camel
+ * uses ({@code camel.main.dumpRoutes}), in a CamelContext that is never 
started. Nothing of the project is compiled,
+ * loaded or run.
+ */
+final class TransformJavaRoutes {
+
+    /** Whether the routes were transformed, and why not: the first part the 
parser could not read. */
+    record Result(boolean transformed, String reason) {
+    }
+
+    private TransformJavaRoutes() {
+    }
+
+    /** Whether the files are all Java sources, which the parser may read. */
+    static boolean applies(List<String> files) {
+        return !files.isEmpty()
+                && files.stream().allMatch(f -> f.endsWith(".java") && 
Files.isRegularFile(Path.of(f)));
+    }
+
+    /**
+     * Transforms the Java routes of the files when every route can be read 
completely.
+     *
+     * @param  format          yaml or xml
+     * @param  output          the file or directory to write to
+     * @param  uriAsParameters whether to expand URIs into key/value 
parameters (YAML)
+     * @return                 whether they were transformed; else why not, 
and nothing is written
+     */
+    static Result transform(List<String> files, String format, String output, 
boolean uriAsParameters)
+            throws Exception {
+        CamelCatalog catalog = new DefaultCamelCatalog();
+        Map<String, Supplier<String>> sources = javaSources(files);
+        List<JavaParseResult> results = new ArrayList<>();
+        List<Resource> resources = new ArrayList<>();
+        for (String f : files) {
+            String content = Files.readString(Path.of(f), 
StandardCharsets.UTF_8);
+            JavaParseResult result = ProjectRoutes.parseJava(content, sources, 
catalog);
+            for (JavaParseResult.Unresolved u : result.unresolved()) {
+                if (!JavaParseResult.configuresTheContext(u)) {
+                    return new Result(false, f + ":" + u.line() + " " + 
u.text() + " (" + u.reason() + ")");
+                }
+            }
+            if (result.routes().getRoutes().isEmpty() && 
result.rests().getRests().isEmpty()
+                    && result.routeTemplates().getRouteTemplates().isEmpty()
+                    && 
result.routeConfigurations().getRouteConfigurations().isEmpty()) {
+                return new Result(false, f + " has no routes the parser can 
read");
+            }
+            results.add(result);
+            // the source file, so each is dumped on its own and named after 
it, as when the routes run
+            resources.add(ResourceHelper.fromString("file:" + 
Path.of(f).getFileName(), content));
+        }
+        try (DefaultCamelContext context = new DefaultCamelContext()) {
+            // never started: adding the definitions only registers them
+            for (int i = 0; i < results.size(); i++) {
+                JavaParseResult r = results.get(i);
+                Resource resource = resources.get(i);
+                r.routes().getRoutes().forEach(d -> d.setResource(resource));
+                r.rests().getRests().forEach(d -> d.setResource(resource));
+                r.routeTemplates().getRouteTemplates().forEach(d -> 
d.setResource(resource));
+                r.routeConfigurations().getRouteConfigurations().forEach(d -> 
d.setResource(resource));
+                
context.addRouteConfigurations(r.routeConfigurations().getRouteConfigurations());
+                context.addRestDefinitions(r.rests().getRests(), false);
+                
context.addRouteTemplateDefinitions(r.routeTemplates().getRouteTemplates());
+                context.addRouteDefinitions(r.routes().getRoutes());
+            }
+            DefaultDumpRoutesStrategy dumper = new DefaultDumpRoutesStrategy();
+            dumper.setCamelContext(context);
+            
dumper.setInclude("routes,rests,routeConfigurations,beans,dataFormats");
+            dumper.setLog(false);
+            dumper.setResolvePlaceholders(false);
+            dumper.setUriAsParameters(uriAsParameters);
+            dumper.setOutput(output);
+            dumper.dumpRoutes(format);
+        }
+        return new Result(true, null);
+    }
+
+    /** The Java sources of the files' folders, for the constants a route 
takes from another class. */
+    private static Map<String, Supplier<String>> javaSources(List<String> 
files) throws IOException {
+        Map<String, Supplier<String>> answer = new LinkedHashMap<>();
+        for (String f : files) {
+            Path dir = Path.of(f).toAbsolutePath().getParent();
+            if (dir == null) {
+                continue;
+            }
+            try (Stream<Path> list = Files.list(dir)) {
+                list.filter(p -> p.getFileName().toString().endsWith(".java"))
+                        .forEach(p -> answer.putIfAbsent(p.toString(), () -> 
read(p)));
+            }
+        }
+        return answer;
+    }
+
+    private static String read(Path p) {
+        try {
+            return Files.readString(p, StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            return null;
+        }
+    }
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
index 7a74d4924b3e..020f4d745822 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
@@ -82,6 +82,11 @@ public class TransformRoute extends CamelCommand {
                         description = "Whether to ignore route loading and 
compilation errors (use this with care!)")
     boolean ignoreLoadingError;
 
+    @CommandLine.Option(names = { "--compile" }, defaultValue = "false",
+                        description = "Compile and run Java routes to 
transform them. By default Java routes are read "
+                                      + "without compiling them, and compiled 
only when a route cannot be read that way")
+    boolean compile;
+
     @CommandLine.Mixin
     MavenResolverMixin mavenResolver;
 
@@ -108,6 +113,15 @@ public class TransformRoute extends CamelCommand {
         Files.deleteIfExists(Path.of(dump));
         final String target = dump;
 
+        if (!compile && !resolvePlaceholders && 
TransformJavaRoutes.applies(files)) {
+            // Java routes read without compiling them: in milliseconds, and 
no code of the project runs
+            TransformJavaRoutes.Result result = 
TransformJavaRoutes.transform(files, format, target, uriAsParameters);
+            if (result.transformed()) {
+                return printDump(target);
+            }
+            // a route the parser cannot read completely (a lambda, a value 
known only at runtime): compile them all
+        }
+
         Run run = new Run(getMain()) {
             @Override
             protected void doAddInitialProperty(KameletMain main) {
@@ -135,9 +149,13 @@ public class TransformRoute extends CamelCommand {
             return exit;
         }
 
+        return printDump(target);
+    }
+
+    private Integer printDump(String target) {
         if (output == null || "clipboard".equals(output)) {
             // load target file and print to console
-            dump = waitForDumpFile(Path.of(target));
+            String dump = waitForDumpFile(Path.of(target));
             if (dump != null) {
                 if ("clipboard".equals(output)) {
                     Clipboard c = 
Toolkit.getDefaultToolkit().getSystemClipboard();
@@ -155,14 +173,13 @@ public class TransformRoute extends CamelCommand {
         StopWatch watch = new StopWatch();
         while (watch.taken() < 5000) {
             try {
-                // give time for response to be ready
-                Thread.sleep(100);
-
                 if (Files.exists(dumpFile)) {
                     try (InputStream is = Files.newInputStream(dumpFile)) {
                         return IOHelper.loadText(is);
                     }
                 }
+                // give time for response to be ready
+                Thread.sleep(100);
             } catch (InterruptedException e) {
                 Thread.currentThread().interrupt();
             } catch (Exception e) {
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/TransformJavaRoutesTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/TransformJavaRoutesTest.java
new file mode 100644
index 000000000000..02192249a836
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/TransformJavaRoutesTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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.dsl.jbang.core.commands;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * CAMEL-25202: camel transform route reads Java routes without compiling 
them, and writes what the same routes compiled
+ * and dumped give.
+ */
+class TransformJavaRoutesTest {
+
+    private static final String ORDERS = """
+            import org.apache.camel.builder.RouteBuilder;
+
+            public class Orders extends RouteBuilder {
+                private static final String QUEUE = "orders";
+
+                @Override
+                public void configure() {
+                    from("direct:orders").routeId("intake").description("Order 
entry point")
+                        .setHeader("source").constant("web")
+                        .choice()
+                            .when(simple("${header.vip} == true"))
+                                .to("seda:" + QUEUE + "-vip")
+                            .otherwise()
+                                .to("seda:" + QUEUE)
+                        .end()
+                        .log("${body}");
+
+                    from("direct:audit").routeId("audit")
+                        .split(body().tokenize(","))
+                            .to("mock:audit")
+                        .end();
+                }
+            }
+            """;
+
+    /** What camel transform route wrote for these routes before, compiling 
them (Camel 4.23). */
+    private static final String YAML = """
+            - route:
+                id: intake
+                description: Order entry point
+                from:
+                  uri: direct
+                  parameters:
+                    name: orders
+                  steps:
+                    - setHeader:
+                        name: source
+                        expression:
+                          constant:
+                            expression: web
+                    - choice:
+                        when:
+                          - expression:
+                              simple:
+                                expression: "${header.vip} == true"
+                            steps:
+                              - to:
+                                  uri: seda
+                                  parameters:
+                                    name: orders-vip
+                        otherwise:
+                          steps:
+                            - to:
+                                uri: seda
+                                parameters:
+                                  name: orders
+                    - log:
+                        message: "${body}"
+            - route:
+                id: audit
+                from:
+                  uri: direct
+                  parameters:
+                    name: audit
+                  steps:
+                    - split:
+                        expression:
+                          expressionDefinition:
+                            expression: "tokenize(simple{${body}}, ,)"
+                        steps:
+                          - to:
+                              uri: mock
+                              parameters:
+                                name: audit
+            """;
+
+    @TempDir
+    Path dir;
+
+    @Test
+    void writesWhatCompilingTheRoutesGives() throws Exception {
+        Path source = Files.writeString(dir.resolve("Orders.java"), ORDERS);
+        Path out = dir.resolve("out.yaml");
+        TransformJavaRoutes.Result result = 
TransformJavaRoutes.transform(List.of(source.toString()), "yaml", 
out.toString(),
+                true);
+        assertThat(result.transformed()).as(result.reason()).isTrue();
+        assertThat(Files.readString(out)).isEqualToIgnoringNewLines(YAML);
+
+        Path xml = dir.resolve("out.xml");
+        assertThat(TransformJavaRoutes.transform(List.of(source.toString()), 
"xml", xml.toString(), true).transformed())
+                .isTrue();
+        assertThat(Files.readString(xml)).contains("<route id=\"intake\" 
description=\"Order entry point\">",
+                "<constant>web</constant>", "<to uri=\"seda:orders-vip\"/>");
+    }
+
+    @Test
+    void aDirectoryGetsAFileNamedAfterEachSource() throws Exception {
+        Path source = Files.writeString(dir.resolve("Orders.java"), ORDERS);
+        Path out = dir.resolve("out");
+        assertThat(TransformJavaRoutes.transform(List.of(source.toString()), 
"yaml", out.toString(), true).transformed())
+                .isTrue();
+        assertThat(out.resolve("Orders.yaml")).exists();
+    }
+
+    @Test
+    void aRouteThatCannotBeReadIsCompiled() throws Exception {
+        Path source = Files.writeString(dir.resolve("Hey.java"), """
+                public class Hey extends org.apache.camel.builder.RouteBuilder 
{
+                    @Override
+                    public void configure() {
+                        from("timer:java").process(e -> 
e.getMessage().setBody("Hello")).log("${body}");
+                    }
+                }
+                """);
+        Path out = dir.resolve("out.yaml");
+        TransformJavaRoutes.Result result = 
TransformJavaRoutes.transform(List.of(source.toString()), "yaml", 
out.toString(),
+                true);
+        assertThat(result.transformed()).isFalse();
+        assertThat(result.reason()).contains("Hey.java:4").contains("lambda");
+        assertThat(out).doesNotExist();
+    }
+
+    @Test
+    void onlyJavaSources() throws Exception {
+        Path java = Files.writeString(dir.resolve("Orders.java"), ORDERS);
+        Path yaml = Files.writeString(dir.resolve("r.camel.yaml"), "- route: 
{}");
+        
assertThat(TransformJavaRoutes.applies(List.of(java.toString()))).isTrue();
+        assertThat(TransformJavaRoutes.applies(List.of(java.toString(), 
yaml.toString()))).isFalse();
+        assertThat(TransformJavaRoutes.applies(List.of())).isFalse();
+    }
+}

Reply via email to