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 b1ece4be57a293bd4a965cd7970e351e01d1af3c Author: Claus Ibsen <[email protected]> AuthorDate: Wed Jun 3 22:08:49 2026 +0200 CAMEL-23672: camel-tui - Fix link indicator by extracting URI from code field The code field uses format type[uri] (e.g. from[direct:foo]) but URI matching compared the wrapped strings directly. Added extractBaseUri() to strip the type wrapper and query parameters before matching. Co-Authored-By: Claude Opus 4.6 <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../jbang/core/commands/tui/DiagramSupport.java | 84 ++++++++++++---------- .../commands/tui/diagram/RouteDiagramWidget.java | 17 +++-- 2 files changed, 59 insertions(+), 42 deletions(-) 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 0b5842383c53..7c429eab91ca 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,8 +594,8 @@ class DiagramSupport { && !"from".equals(type)) { return null; } - String code = box.layoutNode().treeNode.info.code; - if (code == null || code.isBlank()) { + String baseUri = extractBaseUri(box.layoutNode().treeNode.info.code); + if (baseUri == null || baseUri.isBlank()) { return null; } @@ -609,9 +609,8 @@ class DiagramSupport { } else { // "to" node: find route that consumes FROM this endpoint if (currentRouteId.equals(edge.from.routeId) && !currentRouteId.equals(edge.to.routeId)) { - // Match endpoint URI against the target route's from - String targetFrom = edge.to.from; - if (targetFrom != null && uriMatches(code, targetFrom)) { + String targetFrom = extractBaseUri(edge.to.from); + if (baseUri.equals(targetFrom)) { return edge.to.routeId; } } @@ -628,8 +627,8 @@ class DiagramSupport { if (!lr.nodes.isEmpty()) { var firstNode = lr.nodes.get(0); if ("from".equals(firstNode.type) && firstNode.treeNode != null) { - String fromCode = firstNode.treeNode.info.code; - if (fromCode != null && uriMatches(code, fromCode)) { + String fromBaseUri = extractBaseUri(firstNode.treeNode.info.code); + if (baseUri.equals(fromBaseUri)) { return entry.getKey(); } } @@ -639,11 +638,26 @@ class DiagramSupport { return null; } - private static boolean uriMatches(String toUri, String fromUri) { - // Normalize: strip query parameters for matching - String toBase = toUri.contains("?") ? toUri.substring(0, toUri.indexOf('?')) : toUri; - String fromBase = fromUri.contains("?") ? fromUri.substring(0, fromUri.indexOf('?')) : fromUri; - return toBase.equals(fromBase); + /** + * 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) { + 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; } void selectEipNodeUp() { @@ -746,6 +760,15 @@ class DiagramSupport { */ private Set<String> computeLinkableEndpoints(String currentRouteId) { Set<String> endpoints = new HashSet<>(); + String currentFromUri = null; + var currentLayout = routeLayouts.get(currentRouteId); + 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); + } + } + for (var entry : routeLayouts.entrySet()) { if (currentRouteId.equals(entry.getKey())) { continue; @@ -755,33 +778,20 @@ 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 code = firstNode.treeNode.info.code; - if (code != null) { - endpoints.add(code.contains("?") ? code.substring(0, code.indexOf('?')) : code); + String uri = extractBaseUri(firstNode.treeNode.info.code); + if (uri != null) { + endpoints.add(uri); } } - // Add "to" URIs of other routes (linkable from "from" node) - for (var node : lr.nodes) { - String type = node.type; - if (("to".equals(type) || "toD".equals(type) || "wireTap".equals(type)) - && node.treeNode != null) { - String code = node.treeNode.info.code; - if (code != null) { - String baseUri = code.contains("?") ? code.substring(0, code.indexOf('?')) : code; - // Check if this targets our route's "from" endpoint - var currentLayout = routeLayouts.get(currentRouteId); - if (currentLayout != null && !currentLayout.nodes.isEmpty()) { - var fromNode = currentLayout.nodes.get(0); - if ("from".equals(fromNode.type) && fromNode.treeNode != null) { - String fromCode = fromNode.treeNode.info.code; - if (fromCode != null) { - String fromBase = fromCode.contains("?") - ? fromCode.substring(0, fromCode.indexOf('?')) : fromCode; - if (baseUri.equals(fromBase)) { - endpoints.add(fromBase); - } - } - } + // Add "to" URIs that target our "from" endpoint (linkable from "from" node) + if (currentFromUri != null) { + for (var node : lr.nodes) { + String type = node.type; + if (("to".equals(type) || "toD".equals(type) || "wireTap".equals(type)) + && node.treeNode != null) { + String uri = extractBaseUri(node.treeNode.info.code); + 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 0d82aebc907d..7d8cd4cb827d 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,12 +429,19 @@ public class RouteDiagramWidget implements Widget { && !"from".equals(type)) { return false; } - String code = node.treeNode.info.code; - if (code == null || code.isBlank()) { - 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 baseUri = code.contains("?") ? code.substring(0, code.indexOf('?')) : code; - return linkableEndpoints.contains(baseUri); + 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; } private int toRow(int pixelY) {
