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

davsclaus pushed a commit to branch feature/CAMEL-23672-tui-diagram
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f045f778ddb58cc195245239be76544eb9951d75
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Jun 3 22:13:53 2026 +0200

    CAMEL-23672: camel-tui - Add uri field to ModelDumpLine and route structure 
JSON
    
    Enriched the dev console route-structure response with a dedicated uri
    field for endpoint-producing EIP nodes (from, to, toD, wireTap, etc).
    This replaces fragile parsing of the code[uri] format for route linking.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../apache/camel/diagram/RouteDiagramHelper.java   |  4 +++
 .../camel/diagram/RouteDiagramLayoutEngine.java    |  1 +
 .../java/org/apache/camel/spi/ModelDumpLine.java   |  3 +-
 .../impl/console/RouteStructureDevConsole.java     |  3 ++
 .../camel/impl/DefaultModelToStructureDumper.java  | 19 +++++++++----
 .../jbang/core/commands/tui/DiagramSupport.java    | 32 ++++++----------------
 .../commands/tui/diagram/RouteDiagramWidget.java   | 16 ++++-------
 7 files changed, 37 insertions(+), 41 deletions(-)

diff --git 
a/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramHelper.java
 
b/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramHelper.java
index 5ad89d4b11e4..6024a5d8a814 100644
--- 
a/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramHelper.java
+++ 
b/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramHelper.java
@@ -70,6 +70,10 @@ public final class RouteDiagramHelper {
                     node.type = line.getString("type");
                     node.id = line.getString("id");
                     node.code = Jsoner.unescape(line.getString("code"));
+                    String uri = line.getString("uri");
+                    if (uri != null) {
+                        node.uri = Jsoner.unescape(uri);
+                    }
                     node.description = line.getString("description");
                     Integer level = line.getInteger("level");
                     node.level = level != null ? level : 0;
diff --git 
a/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramLayoutEngine.java
 
b/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramLayoutEngine.java
index 851a6ca65d56..2c7cb558a427 100644
--- 
a/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramLayoutEngine.java
+++ 
b/components/camel-diagram/src/main/java/org/apache/camel/diagram/RouteDiagramLayoutEngine.java
@@ -154,6 +154,7 @@ public class RouteDiagramLayoutEngine {
         public String type;
         public String id;
         public String code;
+        public String uri;
         public String description;
         public int level;
         public StatInfo stat;
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/ModelDumpLine.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/ModelDumpLine.java
index 7f1e40646502..a5e0ba00eb7b 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/ModelDumpLine.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/ModelDumpLine.java
@@ -27,8 +27,9 @@ import org.jspecify.annotations.Nullable;
  * @param level       indent level of the EIP node
  * @param code        EIP code such as label or short name that is 
human-readable or pseudocode
  * @param description optional description of the EIP node
+ * @param uri         the raw endpoint URI for endpoint-producing EIP nodes 
(from, to, toD, wireTap, enrich, etc.)
  * @since             4.16
  */
 public record ModelDumpLine(@Nullable String location, String type, String id, 
int level, String code,
-        @Nullable String description) {
+        @Nullable String description, @Nullable String uri) {
 }
diff --git 
a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteStructureDevConsole.java
 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteStructureDevConsole.java
index a55dd747b06f..f8ab84fe6859 100644
--- 
a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteStructureDevConsole.java
+++ 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteStructureDevConsole.java
@@ -202,6 +202,9 @@ public class RouteStructureDevConsole extends 
AbstractDevConsole {
                 c.put("description", line.description());
             }
             c.put("code", Jsoner.escape(line.code()));
+            if (line.uri() != null) {
+                c.put("uri", Jsoner.escape(line.uri()));
+            }
 
             if (metric && mcc != null) {
                 if (counter <= 2) {
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModelToStructureDumper.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModelToStructureDumper.java
index 3389e5bf6355..e980ced54f7d 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModelToStructureDumper.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModelToStructureDumper.java
@@ -46,12 +46,15 @@ public class DefaultModelToStructureDumper implements 
ModelToStructureDumper {
 
         String loc = scheme + ":" + LoggerHelper.getLineNumberLoggerName(def);
         answer.add(
-                new ModelDumpLine(loc, "route", def.getRouteId(), 0, "route[" 
+ def.getRouteId() + "]", def.getDescription()));
+                new ModelDumpLine(
+                        loc, "route", def.getRouteId(), 0, "route[" + 
def.getRouteId() + "]", def.getDescription(),
+                        null));
         String uri = def.getInput().getLabel();
         if (brief) {
             uri = StringHelper.before(uri, "?", uri);
         }
-        answer.add(new ModelDumpLine(loc, "from", routeId, 1, "from[" + uri + 
"]", def.getDescription()));
+        String fromUri = def.getInput().getEndpointUri();
+        answer.add(new ModelDumpLine(loc, "from", routeId, 1, "from[" + uri + 
"]", def.getDescription(), fromUri));
 
         dumpChildren(def, scheme, brief, 2, answer);
 
@@ -69,11 +72,15 @@ public class DefaultModelToStructureDumper implements 
ModelToStructureDumper {
                 String id = output.getId();
                 boolean choice = "choice".equals(kind);
                 String code = choice || brief ? output.getShortName() : 
output.getLabel();
-                if (brief && output instanceof EndpointRequiredDefinition erd) 
{
-                    String uri = StringHelper.before(erd.getEndpointUri(), 
"?", erd.getEndpointUri());
-                    code = output.getShortName() + "[" + uri + "]";
+                String endpointUri = null;
+                if (output instanceof EndpointRequiredDefinition erd) {
+                    endpointUri = erd.getEndpointUri();
+                    if (brief) {
+                        String uri = StringHelper.before(endpointUri, "?", 
endpointUri);
+                        code = output.getShortName() + "[" + uri + "]";
+                    }
                 }
-                answer.add(new ModelDumpLine(loc, kind, id, level, code, 
output.getDescription()));
+                answer.add(new ModelDumpLine(loc, kind, id, level, code, 
output.getDescription(), endpointUri));
             }
             dumpChildren(child, scheme, brief, level + 1, answer);
         }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java
index 7c429eab91ca..8fd0464e085e 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java
@@ -594,7 +594,7 @@ class DiagramSupport {
                 && !"from".equals(type)) {
             return null;
         }
-        String baseUri = extractBaseUri(box.layoutNode().treeNode.info.code);
+        String baseUri = stripQueryParams(box.layoutNode().treeNode.info.uri);
         if (baseUri == null || baseUri.isBlank()) {
             return null;
         }
@@ -609,7 +609,7 @@ class DiagramSupport {
             } else {
                 // "to" node: find route that consumes FROM this endpoint
                 if (currentRouteId.equals(edge.from.routeId) && 
!currentRouteId.equals(edge.to.routeId)) {
-                    String targetFrom = extractBaseUri(edge.to.from);
+                    String targetFrom = stripQueryParams(edge.to.from);
                     if (baseUri.equals(targetFrom)) {
                         return edge.to.routeId;
                     }
@@ -617,7 +617,7 @@ class DiagramSupport {
             }
         }
 
-        // Fallback: match code against route "from" endpoints in routeLayouts
+        // Fallback: match uri against route "from" endpoints in routeLayouts
         if (!"from".equals(type)) {
             for (var entry : routeLayouts.entrySet()) {
                 if (currentRouteId.equals(entry.getKey())) {
@@ -627,7 +627,7 @@ class DiagramSupport {
                 if (!lr.nodes.isEmpty()) {
                     var firstNode = lr.nodes.get(0);
                     if ("from".equals(firstNode.type) && firstNode.treeNode != 
null) {
-                        String fromBaseUri = 
extractBaseUri(firstNode.treeNode.info.code);
+                        String fromBaseUri = 
stripQueryParams(firstNode.treeNode.info.uri);
                         if (baseUri.equals(fromBaseUri)) {
                             return entry.getKey();
                         }
@@ -638,24 +638,10 @@ class DiagramSupport {
         return null;
     }
 
-    /**
-     * Extracts the bare endpoint URI from a code field like 
"from[direct:foo?bar=baz]" or "to[kafka:topic]". Returns
-     * the base URI without query parameters.
-     */
-    static String extractBaseUri(String code) {
-        if (code == null) {
+    static String stripQueryParams(String uri) {
+        if (uri == null) {
             return null;
         }
-        // Strip type[...] wrapper
-        int open = code.indexOf('[');
-        int close = code.lastIndexOf(']');
-        String uri;
-        if (open >= 0 && close > open) {
-            uri = code.substring(open + 1, close);
-        } else {
-            uri = code;
-        }
-        // Strip query parameters
         int q = uri.indexOf('?');
         return q >= 0 ? uri.substring(0, q) : uri;
     }
@@ -765,7 +751,7 @@ class DiagramSupport {
         if (currentLayout != null && !currentLayout.nodes.isEmpty()) {
             var fromNode = currentLayout.nodes.get(0);
             if ("from".equals(fromNode.type) && fromNode.treeNode != null) {
-                currentFromUri = extractBaseUri(fromNode.treeNode.info.code);
+                currentFromUri = stripQueryParams(fromNode.treeNode.info.uri);
             }
         }
 
@@ -778,7 +764,7 @@ class DiagramSupport {
                 // Add "from" URIs of other routes (linkable from "to" nodes)
                 var firstNode = lr.nodes.get(0);
                 if ("from".equals(firstNode.type) && firstNode.treeNode != 
null) {
-                    String uri = extractBaseUri(firstNode.treeNode.info.code);
+                    String uri = stripQueryParams(firstNode.treeNode.info.uri);
                     if (uri != null) {
                         endpoints.add(uri);
                     }
@@ -789,7 +775,7 @@ class DiagramSupport {
                         String type = node.type;
                         if (("to".equals(type) || "toD".equals(type) || 
"wireTap".equals(type))
                                 && node.treeNode != null) {
-                            String uri = 
extractBaseUri(node.treeNode.info.code);
+                            String uri = 
stripQueryParams(node.treeNode.info.uri);
                             if (currentFromUri.equals(uri)) {
                                 endpoints.add(currentFromUri);
                             }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/diagram/RouteDiagramWidget.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/diagram/RouteDiagramWidget.java
index 7d8cd4cb827d..8762935f9536 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/diagram/RouteDiagramWidget.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/diagram/RouteDiagramWidget.java
@@ -429,19 +429,13 @@ public class RouteDiagramWidget implements Widget {
                 && !"from".equals(type)) {
             return false;
         }
-        String baseUri = extractBaseUri(node.treeNode.info.code);
-        return baseUri != null && linkableEndpoints.contains(baseUri);
-    }
-
-    private static String extractBaseUri(String code) {
-        if (code == null) {
-            return null;
+        String uri = node.treeNode.info.uri;
+        if (uri == null) {
+            return false;
         }
-        int open = code.indexOf('[');
-        int close = code.lastIndexOf(']');
-        String uri = (open >= 0 && close > open) ? code.substring(open + 1, 
close) : code;
         int q = uri.indexOf('?');
-        return q >= 0 ? uri.substring(0, q) : uri;
+        String baseUri = q >= 0 ? uri.substring(0, q) : uri;
+        return linkableEndpoints.contains(baseUri);
     }
 
     private int toRow(int pixelY) {

Reply via email to