diff --git a/build.gradle b/build.gradle index 4a66efc..6342a58 100644 --- a/build.gradle +++ b/build.gradle @@ -32,11 +32,14 @@ repositories { dependencies { implementation('net.dv8tion:JDA:5.0.0-beta.21') + compileOnly('dev.latvian.apps:ansi:1.0.0-build.2') implementation('dev.latvian.apps:tiny-java-server:1.0.0-build.7') implementation('org.mongodb:mongodb-driver-sync:5.0.0') // implementation('org.slf4j:slf4j-simple:2.0.5') // implementation('com.google.guava:guava:31.1-jre') { exclude group: "com.google.code.findbugs" } compileOnly('org.jetbrains:annotations:24.0.1') + + testImplementation('dev.latvian.apps:ansi:1.0.0-build.2') testImplementation('org.junit.jupiter:junit-jupiter-api:5.10.0') testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.10.0') testImplementation('junit:junit:4.13.2') diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/Ansi.java b/src/main/java/dev/latvian/apps/webutils/ansi/Ansi.java deleted file mode 100644 index 3013627..0000000 --- a/src/main/java/dev/latvian/apps/webutils/ansi/Ansi.java +++ /dev/null @@ -1,215 +0,0 @@ -package dev.latvian.apps.webutils.ansi; - -import dev.latvian.apps.webutils.json.JSON; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; -import java.util.regex.Pattern; - -/** - * See ANSI Escape Sequences - */ -public interface Ansi { - Pattern PATTERN = Pattern.compile("\u001B\\[(?:\\d;)?\\d+[mD]"); - char CHAR = '\u001B'; - - String[] COLOR_NAMES = { - "black", - "darkRed", - "green", - "orange", - "navy", - "purple", - "teal", - "lightGray", - "darkGray", - "red", - "lime", - "yellow", - "blue", - "magenta", - "cyan", - "white", - }; - - static AnsiComponent of() { - return new AnsiComponent(""); - } - - static AnsiComponent of(Object text) { - return text instanceof AnsiComponent ac ? ac : new AnsiComponent(text); - } - - static AnsiComponent ofObject(Object object) { - return ofObject0(object, 0); - } - - private static AnsiComponent ofObject0(@Nullable Object object, int depth) { - if (object == null || object == JSON.NULL) { - return Ansi.darkRed("null"); - } else if (object instanceof Map map) { - var builder = Ansi.of().treeColor(depth); - builder.append('{'); - boolean first = true; - - for (var entry : map.entrySet()) { - if (first) { - first = false; - } else { - builder.append(','); - } - - builder.append(Ansi.cyan("\"" + entry.getKey() + "\"")); - builder.append(':'); - builder.append(ofObject0(entry.getValue(), depth + 1)); - } - - builder.append('}'); - return builder; - } else if (object instanceof Iterable itr) { - var builder = Ansi.of(); - builder.append('['); - boolean first = true; - - for (var e : itr) { - if (first) { - first = false; - } else { - builder.append(','); - } - - builder.append(ofObject0(e, depth + 1)); - } - - builder.append(']'); - return builder; - } else if (object instanceof CharSequence) { - return Ansi.orange("\"" + object + "\""); - } else if (object instanceof Boolean b) { - return b ? Ansi.green("true") : Ansi.red("false"); - } else if (object instanceof Number) { - return Ansi.purple(object); - } else if (object.getClass().isRecord()) { - var builder = Ansi.of().treeColor(depth); - builder.append('{'); - boolean first = true; - - for (var component : object.getClass().getRecordComponents()) { - if (first) { - first = false; - } else { - builder.append(','); - } - - builder.append(Ansi.cyan("\"" + component.getName() + "\"")); - builder.append(':'); - - try { - builder.append(ofObject0(component.getAccessor().invoke(object), depth + 1)); - } catch (Exception ex) { - builder.append(darkRed("").whiteBg()); - ex.printStackTrace(); - } - } - - builder.append('}'); - return builder; - } else if (object.getClass().isEnum()) { - return Ansi.orange(object); - } else { - return Ansi.lightGray(object.toString()); - } - } - - static AnsiComponent bold(Object text) { - return of(text).bold(); - } - - static AnsiComponent italic(Object text) { - return of(text).italic(); - } - - static AnsiComponent underline(Object text) { - return of(text).underline(); - } - - static AnsiComponent blink(Object text) { - return of(text).blink(); - } - - static AnsiComponent reverse(Object text) { - return of(text).reverse(); - } - - static AnsiComponent hidden(Object text) { - return of(text).hidden(); - } - - static AnsiComponent strikethrough(Object text) { - return of(text).strikethrough(); - } - - static AnsiComponent black(Object text) { - return of(text).black(); - } - - static AnsiComponent darkRed(Object text) { - return of(text).darkRed(); - } - - static AnsiComponent green(Object text) { - return of(text).green(); - } - - static AnsiComponent orange(Object text) { - return of(text).orange(); - } - - static AnsiComponent navy(Object text) { - return of(text).navy(); - } - - static AnsiComponent purple(Object text) { - return of(text).purple(); - } - - static AnsiComponent teal(Object text) { - return of(text).teal(); - } - - static AnsiComponent lightGray(Object text) { - return of(text).lightGray(); - } - - static AnsiComponent darkGray(Object text) { - return of(text).darkGray(); - } - - static AnsiComponent red(Object text) { - return of(text).red(); - } - - static AnsiComponent lime(Object text) { - return of(text).lime(); - } - - static AnsiComponent yellow(Object text) { - return of(text).yellow(); - } - - static AnsiComponent blue(Object text) { - return of(text).blue(); - } - - static AnsiComponent magenta(Object text) { - return of(text).magenta(); - } - - static AnsiComponent cyan(Object text) { - return of(text).cyan(); - } - - static AnsiComponent white(Object text) { - return of(text).white(); - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiAppendable.java b/src/main/java/dev/latvian/apps/webutils/ansi/AnsiAppendable.java deleted file mode 100644 index 92a4d72..0000000 --- a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiAppendable.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.latvian.apps.webutils.ansi; - -public interface AnsiAppendable { - void appendAnsi(StringBuilder builder, AnsiContext ctx); - - default String toAnsiString() { - var builder = new StringBuilder(); - appendAnsi(builder, AnsiContext.NONE); - return builder.toString(); - } - - default String toDebugString() { - var builder = new StringBuilder(); - appendAnsi(builder, new AnsiContext(1)); - return builder.toString(); - } - - default String toUnformattedString() { - var builder = new StringBuilder(); - appendAnsi(builder, AnsiContext.UNFORMATTED); - return builder.toString(); - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiCode.java b/src/main/java/dev/latvian/apps/webutils/ansi/AnsiCode.java deleted file mode 100644 index b0bb6f9..0000000 --- a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiCode.java +++ /dev/null @@ -1,28 +0,0 @@ -package dev.latvian.apps.webutils.ansi; - -public enum AnsiCode implements AnsiAppendable { - RESET("[0m"), - LEFT("[1000D"), - BOLD("[1m"), - UNDERLINE("[4m"), - REVERSE("[7m"); - - public final String code; - - AnsiCode(String c) { - code = c; - } - - @Override - public void appendAnsi(StringBuilder builder, AnsiContext ctx) { - if (!ctx.unformatted()) { - builder.append(ctx.debug() ? '§' : Ansi.CHAR); - builder.append(code); - } - } - - @Override - public String toString() { - return Ansi.CHAR + code; - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiComponent.java b/src/main/java/dev/latvian/apps/webutils/ansi/AnsiComponent.java deleted file mode 100644 index 29e5653..0000000 --- a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiComponent.java +++ /dev/null @@ -1,426 +0,0 @@ -package dev.latvian.apps.webutils.ansi; - -import java.util.ArrayList; -import java.util.List; - -public class AnsiComponent implements AnsiAppendable { - public AnsiComponent parent = null; - public String text; - private int color = -1; - private int bgColor = -1; - private int bold = -1; - private int italic = -1; - private int underline = -1; - private int blink = -1; - private int reverse = -1; - private int hidden = -1; - private int strikethrough = -1; - private List children; - - public AnsiComponent(Object text) { - this.text = String.valueOf(text); - } - - private static boolean appendMode(StringBuilder builder, boolean semi, int prevMode, int mode, char code, char resetCode, AnsiContext ctx, String debug) { - if (prevMode != mode) { - if (semi) { - builder.append(';'); - } - - if (ctx.debug()) { - if (mode == 1) { - builder.append(debug); - } else { - builder.append('!'); - builder.append(debug); - } - } else if (mode == 1) { - builder.append(code); - } else { - builder.append('2'); - builder.append(resetCode); - } - - return true; - } - - return semi; - } - - private static boolean appendColor(StringBuilder builder, boolean semi, int prevColor, int color, char code, String brightCode, AnsiContext ctx) { - if (prevColor != color) { - if (semi) { - builder.append(';'); - } - - if (ctx.debug()) { - if (color == -1) { - builder.append("!color"); - } else if (color >= 0 && color < 16) { - builder.append(Ansi.COLOR_NAMES[color]); - } else { - builder.append("#%06X".formatted(color & 0xFFFFFF)); - } - - return true; - } - - int a = (color >> 24) & 0xFF; - int r = (color >> 16) & 0xFF; - int g = (color >> 8) & 0xFF; - int b = color & 0xFF; - - if (color == -1) { - builder.append(code); - builder.append('9'); - } else if (a == 255) { - builder.append(code); - builder.append("8;2;"); - builder.append(r); - builder.append(';'); - builder.append(g); - builder.append(';'); - builder.append(b); - } else if (color < 8) { - builder.append(code); - builder.append((char) (color + '0')); - } else if (color < 16) { - builder.append(brightCode); - builder.append((char) (color - 8 + '0')); - } else { - builder.append(code); - builder.append("8;5;"); - builder.append(color); - } - - return true; - } - - return semi; - } - - @Override - public void appendAnsi(StringBuilder builder, AnsiContext ctx) { - if (ctx.unformatted()) { - if (!text.isEmpty()) { - builder.append(text); - } - - if (children != null) { - for (var c : children) { - c.appendAnsi(builder, ctx); - } - } - - return; - } - - int pColor = parent == null ? -1 : parent.color; - int pBgColor = parent == null ? -1 : parent.bgColor; - int pBold = parent == null ? -1 : parent.bold; - int pItalic = parent == null ? -1 : parent.italic; - int pUnderline = parent == null ? -1 : parent.underline; - int pBlink = parent == null ? -1 : parent.blink; - int pReverse = parent == null ? -1 : parent.reverse; - int pHidden = parent == null ? -1 : parent.hidden; - int pStrikethrough = parent == null ? -1 : parent.strikethrough; - boolean changed = color != pColor || bgColor != pBgColor || bold != pBold || italic != pItalic || underline != pUnderline || blink != pBlink || reverse != pReverse || hidden != pHidden || strikethrough != pStrikethrough; - - if (changed) { - builder.append(Ansi.CHAR); - - if (ctx.debug()) { - builder.append("[9").append((ctx.index++ & 3) + 1).append("m§"); - } - - builder.append('['); - boolean semi = false; - semi = appendColor(builder, semi, pColor, color, '3', "9", ctx); - semi = appendColor(builder, semi, pBgColor, bgColor, '4', "10", ctx); - semi = appendMode(builder, semi, pBold, bold, '1', '2', ctx, "bold"); - semi = appendMode(builder, semi, pItalic, italic, '3', '3', ctx, "italic"); - semi = appendMode(builder, semi, pUnderline, underline, '4', '4', ctx, "underline"); - semi = appendMode(builder, semi, pBlink, blink, '5', '5', ctx, "blink"); - semi = appendMode(builder, semi, pReverse, reverse, '7', '7', ctx, "reverse"); - semi = appendMode(builder, semi, pHidden, hidden, '8', '8', ctx, "hidden"); - semi = appendMode(builder, semi, pStrikethrough, strikethrough, '9', '9', ctx, "strikethrough"); - - if (ctx.debug()) { - builder.append(']'); - builder.append(Ansi.CHAR); - builder.append(AnsiCode.RESET.code); - } else { - builder.append('m'); - } - } - - if (!text.isEmpty()) { - builder.append(text); - } - - if (children != null) { - for (var c : children) { - c.appendAnsi(builder, ctx); - } - } - - if (changed) { - builder.append(Ansi.CHAR); - - if (ctx.debug()) { - builder.append("[9").append((ctx.index++ & 3) + 1).append("m§"); - } - - builder.append('['); - boolean semi = false; - semi = appendColor(builder, semi, color, pColor, '3', "9", ctx); - semi = appendColor(builder, semi, bgColor, pBgColor, '4', "10", ctx); - semi = appendMode(builder, semi, bold, pBold, '1', '2', ctx, "bold"); - semi = appendMode(builder, semi, italic, pItalic, '3', '3', ctx, "italic"); - semi = appendMode(builder, semi, underline, pUnderline, '4', '4', ctx, "underline"); - semi = appendMode(builder, semi, blink, pBlink, '5', '5', ctx, "blink"); - semi = appendMode(builder, semi, reverse, pReverse, '7', '7', ctx, "reverse"); - semi = appendMode(builder, semi, hidden, pHidden, '8', '8', ctx, "hidden"); - semi = appendMode(builder, semi, strikethrough, pStrikethrough, '9', '9', ctx, "strikethrough"); - - if (ctx.debug()) { - builder.append(']'); - builder.append(Ansi.CHAR); - builder.append(AnsiCode.RESET.code); - } else { - builder.append('m'); - } - } - } - - @Override - public String toString() { - return toAnsiString(); - } - - public AnsiComponent end() { - return parent; - } - - public AnsiComponent append(Object text) { - var c = text instanceof AnsiComponent ac ? ac : new AnsiComponent(text); - c.parent = this; - - if (children == null) { - children = new ArrayList<>(1); - } - - if (c.color == -1) { - c.color = color; - } - - if (c.bgColor == -1) { - c.bgColor = bgColor; - } - - c.bold |= bold; - c.italic |= italic; - c.underline |= underline; - c.blink |= blink; - c.reverse |= reverse; - c.hidden |= hidden; - c.strikethrough |= strikethrough; - children.add(c); - return this; - } - - public AnsiComponent bold() { - bold = 1; - return this; - } - - public AnsiComponent italic() { - italic = 1; - return this; - } - - public AnsiComponent underline() { - underline = 1; - return this; - } - - public AnsiComponent blink() { - blink = 1; - return this; - } - - public AnsiComponent reverse() { - reverse = 1; - return this; - } - - public AnsiComponent hidden() { - hidden = 1; - return this; - } - - public AnsiComponent strikethrough() { - strikethrough = 1; - return this; - } - - public AnsiComponent color(int color) { - this.color = color; - return this; - } - - public AnsiComponent rgb(int color) { - return color(0xFF000000 | color); - } - - public AnsiComponent black() { - return color(0); - } - - public AnsiComponent darkRed() { - return color(1); - } - - public AnsiComponent green() { - return color(2); - } - - public AnsiComponent orange() { - return color(3); - } - - public AnsiComponent navy() { - return color(4); - } - - public AnsiComponent purple() { - return color(5); - } - - public AnsiComponent teal() { - return color(6); - } - - public AnsiComponent lightGray() { - return color(7); - } - - public AnsiComponent darkGray() { - return color(8); - } - - public AnsiComponent red() { - return color(9); - } - - public AnsiComponent lime() { - return color(10); - } - - public AnsiComponent yellow() { - return color(11); - } - - public AnsiComponent blue() { - return color(12); - } - - public AnsiComponent magenta() { - return color(13); - } - - public AnsiComponent cyan() { - return color(14); - } - - public AnsiComponent white() { - return color(15); - } - - public AnsiComponent error() { - return white().darkRedBg(); - } - - public AnsiComponent treeColor(int index) { - return switch (index & 3) { - case 0 -> red(); - case 1 -> green(); - case 2 -> blue(); - case 3 -> yellow(); - default -> this; - }; - } - - public AnsiComponent bgColor(int color) { - bgColor = color; - return this; - } - - public AnsiComponent rgbBg(int color) { - return bgColor(0xFF000000 | color); - } - - public AnsiComponent blackBg() { - return bgColor(0); - } - - public AnsiComponent darkRedBg() { - return bgColor(1); - } - - public AnsiComponent greenBg() { - return bgColor(2); - } - - public AnsiComponent orangeBg() { - return bgColor(3); - } - - public AnsiComponent navyBg() { - return bgColor(4); - } - - public AnsiComponent purpleBg() { - return bgColor(5); - } - - public AnsiComponent tealBg() { - return bgColor(6); - } - - public AnsiComponent lightGrayBg() { - return bgColor(7); - } - - public AnsiComponent darkGrayBg() { - return bgColor(8); - } - - public AnsiComponent redBg() { - return bgColor(9); - } - - public AnsiComponent limeBg() { - return bgColor(10); - } - - public AnsiComponent yellowBg() { - return bgColor(11); - } - - public AnsiComponent blueBg() { - return bgColor(12); - } - - public AnsiComponent magentaBg() { - return bgColor(13); - } - - public AnsiComponent cyanBg() { - return bgColor(14); - } - - public AnsiComponent whiteBg() { - return bgColor(15); - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiContext.java b/src/main/java/dev/latvian/apps/webutils/ansi/AnsiContext.java deleted file mode 100644 index 31dabfd..0000000 --- a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiContext.java +++ /dev/null @@ -1,20 +0,0 @@ -package dev.latvian.apps.webutils.ansi; - -public class AnsiContext { - public static final AnsiContext UNFORMATTED = new AnsiContext(-1); - public static final AnsiContext NONE = new AnsiContext(0); - - public int index; - - public AnsiContext(int index) { - this.index = index; - } - - public boolean unformatted() { - return index == -1; - } - - public boolean debug() { - return index != 0; - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiPrintStream.java b/src/main/java/dev/latvian/apps/webutils/ansi/AnsiPrintStream.java deleted file mode 100644 index b1a5f7f..0000000 --- a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiPrintStream.java +++ /dev/null @@ -1,15 +0,0 @@ -package dev.latvian.apps.webutils.ansi; - -import org.jetbrains.annotations.NotNull; - -import java.io.PrintStream; - -// WIP for printing exceptions to console with ANSI colors -public class AnsiPrintStream extends PrintStream { - public final PrintStream parent; - - public AnsiPrintStream(@NotNull PrintStream parent) { - super(parent); - this.parent = parent; - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/Log.java b/src/main/java/dev/latvian/apps/webutils/ansi/Log.java deleted file mode 100644 index b8c2d38..0000000 --- a/src/main/java/dev/latvian/apps/webutils/ansi/Log.java +++ /dev/null @@ -1,82 +0,0 @@ -package dev.latvian.apps.webutils.ansi; - -import dev.latvian.apps.webutils.TimeUtils; - -import java.util.Date; - -public class Log { - public enum Type { - INFO, - WARN, - ERROR, - DEBUG, - SUCCESS, - FAIL, - IMPORTANT, - CODE - } - - public static Log INSTANCE = new Log(); - - public static void info(Object message) { - INSTANCE.log(Type.INFO, message); - } - - public static void warn(Object message) { - INSTANCE.log(Type.WARN, message); - } - - public static void error(Object message) { - INSTANCE.log(Type.ERROR, message); - } - - public static void debug(Object message) { - INSTANCE.log(Type.DEBUG, message); - } - - public static void success(Object message) { - INSTANCE.log(Type.SUCCESS, message); - } - - public static void fail(Object message) { - INSTANCE.log(Type.FAIL, message); - } - - public static void success(Object message, boolean success) { - if (success) { - success(message); - } else { - fail(message); - } - } - - public static void important(Object message) { - INSTANCE.log(Type.IMPORTANT, message); - } - - public static void code(Object message) { - INSTANCE.log(Type.CODE, message); - } - - public void log(Type type, Object message) { - var now = new Date(); - var c = Ansi.of(); - c.append(Ansi.cyan(TimeUtils.formatDate(new StringBuilder(), now).toString())); - c.append(' '); - c.append(format(message, type)); - System.out.println(c); - } - - public AnsiComponent format(Object message, Type type) { - return switch (type) { - case WARN -> Ansi.of(message).yellow(); - case ERROR -> Ansi.of(message).error(); - case DEBUG -> Ansi.of(message).lightGray(); - case SUCCESS -> Ansi.of(message).green(); - case FAIL -> Ansi.of(message).red(); - case IMPORTANT -> Ansi.of(message).orange(); - case CODE -> Ansi.of(message).teal(); - default -> Ansi.of(message); - }; - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/Table.java b/src/main/java/dev/latvian/apps/webutils/ansi/Table.java deleted file mode 100644 index da2a6cd..0000000 --- a/src/main/java/dev/latvian/apps/webutils/ansi/Table.java +++ /dev/null @@ -1,243 +0,0 @@ -package dev.latvian.apps.webutils.ansi; - -import dev.latvian.apps.webutils.html.PairedTag; -import dev.latvian.apps.webutils.html.Tag; -import org.jetbrains.annotations.Nullable; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -public class Table { - public static class Cell { - private AnsiComponent value = Ansi.of(""); - private Tag tag = null; - private char padding = ' '; - private boolean alignRight = false; - - private Cell() { - } - - public Cell value(Object v) { - value = Ansi.of(v); - return this; - } - - public Tag tag() { - tag = new PairedTag(""); - return tag; - } - - public Cell padding(char p) { - padding = p; - return this; - } - - public Cell alignRight() { - alignRight = true; - return this; - } - - public void fill(Tag cellTag) { - if (tag != null) { - cellTag.add(tag); - } else { - cellTag.string(value.toUnformattedString()); - } - } - - public String unformattedValue() { - return tag == null ? value.toUnformattedString() : tag.toRawString(); - } - - public int unformattedLength() { - return unformattedValue().length(); - } - } - - public static String escapeCSVSpecialCharacters(@Nullable String data) { - if (data == null) { - return "null"; - } - - String escapedData = data.replaceAll("\\R", " "); - if (data.contains(",") || data.contains("\"") || data.contains("'")) { - data = data.replace("\"", "\"\""); - escapedData = "\"" + data + "\""; - } - return escapedData; - - //return "\"" + data.replace("\"", "\"\"") + "\""; - } - - public final Cell[] head; - public final List rows; - - public Table(String... h) { - head = new Cell[h.length]; - rows = new ArrayList<>(); - - for (int i = 0; i < head.length; i++) { - head[i] = new Cell().value(Ansi.bold(h[i])); - } - } - - public Cell[] addRow() { - Cell[] cells = new Cell[head.length]; - - for (int i = 0; i < head.length; i++) { - cells[i] = new Cell(); - } - - rows.add(cells); - return cells; - } - - public void addRow(Object... h) { - Cell[] c = addRow(); - - for (int i = 0; i < h.length; i++) { - c[i].value(h[i]); - } - } - - private void printLine(List lines, boolean colors, StringBuilder sb, int[] max, int type) { - sb.setLength(0); - sb.append(type == 0 ? '┌' : type == 1 ? '├' : '└'); - - for (int i : max) { - for (int k = 0; k < i + 2; k++) { - sb.append('─'); - } - - sb.append(type == 0 ? '┬' : type == 1 ? '┼' : '┴'); - } - - sb.setCharAt(sb.length() - 1, type == 0 ? '┐' : type == 1 ? '┤' : '┘'); - - if (colors) { - lines.add(sb.toString()); - } else { - lines.add(Ansi.PATTERN.matcher(sb.toString()).replaceAll("")); - } - } - - private void printRow(List lines, boolean colors, StringBuilder sb, int[] max, Cell[] cells) { - sb.setLength(0); - sb.append('│'); - - for (int i = 0; i < max.length; i++) { - sb.append(' '); - - int l = max[i] - cells[i].unformattedLength(); - - if (cells[i].alignRight) { - for (int j = 0; j < l; j++) { - sb.append(cells[i].padding); - } - } - - sb.append(cells[i].value); - sb.append(AnsiCode.RESET); - - if (!cells[i].alignRight) { - for (int j = 0; j < l; j++) { - sb.append(cells[i].padding); - } - } - - sb.append(" │"); - } - - if (colors) { - lines.add(sb.toString()); - } else { - lines.add(Ansi.PATTERN.matcher(sb.toString()).replaceAll("")); - } - } - - public List getCSVLines(boolean includeHead) { - List lines = new ArrayList<>(); - - if (includeHead) { - addCSVLine(lines, head); - } - - for (Cell[] c : rows) { - addCSVLine(lines, c); - } - - return lines; - } - - public byte[] getCSVBytes(boolean includeHead) { - return String.join("\n", getCSVLines(includeHead)).getBytes(StandardCharsets.UTF_8); - } - - private void addCSVLine(List lines, Cell[] cells) { - lines.add(Arrays.stream(cells).map(c -> escapeCSVSpecialCharacters(c.unformattedValue())).collect(Collectors.joining(","))); - } - - public List getLines(boolean colors) { - List lines = new ArrayList<>(); - if (head.length == 0) { - lines.add("┌───────┐"); - lines.add("│ Empty │"); - lines.add("└───────┘"); - return lines; - } - - int[] max = new int[head.length]; - - for (int i = 0; i < head.length; i++) { - max[i] = head[i].unformattedLength(); - } - - for (Cell[] cells : rows) { - for (int i = 0; i < head.length; i++) { - max[i] = Math.max(max[i], cells[i].unformattedLength()); - } - } - - StringBuilder sb = new StringBuilder(); - printLine(lines, colors, sb, max, 0); - printRow(lines, colors, sb, max, head); - printLine(lines, colors, sb, max, 1); - - for (Cell[] cells : rows) { - printRow(lines, colors, sb, max, cells); - } - - printLine(lines, colors, sb, max, 2); - return lines; - } - - public void print() { - Log.info("\n" + String.join("\n", getLines(true))); - } - - public Tag toTag() { - Tag table = new PairedTag("table"); - - var theadTag = table.thead(); - var headTag = theadTag.tr(); - - for (var cell : head) { - cell.fill(headTag.th()); - } - - var tbodyTag = table.tbody(); - - for (var cells : rows) { - var rowTag = tbodyTag.tr(); - - for (var cell : cells) { - cell.fill(rowTag.td()); - } - } - - return table; - } -} \ No newline at end of file diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/package-info.java b/src/main/java/dev/latvian/apps/webutils/ansi/package-info.java deleted file mode 100644 index eef858f..0000000 --- a/src/main/java/dev/latvian/apps/webutils/ansi/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -@dev.latvian.apps.webutils.NonnullByDefault -package dev.latvian.apps.webutils.ansi; \ No newline at end of file diff --git a/src/main/java/dev/latvian/apps/webutils/data/Lazy.java b/src/main/java/dev/latvian/apps/webutils/data/Lazy.java index 6f311ea..1552166 100644 --- a/src/main/java/dev/latvian/apps/webutils/data/Lazy.java +++ b/src/main/java/dev/latvian/apps/webutils/data/Lazy.java @@ -1,27 +1,22 @@ package dev.latvian.apps.webutils.data; -import dev.latvian.apps.webutils.ansi.Log; import org.jetbrains.annotations.Nullable; import java.util.Optional; +import java.util.concurrent.Callable; import java.util.function.Supplier; public class Lazy implements Supplier { - @FunctionalInterface - public interface LazySupplier { - T get() throws Exception; - } - - private record Present(T value) implements LazySupplier { + private record Present(T value) implements Callable { @Override - public T get() { + public T call() { return value; } } - public static final Lazy EMPTY = of(() -> null); + public static final Lazy EMPTY = present(null); - public static Lazy of(LazySupplier getter) { + public static Lazy of(Callable getter) { return new Lazy<>(getter); } @@ -34,11 +29,11 @@ public static Lazy empty() { return (Lazy) EMPTY; } - private final LazySupplier getter; + private final Callable getter; private T object; private boolean inited; - private Lazy(LazySupplier g) { + private Lazy(Callable g) { getter = g; } @@ -54,9 +49,9 @@ public T get() { inited = true; try { - object = getter.get(); + object = getter.call(); } catch (Exception ex) { - Log.error(ex); + throw new RuntimeException(ex); } } diff --git a/src/main/java/dev/latvian/apps/webutils/html/PairedTag.java b/src/main/java/dev/latvian/apps/webutils/html/PairedTag.java index 65b0b84..9ca963b 100644 --- a/src/main/java/dev/latvian/apps/webutils/html/PairedTag.java +++ b/src/main/java/dev/latvian/apps/webutils/html/PairedTag.java @@ -1,8 +1,5 @@ package dev.latvian.apps.webutils.html; -import dev.latvian.apps.webutils.ansi.Ansi; -import dev.latvian.apps.webutils.ansi.AnsiComponent; - import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; @@ -153,51 +150,4 @@ public void appendRaw(StringBuilder builder) { } } } - - @Override - public void ansi(AnsiComponent component, int depth, int indent) { - int col = TagUtils.ANSI_COLORS[depth % TagUtils.ANSI_COLORS.length]; - - if (!this.name.isEmpty()) { - component.append(Ansi.of("<" + this.name).color(col)); - TagUtils.ansiAttributes(component, this.attributes, depth); - component.append(Ansi.of(">").color(col)); - } - - boolean shouldIndent = indent >= 0 && !this.name.isEmpty(); - - if (shouldIndent) { - shouldIndent = false; - - if (this.content != null && !this.content.isEmpty()) { - for (var tag : this.content) { - if (tag instanceof UnpairedTag) { - shouldIndent = true; - break; - } - } - } - } - - if (this.content != null && !this.content.isEmpty()) { - for (var tag : this.content) { - if (shouldIndent) { - component.append('\n'); - component.append(" ".repeat(indent + 1)); - tag.ansi(component, depth + 1, indent + 1); - } else { - tag.ansi(component, depth + 1, indent); - } - } - } - - if (shouldIndent) { - component.append('\n'); - component.append(" ".repeat(indent)); - } - - if (!this.name.isEmpty()) { - component.append(Ansi.of("").color(col)); - } - } } diff --git a/src/main/java/dev/latvian/apps/webutils/html/Tag.java b/src/main/java/dev/latvian/apps/webutils/html/Tag.java index 30af2cf..56b9c5f 100644 --- a/src/main/java/dev/latvian/apps/webutils/html/Tag.java +++ b/src/main/java/dev/latvian/apps/webutils/html/Tag.java @@ -3,9 +3,6 @@ import dev.latvian.apps.tinyserver.content.MimeType; import dev.latvian.apps.tinyserver.http.response.HTTPResponse; import dev.latvian.apps.tinyserver.http.response.HTTPStatus; -import dev.latvian.apps.webutils.ansi.Ansi; -import dev.latvian.apps.webutils.ansi.AnsiComponent; -import dev.latvian.apps.webutils.ansi.Log; import org.jetbrains.annotations.Nullable; import java.nio.charset.StandardCharsets; @@ -33,18 +30,13 @@ default Tag end() { void appendRaw(StringBuilder builder); - default void ansi(AnsiComponent component, int depth, int indent) { - component.append(toRawString()); - } - default String toRawString() { var builder = new StringBuilder(); try { appendRaw(builder); } catch (OutOfMemoryError error) { - Log.error("Out of memory while generating HTML:"); - error.printStackTrace(); + throw new RuntimeException("Out of memory while generating HTML:", error); } catch (Throwable error) { error.printStackTrace(); } @@ -58,8 +50,7 @@ default String toTagString(boolean header) { try { append(builder, header); } catch (OutOfMemoryError error) { - Log.error("Out of memory while generating HTML:"); - error.printStackTrace(); + throw new RuntimeException("Out of memory while generating HTML:", error); } catch (Throwable error) { error.printStackTrace(); } @@ -67,12 +58,6 @@ default String toTagString(boolean header) { return builder.toString(); } - default AnsiComponent toAnsi(boolean indent) { - var component = Ansi.of(); - ansi(component, 0, indent ? 0 : -1); - return component; - } - default Tag add(Tag tag) { addAnd(tag); return this; diff --git a/src/main/java/dev/latvian/apps/webutils/html/TagANSI.java b/src/main/java/dev/latvian/apps/webutils/html/TagANSI.java new file mode 100644 index 0000000..db70d3f --- /dev/null +++ b/src/main/java/dev/latvian/apps/webutils/html/TagANSI.java @@ -0,0 +1,104 @@ +package dev.latvian.apps.webutils.html; + +import dev.latvian.apps.ansi.ANSI; +import dev.latvian.apps.ansi.color.Color16; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +public interface TagANSI { + static ANSI of(Tag tag) { + return of(tag, false); + } + + static ANSI of(Tag tag, boolean indent) { + var component = ANSI.empty(); + ansi(tag, component, 0, indent ? 0 : -1); + return component; + } + + private static void ansi(Tag tag, ANSI component, int depth, int indent) { + if (tag instanceof PairedTag paired) { + paired(paired, component, depth, indent); + } else if (tag instanceof UnpairedTag unpaired) { + unpaired(unpaired, component, depth, indent); + } else { + component.append(tag.toRawString()); + } + } + + private static void unpaired(UnpairedTag tag, ANSI component, int depth, int indent) { + var col = Color16.tree(depth); + + component.append(ANSI.of("<" + tag.name).foreground(col)); + TagANSI.attributes(component, tag.attributes, depth); + component.append(ANSI.of(" />").foreground(col)); + } + + private static void paired(PairedTag tag, ANSI component, int depth, int indent) { + var col = Color16.tree(depth); + + if (!tag.name.isEmpty()) { + component.append(ANSI.of("<" + tag.name).foreground(col)); + TagANSI.attributes(component, tag.attributes, depth); + component.append(ANSI.of(">").foreground(col)); + } + + boolean shouldIndent = indent >= 0 && !tag.name.isEmpty(); + + if (shouldIndent) { + shouldIndent = false; + + if (tag.content != null && !tag.content.isEmpty()) { + for (var c : tag.content) { + if (c instanceof UnpairedTag) { + shouldIndent = true; + break; + } + } + } + } + + if (tag.content != null && !tag.content.isEmpty()) { + for (var c : tag.content) { + if (shouldIndent) { + component.append('\n'); + component.append(" ".repeat(indent + 1)); + ansi(c, component, depth + 1, indent + 1); + } else { + ansi(c, component, depth + 1, indent); + } + } + } + + if (shouldIndent) { + component.append('\n'); + component.append(" ".repeat(indent)); + } + + if (!tag.name.isEmpty()) { + component.append(ANSI.of("").foreground(col)); + } + } + + static void attributes(ANSI component, @Nullable Map attributes, int depth) { + var col = Color16.tree(depth); + + if (attributes != null) { + var sb = new StringBuilder(); + + for (var entry : attributes.entrySet()) { + component.append(' '); + component.append(ANSI.lime(entry.getKey())); + + if (!entry.getValue().equals("")) { + component.append(ANSI.of("=\"").foreground(col)); + TagUtils.encode(sb, entry.getValue()); + component.append(ANSI.yellow(sb.toString())); + sb.setLength(0); + component.append(ANSI.of("\"").foreground(col)); + } + } + } + } +} diff --git a/src/main/java/dev/latvian/apps/webutils/html/TagUtils.java b/src/main/java/dev/latvian/apps/webutils/html/TagUtils.java index e471706..1b265a5 100644 --- a/src/main/java/dev/latvian/apps/webutils/html/TagUtils.java +++ b/src/main/java/dev/latvian/apps/webutils/html/TagUtils.java @@ -1,19 +1,10 @@ package dev.latvian.apps.webutils.html; -import dev.latvian.apps.webutils.ansi.Ansi; -import dev.latvian.apps.webutils.ansi.AnsiComponent; import org.jetbrains.annotations.Nullable; import java.util.Map; public class TagUtils { - public static final int[] ANSI_COLORS = { - 13, // MAGENTA - 5, // PURPLE - 12, // BLUE - 14, // CYAN - }; - public static String encode(char c) { return switch (c) { case '&' -> "&"; @@ -314,25 +305,4 @@ public static void writeAttributes(StringBuilder writer, @Nullable Map attributes, int depth) { - int col = ANSI_COLORS[depth % ANSI_COLORS.length]; - - if (attributes != null) { - var sb = new StringBuilder(); - - for (var entry : attributes.entrySet()) { - component.append(' '); - component.append(Ansi.lime(entry.getKey())); - - if (!entry.getValue().equals("")) { - component.append(Ansi.of("=\"").color(col)); - encode(sb, entry.getValue()); - component.append(Ansi.yellow(sb.toString())); - sb.setLength(0); - component.append(Ansi.of("\"").color(col)); - } - } - } - } } diff --git a/src/main/java/dev/latvian/apps/webutils/html/UnpairedTag.java b/src/main/java/dev/latvian/apps/webutils/html/UnpairedTag.java index 00e8db1..03557db 100644 --- a/src/main/java/dev/latvian/apps/webutils/html/UnpairedTag.java +++ b/src/main/java/dev/latvian/apps/webutils/html/UnpairedTag.java @@ -1,7 +1,5 @@ package dev.latvian.apps.webutils.html; -import dev.latvian.apps.webutils.ansi.Ansi; -import dev.latvian.apps.webutils.ansi.AnsiComponent; import org.jetbrains.annotations.Nullable; import java.util.LinkedHashMap; @@ -68,13 +66,4 @@ public void append(StringBuilder builder, boolean header) { @Override public void appendRaw(StringBuilder builder) { } - - @Override - public void ansi(AnsiComponent component, int depth, int indent) { - int col = TagUtils.ANSI_COLORS[depth % TagUtils.ANSI_COLORS.length]; - - component.append(Ansi.of("<" + this.name).color(col)); - TagUtils.ansiAttributes(component, this.attributes, depth); - component.append(Ansi.of(" />").color(col)); - } } diff --git a/src/main/java/dev/latvian/apps/webutils/json/ArrayJSONAdapter.java b/src/main/java/dev/latvian/apps/webutils/json/ArrayJSONAdapter.java deleted file mode 100644 index 5ce106d..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/ArrayJSONAdapter.java +++ /dev/null @@ -1,68 +0,0 @@ -package dev.latvian.apps.webutils.json; - -import java.io.IOException; -import java.io.Writer; -import java.lang.reflect.Array; -import java.util.Collection; - -public class ArrayJSONAdapter implements JSONAdapter { - private final JSON json; - private final Class type; - private Object emptyArray; - - public ArrayJSONAdapter(JSON json, Class type) { - this.json = json; - this.type = type; - this.emptyArray = null; - } - - @Override - public Object adapt(Object jsonValue) { - if (jsonValue instanceof Iterable itr) { - int size; - - if (itr instanceof Collection c) { - size = c.size(); - } else { - size = 0; - - for (var ignored : itr) { - size++; - } - } - - if (size == 0) { - if (emptyArray == null) { - emptyArray = Array.newInstance(type, 0); - } - - return emptyArray; - } - - var arr = Array.newInstance(type, size); - - int i = 0; - - for (var value : itr) { - Array.set(arr, i, json.adapt(value, type)); - i++; - } - - return arr; - } else { - throw new IllegalArgumentException("Expected collection, got " + jsonValue.getClass().getName()); - } - } - - @Override - public void write(JSON json, Writer writer, Object value, int depth, boolean pretty) throws IOException { - var len = Array.getLength(value); - var arr = JSONArray.of(len); - - for (var i = 0; i < len; i++) { - arr.add(Array.get(value, i)); - } - - json.write(writer, arr, depth, pretty); - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/BufferedJSONReader.java b/src/main/java/dev/latvian/apps/webutils/json/BufferedJSONReader.java deleted file mode 100644 index 3b1ee37..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/BufferedJSONReader.java +++ /dev/null @@ -1,43 +0,0 @@ -package dev.latvian.apps.webutils.json; - -import java.io.Reader; - -public class BufferedJSONReader implements JSONReader { - private final JSON json; - private final Reader reader; - private boolean move; - private char peek; - - public BufferedJSONReader(JSON json, Reader reader) { - this.json = json; - this.reader = reader; - this.move = true; - this.peek = 0; - } - - @Override - public JSON json() { - return json; - } - - @Override - public char read() { - move = true; - return peek(); - } - - @Override - public char peek() { - if (move) { - move = false; - - try { - peek = (char) reader.read(); - } catch (Exception e) { - throw new IllegalStateException(e); - } - } - - return peek; - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/DeepRemovePredicate.java b/src/main/java/dev/latvian/apps/webutils/json/DeepRemovePredicate.java deleted file mode 100644 index dd934d4..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/DeepRemovePredicate.java +++ /dev/null @@ -1,10 +0,0 @@ -package dev.latvian.apps.webutils.json; - -import org.jetbrains.annotations.Nullable; - -@FunctionalInterface -public interface DeepRemovePredicate { - DeepRemovePredicate NONE = (key, index, value) -> false; - - boolean remove(String key, int index, @Nullable Object value); -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/JSON.java b/src/main/java/dev/latvian/apps/webutils/json/JSON.java deleted file mode 100644 index 0a51368..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/JSON.java +++ /dev/null @@ -1,366 +0,0 @@ -package dev.latvian.apps.webutils.json; - -import dev.latvian.apps.webutils.Cast; -import dev.latvian.apps.webutils.data.HexId32; -import dev.latvian.apps.webutils.data.HexId64; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Array; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.time.Instant; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.function.Function; - -public class JSON { - public static final Object NULL = new Object(); - public static final JSON DEFAULT = new JSON(null); - - static { - DEFAULT.registerStringAdapter(UUID.class, UUID::fromString); - DEFAULT.registerAdapter(Date.class, value -> Date.from(Instant.parse(String.valueOf(value))), date -> date.toInstant().toString()); - DEFAULT.registerStringAdapter(Instant.class, Instant::parse); - DEFAULT.registerAdapter(URL.class, value -> { - try { - return new URL(String.valueOf(value)); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - }, URL::toString); - DEFAULT.registerStringAdapter(URI.class, URI::create); - DEFAULT.registerStringAdapter(Path.class, Path::of); - DEFAULT.registerAdapter(Class.class, value -> { - try { - return Class.forName(String.valueOf(value)); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - }, Class::getName); - DEFAULT.registerStringAdapter(HexId32.class, HexId32::of); - DEFAULT.registerStringAdapter(HexId64.class, HexId64::of); - DEFAULT.registerStringAdapter(StringBuilder.class, StringBuilder::new); - } - - private static void escape(Writer writer, String string) throws IOException { - for (int i = 0; i < string.length(); i++) { - char c = string.charAt(i); - - switch (c) { - case '"' -> writer.write("\\\""); - case '\\' -> writer.write("\\\\"); - case '\b' -> writer.write("\\b"); - case '\f' -> writer.write("\\f"); - case '\n' -> writer.write("\\n"); - case '\r' -> writer.write("\\r"); - case '\t' -> writer.write("\\t"); - default -> { - if (c < ' ') { - writer.write("\\u"); - writer.write(String.format("%04x", (int) c)); - } else { - writer.write(c); - } - } - } - } - } - - private final JSON parent; - private final Map, JSONAdapter> adapters; - - private JSON(JSON parent) { - this.parent = parent; - this.adapters = new IdentityHashMap<>(); - } - - public void registerAdapter(Class type, JSONAdapter adapter) { - adapters.put(type, adapter); - } - - public void registerAdapter(Class type, final Function adapt, final Function write) { - registerAdapter(type, new JSONAdapter<>() { - @Override - public T adapt(Object value) { - return adapt.apply(value); - } - - @Override - public void write(JSON json, Writer writer, T value, int depth, boolean pretty) throws IOException { - json.write(writer, write.apply(value), depth, pretty); - } - }); - } - - public void registerStringAdapter(Class type, final Function adapt) { - registerAdapter(type, new JSONAdapter<>() { - @Override - public T adapt(Object value) { - return adapt.apply(String.valueOf(value)); - } - - @Override - public void write(JSON json, Writer writer, T value, int depth, boolean pretty) throws IOException { - json.write(writer, value.toString(), depth, pretty); - } - }); - } - - @SuppressWarnings("unchecked") - public JSONAdapter getAdapter(Class type) { - var a = adapters.get(type); - - if (a == null) { - var p = parent; - - while (p != null) { - a = p.adapters.get(type); - - if (a != null) { - break; - } - - p = p.parent; - } - } - - if (a == null) { - if (type.isArray()) { - a = new ArrayJSONAdapter(this, type.getComponentType()); - } else { - a = new ReflectionJSONAdapter(this, type); - } - - adapters.put(type, a); - } - - return (JSONAdapter) a; - } - - public JSONReader read(String string) { - return new JSONCharArrayReader(this, string.toCharArray()); - } - - public JSONReader read(Path path) throws IOException { - // use BufferedJSONReader in future - return new JSONCharArrayReader(this, String.join("", Files.readAllLines(path)).toCharArray()); - } - - public String write(@Nullable Object value) { - var builder = new StringWriter(); - - try { - write(builder, value, 0, false); - } catch (IOException e) { - throw new RuntimeException(e); - } - - return builder.toString(); - } - - public String writePretty(@Nullable Object value) { - var builder = new StringWriter(); - - try { - write(builder, value, 0, true); - } catch (IOException e) { - throw new RuntimeException(e); - } - - return builder.toString(); - } - - public void write(Path path, Object value, boolean pretty) throws IOException { - if (Files.notExists(path.getParent())) { - Files.createDirectories(path.getParent()); - } - - Files.writeString(path, pretty ? writePretty(value) : write(value)); - } - - public void write(Writer writer, @Nullable Object value, int depth, boolean pretty) throws IOException { - if (depth > 1000) { - throw new IllegalStateException("JSON depth limit reached"); - } - - if (value == null || value == NULL) { - writer.write("null"); - } else if (value instanceof JSONSerializable) { - write(writer, ((JSONSerializable) value).toJSON(), depth, pretty); - } else if (value instanceof String str) { - writer.write('"'); - escape(writer, str); - writer.write('"'); - } else if (value instanceof Number || value instanceof Boolean) { - writer.write(String.valueOf(value)); - } else if (value instanceof Map map) { - boolean first = true; - writer.write('{'); - - for (var entry : map.entrySet()) { - if (first) { - first = false; - } else { - writer.write(','); - } - - if (pretty) { - writer.write('\n'); - - for (int i = 0; i <= depth; i++) { - writer.write('\t'); - } - } - - writer.write('"'); - escape(writer, String.valueOf(entry.getKey())); - writer.write('"'); - writer.write(':'); - - if (pretty) { - writer.write(' '); - } - - write(writer, entry.getValue(), depth + 1, pretty); - } - - if (pretty) { - writer.write('\n'); - - for (int i = 0; i < depth; i++) { - writer.write('\t'); - } - } - - writer.write('}'); - } else if (value instanceof Iterable itr) { - boolean first = true; - writer.write('['); - - for (var o : itr) { - if (first) { - first = false; - } else { - writer.write(','); - } - - if (pretty) { - writer.write('\n'); - - for (int i = 0; i <= depth; i++) { - writer.write('\t'); - } - } - - write(writer, o, depth + 1, pretty); - } - - if (pretty) { - writer.write('\n'); - - for (int i = 0; i < depth; i++) { - writer.write('\t'); - } - } - - writer.write(']'); - } else if (value instanceof Object[] arr) { - write(writer, Arrays.asList(arr), depth, pretty); - } else if (value.getClass().isArray()) { - writer.write('['); - int len = Array.getLength(value); - - for (int i = 0; i < len; i++) { - if (i > 0) { - writer.write(','); - } - - write(writer, Array.get(value, i), depth + 1, pretty); - } - - writer.write(']'); - } else if (value instanceof Enum e) { - write(writer, e.name().toLowerCase(), depth, pretty); - } else if (value instanceof Record) { - var obj = JSONObject.of(); - - for (var field : value.getClass().getRecordComponents()) { - try { - obj.put(field.getName(), field.getAccessor().invoke(value)); - } catch (Exception ex) { - throw new RuntimeException("Failed to access record method", ex); - } - } - - write(writer, obj, depth, pretty); - } - // Other - else { - getAdapter(value.getClass()).write(this, writer, Cast.to(value), depth, pretty); - } - } - - public JSON child() { - return new JSON(this); - } - - @SuppressWarnings("unchecked") - public T adapt(Object value, Class t) { - if (value == null) { - return null; - } else if (t == Object.class || t.isInstance(value)) { - return (T) value; - } else if (t == String.class) { - return (T) String.valueOf(value); - } else if (t == Character.class || t == Character.TYPE) { - return (T) Character.valueOf(String.valueOf(value).charAt(0)); - } else if (t == Number.class) { - return (T) value; - } else if (t == Byte.class || t == Byte.TYPE) { - return (T) Byte.valueOf(((Number) value).byteValue()); - } else if (t == Short.class || t == Short.TYPE) { - return (T) Short.valueOf(((Number) value).shortValue()); - } else if (t == Integer.class || t == Integer.TYPE) { - return (T) Integer.valueOf(((Number) value).intValue()); - } else if (t == Long.class || t == Long.TYPE) { - return (T) Long.valueOf(((Number) value).longValue()); - } else if (t == Float.class || t == Float.TYPE) { - return (T) Float.valueOf(((Number) value).floatValue()); - } else if (t == Double.class || t == Double.TYPE) { - return (T) Double.valueOf(((Number) value).doubleValue()); - } else if (t == Map.class || t == JSONObject.class) { - return (T) value; - } else if (t == List.class || t == Collection.class || t == Iterable.class || t == JSONArray.class) { - return (T) value; - } else if (t == Set.class) { - return (T) new HashSet<>((Collection) value); - } else if (t.isEnum()) { - var str = String.valueOf(value); - - for (var e : t.getEnumConstants()) { - if (e.toString().equalsIgnoreCase(str)) { - return e; - } - } - - throw new IllegalArgumentException("Unknown enum constant: " + str); - } - // Other - else { - return Cast.to(getAdapter(t).adapt(value)); - } - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/JSONAdapter.java b/src/main/java/dev/latvian/apps/webutils/json/JSONAdapter.java deleted file mode 100644 index bee8b46..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/JSONAdapter.java +++ /dev/null @@ -1,10 +0,0 @@ -package dev.latvian.apps.webutils.json; - -import java.io.IOException; -import java.io.Writer; - -public interface JSONAdapter { - T adapt(Object jsonValue); - - void write(JSON json, Writer writer, T value, int depth, boolean pretty) throws IOException; -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/JSONArray.java b/src/main/java/dev/latvian/apps/webutils/json/JSONArray.java deleted file mode 100644 index 5f69243..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/JSONArray.java +++ /dev/null @@ -1,223 +0,0 @@ -package dev.latvian.apps.webutils.json; - -import dev.latvian.apps.webutils.Cast; -import dev.latvian.apps.webutils.data.HexId32; -import dev.latvian.apps.webutils.data.HexId64; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class JSONArray extends ArrayList { - public static JSONArray of() { - return new JSONArray(4); - } - - public static JSONArray of(Object value) { - return new JSONArray(1).append(value); - } - - public static JSONArray ofArray(Object... values) { - var a = new JSONArray(values.length); - - for (var v : values) { - a.append(v); - } - - return a; - } - - public static JSONArray ofAll(Iterable iterable) { - var a = new JSONArray(iterable instanceof Collection c ? c.size() : 4); - - for (var v : iterable) { - a.append(v); - } - - return a; - } - - private JSONArray(int initialCapacity) { - super(initialCapacity); - } - - JSONArray(String key) { - } - - public List ofObjects() { - return Cast.to(this); - } - - public List ofArrays() { - return Cast.to(this); - } - - public List ofStrings() { - return Cast.to(this); - } - - public List ofNumbers() { - return Cast.to(this); - } - - public List ofBooleans() { - return Cast.to(this); - } - - public List ofHex32s() { - return Cast.to(this); - } - - public List ofHex64s() { - return Cast.to(this); - } - - @Override - public Object get(int index) { - var o = super.get(index); - return o == JSON.NULL ? null : o; - } - - public JSONArray append(Object value) { - add(value); - return this; - } - - public JSONObject asObject(int key) { - return (JSONObject) get(key); - } - - public JSONObject addObject() { - var o = JSONObject.of(); - add(o); - return o; - } - - public JSONArray asArray(int key) { - var o = get(key); - return o instanceof JSONArray a ? a : JSONArray.of(o); - } - - public JSONArray addArray() { - var a = JSONArray.of(); - add(a); - return a; - } - - public String asString(int key) { - var o = get(key); - return o == null ? "" : String.valueOf(o); - } - - public Number asNumber(int key) { - return asNumber(key, 0); - } - - public Number asNumber(int key, Number def) { - var o = get(key); - - if (o == null) { - return def; - } else if (o instanceof Number n) { - return n; - } else if (o instanceof CharSequence) { - try { - return Double.parseDouble(o.toString()); - } catch (NumberFormatException e) { - return def; - } - } else { - return def; - } - } - - public int asInt(int key, int def) { - return asNumber(key, def).intValue(); - } - - public int asInt(int key) { - return asInt(key, 0); - } - - public long asLong(int key, long def) { - return asNumber(key, def).longValue(); - } - - public long asLong(int key) { - return asLong(key, 0L); - } - - public double asDouble(int key, double def) { - return asNumber(key, def).doubleValue(); - } - - public double asDouble(int key) { - return asDouble(key, 0D); - } - - public boolean asBoolean(int key) { - return (boolean) get(key); - } - - public HexId32 asHex32(int key) { - return asHex32(key, HexId32.NONE); - } - - public HexId32 asHex32(int key, HexId32 def) { - var s = asString(key); - return s.isEmpty() ? def : HexId32.of(s); - } - - public HexId64 asHex64(int key) { - return asHex64(key, HexId64.NONE); - } - - public HexId64 asHex64(int key, HexId64 def) { - var s = asString(key); - return s.isEmpty() ? def : HexId64.of(s); - } - - @Override - public String toString() { - return JSON.DEFAULT.write(this); - } - - public String toPrettyString() { - return JSON.DEFAULT.writePretty(this); - } - - public boolean removeDeep(DeepRemovePredicate predicate, boolean removeEmpty) { - boolean modified = false; - var it = iterator(); - int index = 0; - - while (it.hasNext()) { - var v = it.next(); - - if (predicate.remove("", index++, v)) { - modified = true; - it.remove(); - } else if (v instanceof JSONObject o) { - if (o.removeDeep(predicate, removeEmpty)) { - modified = true; - } - - if (removeEmpty && o.isEmpty()) { - modified = true; - it.remove(); - } - } else if (v instanceof JSONArray a) { - if (a.removeDeep(predicate, removeEmpty)) { - modified = true; - } - - if (removeEmpty && a.isEmpty()) { - modified = true; - it.remove(); - } - } - } - - return modified; - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/JSONCharArrayReader.java b/src/main/java/dev/latvian/apps/webutils/json/JSONCharArrayReader.java deleted file mode 100644 index 5d19a4b..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/JSONCharArrayReader.java +++ /dev/null @@ -1,33 +0,0 @@ -package dev.latvian.apps.webutils.json; - -public class JSONCharArrayReader implements JSONReader { - private final JSON json; - private final char[] chars; - private int pos; - - public JSONCharArrayReader(JSON json, char[] chars) { - this.json = json; - this.chars = chars; - this.pos = 0; - skipWhitespace(); - } - - @Override - public JSON json() { - return json; - } - - @Override - public char read() { - if (pos == chars.length) { - throw new IllegalStateException("EOL"); - } - - return chars[pos++]; - } - - @Override - public char peek() { - return pos == chars.length ? '\0' : chars[pos]; - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/JSONInfo.java b/src/main/java/dev/latvian/apps/webutils/json/JSONInfo.java deleted file mode 100644 index 73e5b06..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/JSONInfo.java +++ /dev/null @@ -1,14 +0,0 @@ -package dev.latvian.apps.webutils.json; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Documented -@Target({ElementType.FIELD, ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface JSONInfo { - String value() default ""; -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/JSONObject.java b/src/main/java/dev/latvian/apps/webutils/json/JSONObject.java deleted file mode 100644 index 477b378..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/JSONObject.java +++ /dev/null @@ -1,194 +0,0 @@ -package dev.latvian.apps.webutils.json; - -import dev.latvian.apps.webutils.data.HexId32; -import dev.latvian.apps.webutils.data.HexId64; - -import java.util.LinkedHashMap; -import java.util.Map; - -public class JSONObject extends LinkedHashMap { - public static JSONObject of() { - return new JSONObject(8); - } - - public static JSONObject of(int initialCapacity) { - return new JSONObject(initialCapacity); - } - - public static JSONObject of(Map map) { - var o = new JSONObject(map.size()); - o.putAll(map); - return o; - } - - public static JSONObject of(String key, Object value) { - return new JSONObject(1).append(key, value); - } - - public static JSONObject of(String key1, Object value1, String key2, Object value2) { - return new JSONObject(2).append(key1, value1).append(key2, value2); - } - - public static JSONObject of(String key1, Object value1, String key2, Object value2, String key3, Object value3) { - return new JSONObject(3).append(key1, value1).append(key2, value2).append(key3, value3); - } - - private JSONObject(int initialCapacity) { - super(initialCapacity); - } - - JSONObject(String key) { - } - - @Override - public Object get(Object key) { - var o = super.get(key); - return o == JSON.NULL ? null : o; - } - - public JSONObject append(String key, Object value) { - put(key, value); - return this; - } - - public JSONObject asObject(String key) { - return (JSONObject) get(key); - } - - public JSONObject addObject(String key) { - return (JSONObject) computeIfAbsent(key, JSONObject::new); - } - - public JSONArray asArray(String key) { - var o = get(key); - return o instanceof JSONArray a ? a : JSONArray.of(o); - } - - public JSONArray addArray(String key) { - return (JSONArray) computeIfAbsent(key, JSONArray::new); - } - - public String asString(String key, String def) { - return String.valueOf(getOrDefault(key, def)); - } - - public String asString(String key) { - return asString(key, ""); - } - - public Number asNumber(String key) { - return (Number) get(key); - } - - public Number asNumber(String key, Number def) { - var o = get(key); - - if (o == null) { - return def; - } else if (o instanceof Number n) { - return n; - } else if (o instanceof CharSequence) { - try { - return Double.parseDouble(o.toString()); - } catch (NumberFormatException e) { - return def; - } - } else { - return def; - } - } - - public int asInt(String key, int def) { - return asNumber(key, def).intValue(); - } - - public int asInt(String key) { - return asInt(key, 0); - } - - public long asLong(String key, long def) { - return asNumber(key, def).longValue(); - } - - public long asLong(String key) { - return asLong(key, 0L); - } - - public double asDouble(String key, double def) { - return asNumber(key, def).doubleValue(); - } - - public double asDouble(String key) { - return asDouble(key, 0D); - } - - public boolean asBoolean(String key, boolean def) { - return (boolean) getOrDefault(key, def); - } - - public boolean asBoolean(String key) { - return asBoolean(key, false); - } - - public HexId32 asHex32(String key) { - return asHex32(key, HexId32.NONE); - } - - public HexId32 asHex32(String key, HexId32 def) { - var s = asString(key, ""); - return s.isEmpty() ? def : HexId32.of(s); - } - - public HexId64 asHex64(String key) { - return asHex64(key, HexId64.NONE); - } - - public HexId64 asHex64(String key, HexId64 def) { - var s = asString(key, ""); - return s.isEmpty() ? def : HexId64.of(s); - } - - @Override - public String toString() { - return JSON.DEFAULT.write(this); - } - - public String toPrettyString() { - return JSON.DEFAULT.writePretty(this); - } - - public boolean removeDeep(DeepRemovePredicate predicate, boolean removeEmpty) { - boolean modified = false; - var it = entrySet().iterator(); - - while (it.hasNext()) { - var e = it.next(); - var v = e.getValue(); - - if (predicate.remove(e.getKey(), -1, v)) { - modified = true; - it.remove(); - } else if (v instanceof JSONObject o) { - if (o.removeDeep(predicate, removeEmpty)) { - modified = true; - } - - if (removeEmpty && o.isEmpty()) { - modified = true; - it.remove(); - } - } else if (v instanceof JSONArray a) { - if (a.removeDeep(predicate, removeEmpty)) { - modified = true; - } - - if (removeEmpty && a.isEmpty()) { - modified = true; - it.remove(); - } - } - } - - return modified; - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/JSONReader.java b/src/main/java/dev/latvian/apps/webutils/json/JSONReader.java deleted file mode 100644 index 64c3781..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/JSONReader.java +++ /dev/null @@ -1,201 +0,0 @@ -package dev.latvian.apps.webutils.json; - -import org.jetbrains.annotations.Nullable; - -public interface JSONReader { - default JSON json() { - return JSON.DEFAULT; - } - - char read(); - - char peek(); - - default void expect(char c) { - if (read() != c) { - throw new IllegalStateException("Expected " + c); - } - } - - default boolean peekWhitespace() { - var c = peek(); - return c != '\0' && Character.isWhitespace(c); - } - - default void skipWhitespace() { - while (peekWhitespace()) { - read(); - } - } - - default T adapt(Class type) { - return json().adapt(readValue(), type); - } - - @Nullable - default Object readValue() { - return switch (peek()) { - case 'n' -> readNull(); - case 't' -> readTrue(); - case 'f' -> readFalse(); - case '"' -> readString(); - case '{' -> readObject(); - case '[' -> readArray(); - default -> readNumber(); - }; - } - - @Nullable - default Object readNull() { - expect('n'); - expect('u'); - expect('l'); - expect('l'); - return null; - } - - default Boolean readTrue() { - expect('t'); - expect('r'); - expect('u'); - expect('e'); - return Boolean.TRUE; - } - - default Boolean readFalse() { - expect('f'); - expect('a'); - expect('l'); - expect('s'); - expect('e'); - return Boolean.FALSE; - } - - default String readString() { - expect('"'); - - var builder = new StringBuilder(); - - while (peek() != '"') { - char c = read(); - - if (c == '\\') { - c = read(); - - switch (c) { - case 'b' -> builder.append('\b'); - case 'f' -> builder.append('\f'); - case 'n' -> builder.append('\n'); - case 'r' -> builder.append('\r'); - case 't' -> builder.append('\t'); - case 'u' -> { - char[] hex = new char[4]; - - for (int i = 0; i < 4; i++) { - hex[i] = read(); - } - - builder.append((char) Integer.parseInt(new String(hex), 16)); - } - default -> builder.append(c); - } - } else { - builder.append(c); - } - } - - expect('"'); - return builder.toString(); - } - - default Number readNumber() { - // Improve this implementation later - var builder = new StringBuilder(); - - var c = peek(); - - if (c == '-' || c == '+') { - builder.append(read()); - c = peek(); - } - - boolean floating = false; - - while (true) { - if (c == '.') { - if (floating) { - throw new IllegalStateException("Invalid number: Multiple '.'"); - } else { - floating = true; - } - - builder.append(read()); - } else if (c == 'E' || c == 'e') { - builder.append(read()); - - if (peek() == '-') { - builder.append(read()); - } - } else if (c >= '0' && c <= '9') { - builder.append(read()); - } else { - break; - } - - c = peek(); - } - - var str = builder.toString(); - - if (floating) { - return Double.parseDouble(str); - } else { - return Long.decode(str); - } - } - - default JSONObject readObject() { - expect('{'); - skipWhitespace(); - - var obj = JSONObject.of(); - - while (peek() != '}') { - String key = readString(); - skipWhitespace(); - expect(':'); - skipWhitespace(); - var v = readValue(); - - obj.put(key, v == null ? JSON.NULL : v); - - while (peek() == ',' || peekWhitespace()) { - read(); - } - } - - expect('}'); - return obj; - } - - default JSONArray readArray() { - expect('['); - skipWhitespace(); - - var arr = JSONArray.of(); - - while (peek() != ']') { - var v = readValue(); - skipWhitespace(); - - arr.add(v == null ? JSON.NULL : v); - - while (peek() == ',' || peekWhitespace()) { - read(); - } - } - - expect(']'); - return arr; - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/JSONResponse.java b/src/main/java/dev/latvian/apps/webutils/json/JSONResponse.java deleted file mode 100644 index fdbec1f..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/JSONResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -package dev.latvian.apps.webutils.json; - -import dev.latvian.apps.tinyserver.content.MimeType; -import dev.latvian.apps.tinyserver.http.response.HTTPResponse; -import dev.latvian.apps.tinyserver.http.response.HTTPStatus; - -import java.nio.charset.StandardCharsets; - -public interface JSONResponse { - HTTPResponse SUCCESS = HTTPStatus.OK.json(JSONObject.of("success", true).toString()); - - static HTTPResponse of(HTTPStatus status, Object json) { - return status.content(JSON.DEFAULT.write(json).getBytes(StandardCharsets.UTF_8), MimeType.JSON); - } - - static HTTPResponse of(Object json) { - return of(HTTPStatus.OK, json); - } -} \ No newline at end of file diff --git a/src/main/java/dev/latvian/apps/webutils/json/JSONSerializable.java b/src/main/java/dev/latvian/apps/webutils/json/JSONSerializable.java deleted file mode 100644 index 72151f1..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/JSONSerializable.java +++ /dev/null @@ -1,6 +0,0 @@ -package dev.latvian.apps.webutils.json; - -@FunctionalInterface -public interface JSONSerializable { - Object toJSON(); -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/ReflectionJSONAdapter.java b/src/main/java/dev/latvian/apps/webutils/json/ReflectionJSONAdapter.java deleted file mode 100644 index b0f471f..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/ReflectionJSONAdapter.java +++ /dev/null @@ -1,78 +0,0 @@ -package dev.latvian.apps.webutils.json; - -import java.io.IOException; -import java.io.Writer; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.LinkedHashMap; -import java.util.Map; - -public class ReflectionJSONAdapter implements JSONAdapter { - private final JSON json; - private final Class type; - private Constructor constructor; - private Map fields; - - public ReflectionJSONAdapter(JSON json, Class type) { - this.json = json; - this.type = type; - this.fields = null; - } - - private Map fields() { - if (fields == null) { - fields = new LinkedHashMap<>(); - - for (var f : type.getDeclaredFields()) { - if (f.isSynthetic() || Modifier.isTransient(f.getModifiers()) || Modifier.isStatic(f.getModifiers())) { - continue; - } - - f.setAccessible(true); - fields.put(f.getName(), f); - } - } - - return fields; - } - - @Override - public Object adapt(Object jsonValue) { - if (jsonValue instanceof Map object) { - if (constructor == null) { - try { - constructor = type.getDeclaredConstructor(); - constructor.setAccessible(true); - } catch (NoSuchMethodException e) { - throw new RuntimeException("No default constructor for type '" + type.getName() + "'", e); - } - } - - try { - var o = constructor.newInstance(); - - for (var entry : object.entrySet()) { - if (entry.getValue() != null && entry.getValue() != JSON.NULL) { - var f = fields().get(String.valueOf(entry.getKey())); - - if (f != null) { - f.set(o, json.adapt(entry.getValue(), f.getType())); - } - } - } - - return o; - } catch (Exception e) { - throw new RuntimeException("Error reading '" + type.getName() + "' JSON", e); - } - } else { - throw new IllegalArgumentException("Expected JSON object for type '" + type.getName() + "'"); - } - } - - @Override - public void write(JSON json, Writer writer, Object value, int depth, boolean pretty) throws IOException { - throw new UnsupportedOperationException("Reflection JSON for type '" + type.getName() + "' not supported yet"); - } -} diff --git a/src/main/java/dev/latvian/apps/webutils/json/package-info.java b/src/main/java/dev/latvian/apps/webutils/json/package-info.java deleted file mode 100644 index 6356efa..0000000 --- a/src/main/java/dev/latvian/apps/webutils/json/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -@dev.latvian.apps.webutils.NonnullByDefault -package dev.latvian.apps.webutils.json; \ No newline at end of file diff --git a/src/test/java/dev/latvian/apps/webutils/test/AnsiTests.java b/src/test/java/dev/latvian/apps/webutils/test/AnsiTests.java deleted file mode 100644 index 7c1dafb..0000000 --- a/src/test/java/dev/latvian/apps/webutils/test/AnsiTests.java +++ /dev/null @@ -1,33 +0,0 @@ -package dev.latvian.apps.webutils.test; - -import dev.latvian.apps.webutils.ansi.Ansi; -import dev.latvian.apps.webutils.ansi.Log; -import dev.latvian.apps.webutils.html.PairedTag; -import org.junit.jupiter.api.Test; - -public class AnsiTests { - @Test - public void components() { - var c = Ansi.of(); - c.append("GET 200 "); - c.append(Ansi.cyan("Test").underline()); - c.append(" /test"); - var c1 = Ansi.of("WEB ").green().append(c); - - System.out.println(c1); - System.out.println(); - System.out.println(c1.toDebugString()); - System.out.println(); - - Log.error("Hello"); - } - - @Test - public void html() { - var section = new PairedTag("section"); - section.classes("test test-2"); - section.img("img.png"); - section.p().string("Hello!").p().raw("abc").spanstr("yo").raw("test"); - Log.info("Tag:\n" + section.toAnsi(true)); - } -} diff --git a/src/test/java/dev/latvian/apps/webutils/test/JSONTests.java b/src/test/java/dev/latvian/apps/webutils/test/JSONTests.java deleted file mode 100644 index c4985a2..0000000 --- a/src/test/java/dev/latvian/apps/webutils/test/JSONTests.java +++ /dev/null @@ -1,53 +0,0 @@ -package dev.latvian.apps.webutils.test; - -import dev.latvian.apps.webutils.ansi.Ansi; -import dev.latvian.apps.webutils.ansi.Log; -import dev.latvian.apps.webutils.json.JSON; -import dev.latvian.apps.webutils.json.JSONObject; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.List; - -public class JSONTests { - @Test - public void serialize() { - var map = JSONObject.of("a", 10).append("b", "Hi").append("c", List.of(1, 2, 3)); - - Assertions.assertEquals(JSON.DEFAULT.write(map), """ - {"a":10,"b":"Hi","c":[1,2,3]}"""); - } - - @Test - public void deserialize() { - var map = JSON.DEFAULT.read(""" - { "a" : 10 , "b":"Hi","c":[ 1, 2,3 ] }""").readObject(); - - Assertions.assertEquals(map.asArray("c").asInt(2), 3); - } - - @Test - public void adapt() { - var config = JSON.DEFAULT.read(""" - {"database":"https://lat:test@fakedb.com:1234/","discord":[{"clientId":"7"}]}""").adapt(TestConfig.class); - - Assertions.assertEquals(config.database.toString(), "https://lat:test@fakedb.com:1234/"); - Assertions.assertEquals(config.discord[0].clientId, "7"); - Assertions.assertEquals(config.discord[0].clientSecret, "shh"); - } - - @Test - public void readRemoteObject() throws Exception { - // {"hours":672,"total_launches":7864423,"hourly":11700.028795489174,"ml":[{"ml":1,"fraction":0.9412095458242773,"launches":7402070},{"ml":2,"fraction":0.05879045417572275,"launches":462353}],"mc":[{"mc":2001,"fraction":0.6443314404629558,"launches":5067295},{"mc":1902,"fraction":0.3556624561013567,"launches":2797080},{"mc":2004,"fraction":6.103435687525964E-6,"launches":48}],"mlmc":[{"ml":1,"mc":2001,"fraction":0.6154869848684386,"launches":4840450},{"ml":1,"mc":1902,"fraction":0.3257164575201512,"launches":2561572},{"ml":2,"mc":1902,"fraction":0.029945998581205512,"launches":235508},{"ml":2,"mc":2001,"fraction":0.028844455594517232,"launches":226845},{"ml":1,"mc":2004,"fraction":6.103435687525964E-6,"launches":48}],"launches":[{"version":"2001.6.4-build.114","fraction":0.26559062247796184,"launches":2088717},{"version":"2001.6.4-build.120","fraction":0.21153312836809515,"launches":1663586},{"version":"1902.6.2-build.45","fraction":0.1828411315108559,"launches":1437940},{"version":"2001.6.4-build.127","fraction":0.0810527358459737,"launches":637433},{"version":"1902.6.2-build.3","fraction":0.038601560470488426,"launches":303579},{"version":"2001.6.4-build.95","fraction":0.03645264248883866,"launches":286679},{"version":"1902.6.2-build.15","fraction":0.02442060911525232,"launches":192054},{"version":"1902.6.2-build.50","fraction":0.018523800156731142,"launches":145679},{"version":"2001.6.3-build.83","fraction":0.018382658206457105,"launches":144569},{"version":"1902.6.2-build.27","fraction":0.01564005394928528,"launches":123000},{"version":"","fraction":1.3987040117246999E-6,"launches":11}]} - var content = "{\"hours\":672,\"total_launches\":7864423,\"hourly\":11700.028795489174,\"ml\":[{\"ml\":1,\"fraction\":0.9412095458242773,\"launches\":7402070},{\"ml\":2,\"fraction\":0.05879045417572275,\"launches\":462353}],\"mc\":[{\"mc\":2001,\"fraction\":0.6443314404629558,\"launches\":5067295},{\"mc\":1902,\"fraction\":0.3556624561013567,\"launches\":2797080},{\"mc\":2004,\"fraction\":6.103435687525964E-6,\"launches\":48}],\"mlmc\":[{\"ml\":1,\"mc\":2001,\"fraction\":0.6154869848684386,\"launches\":4840450},{\"ml\":1,\"mc\":1902,\"fraction\":0.3257164575201512,\"launches\":2561572},{\"ml\":2,\"mc\":1902,\"fraction\":0.029945998581205512,\"launches\":235508},{\"ml\":2,\"mc\":2001,\"fraction\":0.028844455594517232,\"launches\":226845},{\"ml\":1,\"mc\":2004,\"fraction\":6.103435687525964E-6,\"launches\":48}],\"launches\":[{\"version\":\"2001.6.4-build.114\",\"fraction\":0.26559062247796184,\"launches\":2088717},{\"version\":\"2001.6.4-build.120\",\"fraction\":0.21153312836809515,\"launches\":1663586},{\"version\":\"1902.6.2-build.45\",\"fraction\":0.1828411315108559,\"launches\":1437940},{\"version\":\"2001.6.4-build.127\",\"fraction\":0.0810527358459737,\"launches\":637433},{\"version\":\"1902.6.2-build.3\",\"fraction\":0.038601560470488426,\"launches\":303579},{\"version\":\"2001.6.4-build.95\",\"fraction\":0.03645264248883866,\"launches\":286679},{\"version\":\"1902.6.2-build.15\",\"fraction\":0.02442060911525232,\"launches\":192054},{\"version\":\"1902.6.2-build.50\",\"fraction\":0.018523800156731142,\"launches\":145679},{\"version\":\"2001.6.3-build.83\",\"fraction\":0.018382658206457105,\"launches\":144569},{\"version\":\"1902.6.2-build.27\",\"fraction\":0.01564005394928528,\"launches\":123000},{\"version\":\"\",\"fraction\":1.3987040117246999E-6,\"launches\":11}]}"; - Log.info(content); - var json = JSON.DEFAULT.read(content).readObject(); - json.removeDeep((key, index, value) -> key.equals("fraction") && ((Number) value).doubleValue() < 0.5D, true); - - Log.info(Ansi.ofObject(json)); - Log.info(JSON.DEFAULT.writePretty(json)); - - Log.info(json.asInt("total_launches")); - Log.info(json.asDouble("hourly")); - } -} diff --git a/src/test/java/dev/latvian/apps/webutils/test/TestConfig.java b/src/test/java/dev/latvian/apps/webutils/test/TestConfig.java deleted file mode 100644 index 036ac5d..0000000 --- a/src/test/java/dev/latvian/apps/webutils/test/TestConfig.java +++ /dev/null @@ -1,20 +0,0 @@ -package dev.latvian.apps.webutils.test; - -import java.net.URI; - -public class TestConfig { - public URI database = null; - public WebConfig web = new WebConfig(); - public DiscordConfig[] discord = new DiscordConfig[0]; - - public static class WebConfig { - public int port = 12345; - public String title = "Test"; - } - - public static class DiscordConfig { - public String botToken = "1a2b3c"; - public String clientId = "12345"; - public String clientSecret = "shh"; - } -} diff --git a/src/test/java/dev/latvian/apps/webutils/test/XMLTests.java b/src/test/java/dev/latvian/apps/webutils/test/XMLTests.java index 7a7e3ef..32cb123 100644 --- a/src/test/java/dev/latvian/apps/webutils/test/XMLTests.java +++ b/src/test/java/dev/latvian/apps/webutils/test/XMLTests.java @@ -1,6 +1,7 @@ package dev.latvian.apps.webutils.test; -import dev.latvian.apps.webutils.ansi.Log; +import dev.latvian.apps.ansi.log.Log; +import dev.latvian.apps.webutils.html.TagANSI; import dev.latvian.apps.webutils.html.XMLParser; import org.junit.jupiter.api.Test; @@ -16,6 +17,6 @@ public void xml() { Reminder Don't forget me this weekend! """, false); - Log.info("XML:\n" + xml.toAnsi(true)); + Log.info("XML:\n" + TagANSI.of(xml, true)); } }