You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2021/12/02 11:04:23 UTC

[plc4x] branch develop updated: feat(plc4j/codegen): render virtual fields in boxes

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

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new 17086bd  feat(plc4j/codegen): render virtual fields in boxes
17086bd is described below

commit 17086bd6b2df6ec283cffd7be5d4782d02196b84
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Dec 2 12:04:16 2021 +0100

    feat(plc4j/codegen): render virtual fields in boxes
---
 .../templates/java/pojo-template.java.ftlh         |  1 +
 .../plc4x/java/spi/generation/WriteBuffer.java     |  4 +
 .../java/spi/generation/WriteBufferBoxBased.java   | 91 +++++++++++++++------
 .../plc4x/java/spi/utils/ascii/AsciiBox.java       | 28 ++++---
 .../{AsciiBoxUtils.java => AsciiBoxWriter.java}    | 94 +++++++++++++---------
 ...iiBoxUtilsTest.java => AsciiBoxWriterTest.java} | 83 ++++++++++---------
 6 files changed, 190 insertions(+), 111 deletions(-)

diff --git a/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
index e3d7203..07dc000 100644
--- a/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/pojo-template.java.ftlh
@@ -296,6 +296,7 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
 
                         // Virtual field (doesn't actually serialize anything, just makes the value available)
                         ${helper.getLanguageTypeNameForField(field)} ${namedField.name} = get${namedField.name?cap_first}();
