SysmonAdapters.java
package com.guinetik.hexafun.examples.sysmon;
import java.util.function.Function;
import static com.guinetik.hexafun.examples.tui.Ansi.*;
import static com.guinetik.hexafun.examples.tui.Widgets.*;
/**
* Output adapters for SystemMetrics - transforms domain data to presentation formats.
*
* <p>This is where the hexagonal architecture shines: same domain object,
* four completely different presentations. The domain knows nothing about
* how it will be displayed.</p>
*
* <h2>Available Formats</h2>
* <ul>
* <li><b>TUI</b> - Colorful progress bars with warnings</li>
* <li><b>CLI</b> - Plain text for scripting</li>
* <li><b>JSON</b> - Machine-readable</li>
* <li><b>Prometheus</b> - Metrics exposition format</li>
* </ul>
*/
public final class SysmonAdapters {
private SysmonAdapters() {}
private static final int BAR_WIDTH = 20;
private static final int BOX_WIDTH = 36;
// ═══════════════════════════════════════════════════════════════════
// TUI ADAPTER - Colorful gauges with box drawing
// ═══════════════════════════════════════════════════════════════════
/**
* TUI format with colorful progress bars and warning indicators.
*
* <pre>
* ┌─ System Monitor ─────────────────┐
* │ CPU [████████░░░░░░░░░░░░] 67% │
* │ MEM [██████████░░░░░░░░░░] 52% │
* │ DISK [██████████████████░░] 91% ⚠│
* └──────────────────────────────────┘
* </pre>
*/
public static final Function<SystemMetrics, String> TUI_ADAPTER = metrics -> {
StringBuilder sb = new StringBuilder();
String indent = " ";
// Header
sb.append(indent).append(color(BOX_TOP_LEFT + "─ System Monitor " +
repeat(BOX_HORIZONTAL, BOX_WIDTH - 19) + BOX_TOP_RIGHT, CYAN)).append("\n");
// CPU gauge
sb.append(indent).append(color(BOX_VERTICAL, CYAN))
.append(gauge("CPU ", metrics.cpu(), metrics.cpuWarning()))
.append(color(BOX_VERTICAL, CYAN)).append("\n");
// Memory gauge
sb.append(indent).append(color(BOX_VERTICAL, CYAN))
.append(gauge("MEM ", metrics.memory(), metrics.memoryWarning()))
.append(color(BOX_VERTICAL, CYAN)).append("\n");
// Disk gauge
sb.append(indent).append(color(BOX_VERTICAL, CYAN))
.append(gauge("DISK", metrics.disk(), metrics.diskWarning()))
.append(color(BOX_VERTICAL, CYAN)).append("\n");
// Footer
sb.append(indent).append(color(BOX_BOTTOM_LEFT + repeat(BOX_HORIZONTAL, BOX_WIDTH - 2) +
BOX_BOTTOM_RIGHT, CYAN)).append("\n");
return sb.toString();
};
/**
* Build a single gauge line with color-coded bar.
*/
private static String gauge(String label, double percent, boolean warning) {
int filled = (int) ((BAR_WIDTH * percent) / 100);
int empty = BAR_WIDTH - filled;
String barColor = warning ? RED : GREEN;
String warnIcon = warning ? color(" ⚠", YELLOW) : " ";
return " " + color(label, BOLD) + " " +
color("[", DIM) +
color(repeat(BLOCK_FULL, filled), barColor) +
color(repeat(BLOCK_LIGHT, empty), BRIGHT_BLACK) +
color("]", DIM) +
color(String.format(" %3.0f%%", percent), warning ? RED : WHITE) +
warnIcon + " ";
}
// ═══════════════════════════════════════════════════════════════════
// CLI ADAPTER - Plain text for scripting
// ═══════════════════════════════════════════════════════════════════
/**
* CLI format - simple key: value pairs for shell scripts.
*
* <pre>
* cpu: 67%
* mem: 52%
* disk: 91%
* </pre>
*/
public static final Function<SystemMetrics, String> CLI_ADAPTER = metrics ->
String.format("cpu: %.0f%%\nmem: %.0f%%\ndisk: %.0f%%\n",
metrics.cpu(), metrics.memory(), metrics.disk());
// ═══════════════════════════════════════════════════════════════════
// JSON ADAPTER - Machine readable
// ═══════════════════════════════════════════════════════════════════
/**
* JSON format for APIs and data interchange (pretty-printed).
*
* <pre>
* {
* "cpu": 67.0,
* "memory": 52.0,
* "disk": 91.0,
* "warnings": ["disk"]
* }
* </pre>
*/
public static final Function<SystemMetrics, String> JSON_ADAPTER = metrics -> {
StringBuilder warnings = new StringBuilder("[");
boolean first = true;
if (metrics.cpuWarning()) {
warnings.append("\"cpu\"");
first = false;
}
if (metrics.memoryWarning()) {
if (!first) warnings.append(", ");
warnings.append("\"memory\"");
first = false;
}
if (metrics.diskWarning()) {
if (!first) warnings.append(", ");
warnings.append("\"disk\"");
}
warnings.append("]");
return String.format(
"{\n \"cpu\": %.1f,\n \"memory\": %.1f,\n \"disk\": %.1f,\n \"warnings\": %s\n}\n",
metrics.cpu(), metrics.memory(), metrics.disk(), warnings
);
};
// ═══════════════════════════════════════════════════════════════════
// PROMETHEUS ADAPTER - Metrics exposition format
// ═══════════════════════════════════════════════════════════════════
/**
* Prometheus exposition format for monitoring systems.
*
* <pre>
* # HELP system_cpu_percent Current CPU usage percentage
* # TYPE system_cpu_percent gauge
* system_cpu_percent 67.0
* # HELP system_memory_percent Current memory usage percentage
* # TYPE system_memory_percent gauge
* system_memory_percent 52.0
* # HELP system_disk_percent Current disk usage percentage
* # TYPE system_disk_percent gauge
* system_disk_percent 91.0
* </pre>
*/
public static final Function<SystemMetrics, String> PROMETHEUS_ADAPTER = metrics -> {
StringBuilder sb = new StringBuilder();
sb.append("# HELP system_cpu_percent Current CPU usage percentage\n");
sb.append("# TYPE system_cpu_percent gauge\n");
sb.append(String.format("system_cpu_percent %.1f\n", metrics.cpu()));
sb.append("# HELP system_memory_percent Current memory usage percentage\n");
sb.append("# TYPE system_memory_percent gauge\n");
sb.append(String.format("system_memory_percent %.1f\n", metrics.memory()));
sb.append("# HELP system_disk_percent Current disk usage percentage\n");
sb.append("# TYPE system_disk_percent gauge\n");
sb.append(String.format("system_disk_percent %.1f\n", metrics.disk()));
return sb.toString();
};
}