gnodet-bot commented on code in PR #27560:
URL: https://github.com/apache/camel/pull/27560#discussion_r4217511165
##########
dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/diagram/TopologyDiagramWidget.java:
##########
@@ -254,14 +277,119 @@ public void render(Rect area, Buffer buffer) {
for (TopologyLayoutNode node : layout.nodes) {
drawNode(buffer, area, node);
}
+
+ if (errorLayer != null) {
+ drawErrorLabels(buffer, area);
+ }
+ drawErrorMarks(buffer, area);
+ }
+
+ /** A mark on the border of each route with error handling (shown in the
frame, or hidden until x). */
+ private void drawErrorMarks(Buffer buffer, Rect area) {
+ for (TopologyLayoutNode node : layout.nodes) {
+ if (node.routeId != null && errorMarks.contains(node.routeId) &&
!inFrame(node)) {
+ int col = toCol(node.x) + boxWidth - 3;
+ writeText(buffer, area, toRow(node.y), col, "\u26a1",
errorStyle().dim());
+ }
+ }
+ }
+
+ private Style errorStyle() {
+ return Theme.warning();
+ }
+
+ private boolean inFrame(TopologyLayoutNode node) {
+ return errorLayer != null && node.routeId != null &&
errorLayer.routeIds().contains(node.routeId);
+ }
+
+ private TopologyLayoutNode nodeOf(String routeId) {
+ for (TopologyLayoutNode n : layout.nodes) {
+ if (routeId != null && routeId.equals(n.routeId)) {
+ return n;
+ }
+ }
+ return null;
+ }
+
+ /** The frame of the error handling: from its top to the bottom of the
diagram, as wide as the diagram. */
+ private void drawErrorFrame(Buffer buffer, Rect area) {
+ int top = toRow(errorLayer.frameTopY());
+ int bottom = toRow(layout.totalHeight) - 1;
+ int right = getTotalCols() - 2;
+ Style s = errorStyle().dim();
+ for (int c = 1; c < right; c++) {
+ setChar(buffer, area, top, c, DASH_H, s);
+ setChar(buffer, area, bottom, c, DASH_H, s);
+ }
+ for (int r = top + 1; r < bottom; r++) {
+ setChar(buffer, area, r, 0, DASH_V, s);
+ setChar(buffer, area, r, right, DASH_V, s);
+ }
+ setChar(buffer, area, top, 0, '\u256d', s);
+ setChar(buffer, area, top, right, '\u256e', s);
+ setChar(buffer, area, bottom, 0, '\u2570', s);
+ setChar(buffer, area, bottom, right, '\u256f', s);
+ writeText(buffer, area, top, 2, " Error handling ",
errorStyle().bold());
+ }
+
+ /**
+ * The label lines under each route of the frame: where its failures come
from and how they are handled, one line
+ * per route that sends there.
+ */
+ private Map<TopologyLayoutNode, List<String>> errorLabels() {
+ Map<TopologyLayoutNode, List<String>> answer = new
java.util.LinkedHashMap<>();
+ if (errorLayer == null) {
+ return answer;
+ }
+ for (TopologyLayoutNode node : layout.nodes) {
+ if (!inFrame(node)) {
+ continue;
+ }
+ Map<String, List<String>> bySource = new
java.util.LinkedHashMap<>();
+ for (ErrorLayer.ErrorPath p : errorLayer.paths()) {
+ if (node.routeId.equals(p.toRouteId())) {
+ bySource.computeIfAbsent(p.fromRouteId(), k -> new
ArrayList<>()).add(p.label());
+ }
+ }
+ List<String> lines = new ArrayList<>();
+ for (Map.Entry<String, List<String>> e : bySource.entrySet()) {
+ String how = String.join(" \u00b7 ", e.getValue());
+ lines.add(e.getKey().equals(node.routeId)
+ ? "\u26a0 own failures: " + how
+ : "\u25c2 " + e.getKey() + ": " + how);
+ }
+ answer.put(node, lines);
+ }
+ return answer;
+ }
+
+ private void drawErrorLabels(Buffer buffer, Rect area) {
+ for (Map.Entry<TopologyLayoutNode, List<String>> e :
errorLabels().entrySet()) {
+ int row = toRow(e.getKey().y) + boxHeight(e.getKey());
+ int col = toCol(e.getKey().x);
+ for (String line : e.getValue()) {
+ writeText(buffer, area, row++, col, line, errorStyle());
+ }
+ }
+ }
+
+ /** The column right of the widest label of the error frame, so the frame
and the scrolling take it in. */
+ private int errorLabelsRight() {
+ int right = 0;
+ for (Map.Entry<TopologyLayoutNode, List<String>> e :
errorLabels().entrySet()) {
+ for (String line : e.getValue()) {
+ right = Math.max(right, toCol(e.getKey().x) + line.length() +
2);
+ }
+ }
+ return right;
}
public int getTotalRows() {
return toRow(layout.totalHeight) + 10;
}
public int getTotalCols() {
- return toCol(layout.totalWidth) + boxWidth + 4;
+ return Math.max(toCol(layout.totalWidth) + boxWidth + 4,
errorLabelsRight() + 2);
Review Comment:
⚠️ **Minor:** `getTotalCols()` calls `errorLabelsRight()` which in turn
calls `errorLabels()` (rebuilding the full map). `render()` also calls
`drawErrorLabels()` which calls `errorLabels()` directly. That's two full map
rebuilds per frame. Since the error layer data only changes when
`setErrorLayer()` is called, consider caching the result — e.g. compute and
store it in `setErrorLayer()` — so `render()` and `getTotalCols()` both read a
pre-built structure rather than recomputing it on every repaint.
##########
core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultRouteTopologyDumper.java:
##########
@@ -89,6 +105,49 @@ public TopologyResult dumpTopology(CamelContext context) {
return new TopologyResult(nodes, edges, externalEndpoints);
}
+ private static void addEdges(
+ CamelContext context, List<TopologyEdge> edges, Map<String,
List<String>> inputUriToRouteIds,
+ String fromRouteId, String uri, String kind, String via, String
handling) {
+ String outputUri = normalizeUri(context, uri);
+ List<String> targetRouteIds = inputUriToRouteIds.get(outputUri);
+ if (targetRouteIds != null) {
+ String scheme = extractScheme(outputUri);
+ String connType = INTERNAL_SCHEMES.contains(scheme) ? "internal" :
"external";
+ for (String targetId : targetRouteIds) {
+ edges.add(new TopologyEdge(fromRouteId, targetId, outputUri,
connType, kind, via, handling));
+ }
+ }
+ }
+
+ /**
+ * What an onException clause does with the failure: continued, handled or
not handled (a side trip, the failure
+ * goes on to the caller); null when a predicate decides it at runtime.
+ */
+ private static String handling(OnExceptionDefinition oe) {
+ Boolean continued = constant(oe.getContinued());
+ Boolean handled = constant(oe.getHandled());
+ if (Boolean.TRUE.equals(continued)) {
+ return HANDLING_CONTINUED;
+ }
+ if (Boolean.TRUE.equals(handled)) {
+ return HANDLING_HANDLED;
+ }
+ boolean decidedAtRuntime = oe.getContinued() != null && continued ==
null
+ || oe.getHandled() != null && handled == null;
Review Comment:
💡 **Suggestion:** `&&` binds tighter than `||` in Java, so the logic is
correct, but explicit parentheses remove any doubt for future readers:
```suggestion
boolean decidedAtRuntime = (oe.getContinued() != null && continued
== null)
|| (oe.getHandled() != null && handled == null);
```
--
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]