+                        writeBuffer.writeVirtual("${namedField.name}", ${namedField.name});
                         <#break>
                 </#switch>
             </#list>
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
index bd75d3d..7cf9eca 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
@@ -128,6 +128,10 @@ public interface WriteBuffer extends ByteOrderAware {
 
     void writeString(String logicalName, int bitLength, String encoding, String value, WithWriterArgs... writerArgs) throws SerializationException;
 
+    default void writeVirtual(String logicalName, Object value, WithWriterArgs... writerArgs) throws SerializationException {
+        // No-Op
+    }
+
     default void writeString(int bitLength, String encoding, String value) throws SerializationException {
         writeString("", bitLength, encoding, value);
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferBoxBased.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferBoxBased.java
index cb0c04f..82e03b9 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferBoxBased.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferBoxBased.java
@@ -21,7 +21,9 @@ package org.apache.plc4x.java.spi.generation;
 
 import io.vavr.control.Either;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.plc4x.java.spi.utils.Serializable;
 import org.apache.plc4x.java.spi.utils.ascii.AsciiBox;
+import org.apache.plc4x.java.spi.utils.ascii.AsciiBoxWriter;
 import org.apache.plc4x.java.spi.utils.hex.Hex;
 
 import java.math.BigDecimal;
@@ -30,21 +32,28 @@ import java.util.Collections;
 import java.util.LinkedList;
 import java.util.Deque;
 
-import static org.apache.plc4x.java.spi.utils.ascii.AsciiBoxUtils.*;
-
 public class WriteBufferBoxBased implements WriteBuffer, BufferCommons {
 
-    private Deque<Either<AsciiBox, Deque<AsciiBox>>> boxes = new LinkedList<>();
-    private int desiredWidth = 120;
-    private int currentWidth = 118;
-    private boolean mergeSingleBoxes;
-    private boolean omitEmptyBoxes;
+    private final Deque<Either<AsciiBox, Deque<AsciiBox>>> boxes = new LinkedList<>();
+    private final AsciiBoxWriter asciiBoxWriter;
+    private final AsciiBoxWriter asciiBoxWriterLight;
+    private final int desiredWidth = 120;
+    private final boolean mergeSingleBoxes;
+    private final boolean omitEmptyBoxes;
+    private int currentWidth = desiredWidth - 2;
 
     public WriteBufferBoxBased() {
-
+        this(false, false);
     }
 
     public WriteBufferBoxBased(boolean mergeSingleBoxes, boolean omitEmptyBoxes) {
+        this(AsciiBoxWriter.DEFAULT, AsciiBoxWriter.LIGHT, mergeSingleBoxes, omitEmptyBoxes);
+    }
+
+
+    private WriteBufferBoxBased(AsciiBoxWriter asciiBoxWriter, AsciiBoxWriter asciiBoxWriterLight, boolean mergeSingleBoxes, boolean omitEmptyBoxes) {
+        this.asciiBoxWriter = asciiBoxWriter;
+        this.asciiBoxWriterLight = asciiBoxWriterLight;
         this.mergeSingleBoxes = mergeSingleBoxes;
         this.omitEmptyBoxes = omitEmptyBoxes;
     }
@@ -74,13 +83,13 @@ public class WriteBufferBoxBased implements WriteBuffer, BufferCommons {
     @Override
     public void writeBit(String logicalName, boolean value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("b%d %b%s", value ? 1 : 0, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("b%d %b%s", value ? 1 : 0, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeByte(String logicalName, byte value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("%02x%s", value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("%02x%s", value, additionalStringRepresentation), 0)));
     }
 
     @Override
@@ -89,91 +98,121 @@ public class WriteBufferBoxBased implements WriteBuffer, BufferCommons {
         if (StringUtils.isNotBlank(additionalStringRepresentation)) {
             additionalStringRepresentation += "\n";
         }
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("%s%s", Hex.dump(bytes), additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("%s%s", Hex.dump(bytes), additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeUnsignedByte(String logicalName, int bitLength, byte value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeUnsignedShort(String logicalName, int bitLength, short value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeUnsignedInt(String logicalName, int bitLength, int value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeUnsignedLong(String logicalName, int bitLength, long value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeUnsignedBigInteger(String logicalName, int bitLength, BigInteger value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeSignedByte(String logicalName, int bitLength, byte value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeShort(String logicalName, int bitLength, short value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeInt(String logicalName, int bitLength, int value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeLong(String logicalName, int bitLength, long value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeBigInteger(String logicalName, int bitLength, BigInteger value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeFloat(String logicalName, int bitLength, float value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeDouble(String logicalName, int bitLength, double value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeBigDecimal(String logicalName, int bitLength, BigDecimal value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("0x%0" + Math.max(bitLength / 4, 1) + "x %d%s", value, value, additionalStringRepresentation), 0)));
     }
 
     @Override
     public void writeString(String logicalName, int bitLength, String encoding, String value, WithWriterArgs... writerArgs) throws SerializationException {
         String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
-        boxes.offerLast(Either.left(boxString(logicalName, String.format("%s%s", value, additionalStringRepresentation), 0)));
+        boxes.offerLast(Either.left(asciiBoxWriter.boxString(logicalName, String.format("%s%s", value, additionalStringRepresentation), 0)));
+    }
+
+    @Override
+    public void writeVirtual(String logicalName, Object value, WithWriterArgs... writerArgs) throws SerializationException {
+        String additionalStringRepresentation = extractAdditionalStringRepresentation(writerArgs).map(s -> " " + s).orElse("");
+        AsciiBox virtualBox;
+        if (value instanceof String) {
+            virtualBox = asciiBoxWriterLight.boxString(logicalName, String.format("%s%s", value, additionalStringRepresentation), 0);
+        } else if (value instanceof Number) {
+            // TODO: adjust rendering
+            Number number = (Number) value;
+            virtualBox = asciiBoxWriterLight.boxString(logicalName, String.format("0x%x %d%s", number, number, additionalStringRepresentation), 0);
+        } else if (value instanceof Boolean) {
+            virtualBox = asciiBoxWriterLight.boxString(logicalName, String.format("b%d %b%s", (Boolean) value ? 1 : 0, value, additionalStringRepresentation), 0);
+        } else if (value instanceof Enum) {
+            Enum<?> enumValue = (Enum<?>) value;
+            virtualBox = asciiBoxWriterLight.boxString(logicalName, String.format("%s%s", enumValue.name(), additionalStringRepresentation), 0);
+        } else if (value instanceof Serializable) {
+            Serializable serializable = (Serializable) value;
+            try {
+                WriteBufferBoxBased writeBuffer = new WriteBufferBoxBased(asciiBoxWriterLight, asciiBoxWriterLight, true, true);
+                serializable.serialize(writeBuffer);
+                virtualBox = asciiBoxWriterLight.boxBox(logicalName, writeBuffer.getBox(), 0);
+            } catch (SerializationException e) {
+                virtualBox = asciiBoxWriterLight.boxString(logicalName, e.getMessage(), 0);
+            }
+        } else {
+            virtualBox = asciiBoxWriterLight.boxString(logicalName, "un-renderable", 0);
+        }
+        boxes.offerLast(Either.left(virtualBox));
     }
 
     @Override
@@ -208,7 +247,7 @@ public class WriteBufferBoxBased implements WriteBuffer, BufferCommons {
             boxes.offerLast(Either.left(onlyChild));
             return;
         }
-        AsciiBox asciiBox = boxBox(logicalName, alignBoxes(finalBoxes, currentWidth), 0);
+        AsciiBox asciiBox = asciiBoxWriter.boxBox(logicalName, asciiBoxWriter.alignBoxes(finalBoxes, currentWidth), 0);
         if (omitEmptyBoxes && asciiBox.isEmpty()) {
             return;
         }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBox.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBox.java
index 0029584..c9c3b48 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBox.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBox.java
@@ -24,12 +24,18 @@ import org.apache.commons.lang3.StringUtils;
 import java.util.Objects;
 import java.util.regex.Matcher;
 
-import static org.apache.plc4x.java.spi.utils.ascii.AsciiBoxUtils.*;
-
 public class AsciiBox {
+    private final AsciiBoxWriter asciiBoxWriter;
+
     private final String data;
 
-    public AsciiBox(String data) {
+    protected AsciiBox(String data) {
+        asciiBoxWriter = AsciiBoxWriter.DEFAULT;
+        this.data = data;
+    }
+
+    protected AsciiBox(AsciiBoxWriter asciiBoxWriter, String data) {
+        this.asciiBoxWriter = asciiBoxWriter;
         this.data = data;
     }
 
@@ -62,7 +68,7 @@ public class AsciiBox {
     }
 
     public String getBoxName() {
-        Matcher matcher = boxNameRegex.matcher(data);
+        Matcher matcher = asciiBoxWriter.boxNameRegex.matcher(data);
         if (!matcher.find()) {
             return "";
         }
@@ -70,17 +76,17 @@ public class AsciiBox {
     }
 
     public AsciiBox changeBoxName(String newName) {
-        if (!hasBorders(this)) {
-            return boxString(newName, this.toString(), 0);
+        if (!asciiBoxWriter.hasBorders(this)) {
+            return asciiBoxWriter.boxString(newName, this.toString(), 0);
         }
-        int minimumWidthWithNewName = (upperLeftCorner + horizontalLine + newName + upperRightCorner).length();
-        int nameLengthDifference = minimumWidthWithNewName - (unwrap(this).width() + borderWidth + borderWidth);
-        return boxString(newName, unwrap(this).toString(), this.width() + nameLengthDifference);
+        int minimumWidthWithNewName = (asciiBoxWriter.upperLeftCorner + asciiBoxWriter.horizontalLine + newName + asciiBoxWriter.upperRightCorner).length();
+        int nameLengthDifference = minimumWidthWithNewName - (asciiBoxWriter.unwrap(this).width() + asciiBoxWriter.borderWidth + asciiBoxWriter.borderWidth);
+        return asciiBoxWriter.boxString(newName, asciiBoxWriter.unwrap(this).toString(), this.width() + nameLengthDifference);
     }
 
     public boolean isEmpty() {
-        if (hasBorders(this)) {
-            return StringUtils.isBlank(unwrap(this).toString());
+        if (asciiBoxWriter.hasBorders(this)) {
+            return StringUtils.isBlank(asciiBoxWriter.unwrap(this).toString());
         }
         return StringUtils.isBlank(this.toString());
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxUtils.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxWriter.java
similarity index 76%
rename from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxUtils.java
rename to plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxWriter.java
index 04048c5..c952f41 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxUtils.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxWriter.java
@@ -30,25 +30,53 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.regex.Pattern;
 
-public class AsciiBoxUtils {
+public class AsciiBoxWriter {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(AsciiBoxUtils.class);
+    private final Logger LOGGER = LoggerFactory.getLogger(AsciiBoxWriter.class);
 
-    static final String upperLeftCorner = "╔";
-    static final String upperRightCorner = "╗";
-    static final String horizontalLine = "═";
-    static final String verticalLine = "║";
-    static final String lowerLeftCorner = "╚";
-    static final String lowerRightCorner = "╝";
-    static final String newLine = "\n";
-    static final String emptyPadding = " ";
+    public static AsciiBoxWriter DEFAULT = new AsciiBoxWriter();
+
+    //public static AsciiBoxWriter LIGHT = new AsciiBoxWriter("┌","┐","┄","┆","└","┘");
+    public static AsciiBoxWriter LIGHT = new AsciiBoxWriter("╭","╮","┄","┆","╰","╯");
+
+    final String upperLeftCorner;
+    final String upperRightCorner;
+    final String horizontalLine;
+    final String verticalLine;
+    final String lowerLeftCorner;
+    final String lowerRightCorner;
+    final String newLine;
+    final String emptyPadding;
     // the name gets prefixed with a extra symbol for indent
-    static final int extraNameCharIndent = 1;
-    static final int borderWidth = 1;
-    static final int newLineCharWidth = 1;
-    static Pattern boxNameRegex = Pattern.compile("^" + upperLeftCorner + horizontalLine + "(?<name>[\\w /]+)" + horizontalLine + "*" + upperRightCorner);
+    final int extraNameCharIndent;
+    final int borderWidth;
+    final int newLineCharWidth;
+    final Pattern boxNameRegex;
+
+    public AsciiBoxWriter() {
+        this("╔", "╗", "═", "║", "╚", "╝");
+    }
 
-    static boolean DebugAsciiBox;
+    public AsciiBoxWriter(String upperLeftCorner,
+                          String upperRightCorner,
+                          String horizontalLine,
+                          String verticalLine,
+                          String lowerLeftCorner,
+                          String lowerRightCorner) {
+        this.upperLeftCorner = upperLeftCorner;
+        this.upperRightCorner = upperRightCorner;
+        this.horizontalLine = horizontalLine;
+        this.verticalLine = verticalLine;
+        this.lowerLeftCorner = lowerLeftCorner;
+        this.lowerRightCorner = lowerRightCorner;
+        this.newLine = "\n";
+        this.emptyPadding = " ";
+        // the name gets prefixed with a extra symbol for indent
+        this.extraNameCharIndent = 1;
+        this.borderWidth = 1;
+        this.newLineCharWidth = 1;
+        this.boxNameRegex = Pattern.compile("^" + upperLeftCorner + horizontalLine + "(?<name>[\\w /]+)" + horizontalLine + "*" + upperRightCorner);
+    }
 
     /**
      * BoxBox boxes a box
@@ -58,7 +86,7 @@ public class AsciiBoxUtils {
      * @param charWidth the desired width
      * @return boxed data
      */
-    public static AsciiBox boxBox(String name, AsciiBox box, int charWidth) {
+    public AsciiBox boxBox(String name, AsciiBox box, int charWidth) {
         return boxString(name, box.toString(), charWidth);
     }
 
@@ -70,19 +98,16 @@ public class AsciiBoxUtils {
      * @param charWidth desired width
      * @return boxed data
      */
-    public static AsciiBox boxString(String name, String data, int charWidth) {
+    public AsciiBox boxString(String name, String data, int charWidth) {
         AsciiBox rawBox = new AsciiBox(data);
         int longestLine = rawBox.width();
         if (charWidth < longestLine) {
-            if (DebugAsciiBox) {
-                LOGGER.debug("Overflow by {} chars", longestLine - charWidth);
-            }
+            LOGGER.trace("Overflow by {} chars", longestLine - charWidth);
             charWidth = longestLine + borderWidth + borderWidth;
         }
         StringBuilder boxedString = new StringBuilder();
         int namePadding = (Math.max(charWidth - name.length() - borderWidth - extraNameCharIndent - borderWidth, 0));
-        boxedString.append(upperLeftCorner + horizontalLine).append(name).append(StringUtils.repeat(horizontalLine, namePadding)).append(upperRightCorner);
-        boxedString.append(newLine);
+        boxedString.append(upperLeftCorner).append(horizontalLine).append(name).append(StringUtils.repeat(horizontalLine, namePadding)).append(upperRightCorner).append(newLine);
         // Name of the header stretches the box so we align to that
         charWidth = borderWidth + extraNameCharIndent + name.length() + namePadding + borderWidth;
         for (String line : rawBox.lines()) {
@@ -92,8 +117,7 @@ public class AsciiBoxUtils {
             }
             int frontPadding = (int) Math.floor(linePadding / 2.0);
             int backPadding = (int) Math.ceil(linePadding / 2.0);
-            boxedString.append(verticalLine).append(StringUtils.repeat(emptyPadding, frontPadding)).append(line).append(StringUtils.repeat(emptyPadding, backPadding)).append(verticalLine);
-            boxedString.append(newLine);
+            boxedString.append(verticalLine).append(StringUtils.repeat(emptyPadding, frontPadding)).append(line).append(StringUtils.repeat(emptyPadding, backPadding)).append(verticalLine).append(newLine);
         }
         int bottomPadding = namePadding + name.length() + extraNameCharIndent;
         boxedString.append(lowerLeftCorner).append(StringUtils.repeat(horizontalLine, bottomPadding)).append(lowerRightCorner);
@@ -107,7 +131,7 @@ public class AsciiBoxUtils {
      * @param desiredWidth width desired
      * @return the aligned box.
      */
-    public static AsciiBox alignBoxes(Collection<AsciiBox> boxes, int desiredWidth) {
+    public AsciiBox alignBoxes(Collection<AsciiBox> boxes, int desiredWidth) {
         if (boxes.size() == 0) {
             return new AsciiBox("");
         }
@@ -115,15 +139,11 @@ public class AsciiBoxUtils {
         for (AsciiBox box : boxes) {
             int boxWidth = box.width();
             if (boxWidth > actualWidth) {
-                if (DebugAsciiBox) {
-                    LOGGER.debug("Overflow by {} chars", boxWidth - desiredWidth);
-                }
+                LOGGER.trace("Overflow by {} chars", boxWidth - desiredWidth);
                 actualWidth = boxWidth;
             }
         }
-        if (DebugAsciiBox) {
-            LOGGER.debug("Working with {} chars", actualWidth);
-        }
+        LOGGER.trace("Working with {} chars", actualWidth);
         AsciiBox bigBox = new AsciiBox("");
         List<AsciiBox> currentBoxRow = new LinkedList<>();
         int currentRowLength = 0;
@@ -160,7 +180,7 @@ public class AsciiBoxUtils {
      * @param box2 right of box1
      * @return box1 left of box2
      */
-    public static AsciiBox boxSideBySide(AsciiBox box1, AsciiBox box2) {
+    public AsciiBox boxSideBySide(AsciiBox box1, AsciiBox box2) {
         StringBuilder aggregateBox = new StringBuilder();
         int box1Width = box1.width();
         String[] box1Lines = box1.lines();
@@ -202,7 +222,7 @@ public class AsciiBoxUtils {
      * @param box2 below box1
      * @return box1 above box2
      */
-    public static AsciiBox boxBelowBox(AsciiBox box1, AsciiBox box2) {
+    public AsciiBox boxBelowBox(AsciiBox box1, AsciiBox box2) {
         int box1Width = box1.width();
         int box2Width = box2.width();
         if (box1Width < box2Width) {
@@ -213,7 +233,7 @@ public class AsciiBoxUtils {
         return new AsciiBox(box1.toString() + "\n" + box2.toString());
     }
 
-    static AsciiBox mergeHorizontal(List<AsciiBox> boxes) {
+    AsciiBox mergeHorizontal(List<AsciiBox> boxes) {
         switch (boxes.size()) {
             case 0:
                 return new AsciiBox("");
@@ -226,7 +246,7 @@ public class AsciiBoxUtils {
         }
     }
 
-    static AsciiBox expandBox(AsciiBox box, int desiredWidth) {
+    AsciiBox expandBox(AsciiBox box, int desiredWidth) {
         if (box.width() >= desiredWidth) {
             return box;
         }
@@ -252,7 +272,7 @@ public class AsciiBoxUtils {
      * @param box the box to be checked
      * @return true if it has borders
      */
-    public static boolean hasBorders(AsciiBox box) {
+    public boolean hasBorders(AsciiBox box) {
         if (StringUtils.isBlank(box.toString())) {
             return false;
         }
@@ -260,7 +280,7 @@ public class AsciiBoxUtils {
         return upperLeftCorner.equals(box.toString().substring(0, 1));
     }
 
-    public static AsciiBox unwrap(AsciiBox box) {
+    public AsciiBox unwrap(AsciiBox box) {
         if (!hasBorders(box)) {
             return box;
         }
diff --git a/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxUtilsTest.java b/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxWriterTest.java
similarity index 94%
rename from plc4j/spi/src/test/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxUtilsTest.java
rename to plc4j/spi/src/test/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxWriterTest.java
index 469441a..03ddd9b 100644
--- a/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxUtilsTest.java
+++ b/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/utils/ascii/AsciiBoxWriterTest.java
@@ -27,36 +27,30 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
-import static org.apache.plc4x.java.spi.utils.ascii.AsciiBoxUtils.*;
 import static org.junit.jupiter.api.Assertions.*;
 
-class AsciiBoxUtilsTest {
-
-    @BeforeEach
-    void setUp() {
-        AsciiBoxUtils.DebugAsciiBox = true;
-    }
+class AsciiBoxWriterTest {
 
     @Nested
     class GetBoxName {
         @Test
         void simpleName() {
-            assertEquals("someName", boxString("someName", "some content", 0).getBoxName());
+            assertEquals("someName", AsciiBoxWriter.DEFAULT.boxString("someName", "some content", 0).getBoxName());
         }
 
         @Test
         void noName() {
-            assertEquals("", boxString("", "some content", 0).getBoxName());
+            assertEquals("", AsciiBoxWriter.DEFAULT.boxString("", "some content", 0).getBoxName());
         }
 
         @Test
         void longName() {
-            assertEquals("veryLongName12_13", boxString("veryLongName12_13", "some content", 0).getBoxName());
+            assertEquals("veryLongName12_13", AsciiBoxWriter.DEFAULT.boxString("veryLongName12_13", "some content", 0).getBoxName());
         }
 
         @Test
         void nameWithSpacesAndSlashes() {
-            assertEquals("payload / Message / Concrete Message", boxString("payload / Message / Concrete Message", "some content", 0).getBoxName());
+            assertEquals("payload / Message / Concrete Message", AsciiBoxWriter.DEFAULT.boxString("payload / Message / Concrete Message", "some content", 0).getBoxName());
         }
     }
 
@@ -64,23 +58,23 @@ class AsciiBoxUtilsTest {
     class ChangeBoxName {
         @Test
         void boxWithSimpleName() {
-            AsciiBox asciiBox = boxString("simpleName", "some content", 0);
+            AsciiBox asciiBox = AsciiBoxWriter.DEFAULT.boxString("simpleName", "some content", 0);
             asciiBox = asciiBox.changeBoxName("newSimpleName");
-            assertEquals(boxString("newSimpleName", "some content", 0), asciiBox);
+            assertEquals(AsciiBoxWriter.DEFAULT.boxString("newSimpleName", "some content", 0), asciiBox);
         }
 
         @Test
         void boxWithShorterName() {
-            AsciiBox asciiBox = boxString("veryLongName", "some content", 0);
+            AsciiBox asciiBox = AsciiBoxWriter.DEFAULT.boxString("veryLongName", "some content", 0);
             asciiBox = asciiBox.changeBoxName("name");
-            assertEquals(boxString("name", "some content", 0), asciiBox);
+            assertEquals(AsciiBoxWriter.DEFAULT.boxString("name", "some content", 0), asciiBox);
         }
 
         @Test
         void boxGettingDressed() {
-            AsciiBox asciiBox = boxString("", "some content", 0);
+            AsciiBox asciiBox = AsciiBoxWriter.DEFAULT.boxString("", "some content", 0);
             asciiBox = asciiBox.changeBoxName("name");
-            assertEquals(boxString("name", "some content", 0), asciiBox);
+            assertEquals(AsciiBoxWriter.DEFAULT.boxString("name", "some content", 0), asciiBox);
         }
     }
 
@@ -98,12 +92,12 @@ class AsciiBoxUtilsTest {
 
         @Test
         void nameEmptyBox() {
-            assertTrue(boxString("name", "", 0).isEmpty());
+            assertTrue(AsciiBoxWriter.DEFAULT.boxString("name", "", 0).isEmpty());
         }
 
         @Test
         void nameNonEmptyBox() {
-            assertFalse(boxString("name", "a", 0).isEmpty());
+            assertFalse(AsciiBoxWriter.DEFAULT.boxString("name", "a", 0).isEmpty());
         }
     }
 
@@ -137,7 +131,7 @@ class AsciiBoxUtilsTest {
                 "                                                  ║  120 0x: 38  39  30  61  62  63  64  65  66  67  68  69  6a  6b  6c  6d  6e  6f  70  71  72  73  74  75  '890abcdefghijklmnopqrstu'  ║\n" +
                 "                                                  ║  144 0x: 76  77  78  79  7a  d3  61  61  62                                                              'vwxyz.aab               '  ║\n" +
                 "                                                  ╚══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝";
-            assertEquals(new AsciiBox(want), boxSideBySide(new AsciiBox(box1), new AsciiBox(box2)));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.boxSideBySide(new AsciiBox(box1), new AsciiBox(box2)));
         }
 
         @Test
@@ -154,7 +148,7 @@ class AsciiBoxUtilsTest {
                 "╔═exampleInt╗╔═exampleInt╗\n" +
                 "║     4     ║║     7     ║\n" +
                 "╚═══════════╝╚═══════════╝";
-            assertEquals(new AsciiBox(want), boxSideBySide(new AsciiBox(box1), new AsciiBox(box2)));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.boxSideBySide(new AsciiBox(box1), new AsciiBox(box2)));
         }
 
         @Test
@@ -173,7 +167,7 @@ class AsciiBoxUtilsTest {
                 "║     4     ║║     7     ║\n" +
                 "║     4     ║╚═══════════╝\n" +
                 "╚═══════════╝             ";
-            assertEquals(new AsciiBox(want), boxSideBySide(new AsciiBox(box1), new AsciiBox(box2)));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.boxSideBySide(new AsciiBox(box1), new AsciiBox(box2)));
         }
 
         @Test
@@ -192,7 +186,7 @@ class AsciiBoxUtilsTest {
                 "║     4     ║║     7     ║\n" +
                 "╚═══════════╝║     7     ║\n" +
                 "             ╚═══════════╝";
-            assertEquals(new AsciiBox(want), boxSideBySide(new AsciiBox(box1), new AsciiBox(box2)));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.boxSideBySide(new AsciiBox(box1), new AsciiBox(box2)));
         }
     }
 
@@ -231,7 +225,7 @@ class AsciiBoxUtilsTest {
                 "║  120 38  39  30  61  62  63  64  65  66  67  68  69  6a  6b  6c  6d  6e  6f  70  71  72  73  74  75  '890abcdefghijklmnopqrstu'  ║\n" +
                 "║  144 76  77  78  79  7a  d3  61  61  62                                                              'vwxyz.aab               '  ║\n" +
                 "╚══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝";
-            assertEquals(new AsciiBox(want), boxBelowBox(new AsciiBox(box1), new AsciiBox(box2)));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.boxBelowBox(new AsciiBox(box1), new AsciiBox(box2)));
         }
 
         @Test
@@ -251,7 +245,7 @@ class AsciiBoxUtilsTest {
                 "╔═sampleField╗            \n" +
                 "║123123123123║            \n" +
                 "╚════════════╝            ";
-            assertEquals(new AsciiBox(want), boxBelowBox(new AsciiBox(box1), new AsciiBox(box2)));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.boxBelowBox(new AsciiBox(box1), new AsciiBox(box2)));
         }
     }
 
@@ -266,7 +260,7 @@ class AsciiBoxUtilsTest {
                 "╔═sampleField╗\n" +
                 "║123123123123║\n" +
                 "╚════════════╝";
-            assertEquals(new AsciiBox(want), boxString(name, data, charWidth));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.boxString(name, data, charWidth));
         }
 
         @Test
@@ -278,7 +272,7 @@ class AsciiBoxUtilsTest {
                 "╔════════════╗\n" +
                 "║123123123123║\n" +
                 "╚════════════╝";
-            assertEquals(new AsciiBox(want), boxString(name, data, charWidth));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.boxString(name, data, charWidth));
         }
 
         @Test
@@ -291,7 +285,7 @@ class AsciiBoxUtilsTest {
                 "║      123123123123      ║\n" +
                 "║123123123123123123123123║\n" +
                 "╚════════════════════════╝";
-            assertEquals(new AsciiBox(want), boxString(name, data, charWidth));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.boxString(name, data, charWidth));
         }
 
         @Test
@@ -304,7 +298,7 @@ class AsciiBoxUtilsTest {
                 "║                123123123123                 ║\n" +
                 "║          123123123123123123123123           ║\n" +
                 "╚═════════════════════════════════════════════╝";
-            assertEquals(new AsciiBox(want), boxString(name, data, charWidth));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.boxString(name, data, charWidth));
         }
     }
 
@@ -330,7 +324,7 @@ class AsciiBoxUtilsTest {
                 "║      123123123123      ║║      123123123123      ║\n" +
                 "║123123ABABABABABAB123123║║123123123123123123123123║\n" +
                 "╚════════════════════════╝╚════════════════════════╝";
-            assertEquals(new AsciiBox(want), alignBoxes(boxes, desiredWidth));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.alignBoxes(boxes, desiredWidth));
         }
 
         @Test
@@ -357,7 +351,7 @@ class AsciiBoxUtilsTest {
                 "║      123123123123      ║\n" +
                 "║123123123123123123123123║\n" +
                 "╚════════════════════════╝";
-            assertEquals(new AsciiBox(want), alignBoxes(boxes, desiredWidth));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.alignBoxes(boxes, desiredWidth));
         }
 
         @Test
@@ -422,7 +416,7 @@ class AsciiBoxUtilsTest {
                 "║      123123123123      ║║      123123123123      ║\n" +
                 "║123123ABABABABABAB123123║║123123123123123123123123║\n" +
                 "╚════════════════════════╝╚════════════════════════╝";
-            assertEquals(new AsciiBox(want), alignBoxes(boxes, desiredWidth));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.alignBoxes(boxes, desiredWidth));
         }
 
         @Test
@@ -483,7 +477,7 @@ class AsciiBoxUtilsTest {
                 "║      123123123123      ║║      123123123123      ║                          \n" +
                 "║123123ABABABABABAB123123║║123123123123123123123123║                          \n" +
                 "╚════════════════════════╝╚════════════════════════╝                          ";
-            assertEquals(new AsciiBox(want), alignBoxes(boxes, desiredWidth));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.alignBoxes(boxes, desiredWidth));
         }
     }
 
@@ -530,7 +524,7 @@ class AsciiBoxUtilsTest {
                 "123123123abcabcabczxyzxyzxy\n" +
                 "123123123abcabcabczxyzxyzxy\n" +
                 "123123123abcabcabczxyzxyzxy";
-            assertEquals(new AsciiBox(want), mergeHorizontal(boxes));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.mergeHorizontal(boxes));
         }
 
         @Test
@@ -553,7 +547,7 @@ class AsciiBoxUtilsTest {
                 "123123123abcabcabc                  zxyzxyzxy\n" +
                 "123123123abcabcabcabcabcabcabcabcabczxyzxyzxy\n" +
                 "123123123abcabcabc                  zxyzxyzxy";
-            assertEquals(new AsciiBox(want), mergeHorizontal(boxes));
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.DEFAULT.mergeHorizontal(boxes));
         }
     }
 
@@ -569,7 +563,7 @@ class AsciiBoxUtilsTest {
                 "123123123                                                                                           \n" +
                 "123123123                                                                                           \n" +
                 "123123123                                                                                           ");
-            assertEquals(want, expandBox(box, 100));
+            assertEquals(want, AsciiBoxWriter.DEFAULT.expandBox(box, 100));
         }
 
         @Test
@@ -582,7 +576,22 @@ class AsciiBoxUtilsTest {
                 "123123123                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   [...]
                 "123123123                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   [...]
                 "123123123                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   [...]
-            assertEquals(want, expandBox(box, 10000));
+            assertEquals(want, AsciiBoxWriter.DEFAULT.expandBox(box, 10000));
+        }
+    }
+
+    @Nested
+    class LightBoxString {
+        @Test
+        void simpleBox() {
+            String name = "sampleField";
+            String data = "123123123123";
+            int charWidth = 1;
+            String want = "" +
+                "╭┄sampleField╮\n" +
+                "┆123123123123┆\n" +
+                "╰┄┄┄┄┄┄┄┄┄┄┄┄╯";
+            assertEquals(new AsciiBox(want), AsciiBoxWriter.LIGHT.boxString(name, data, charWidth));
         }
     }
 }
\ No newline at end of file