Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ The sorting looks like this:
## TableBuilder Usage
`TableBuilder` builds a `PrettyTable` from a `Map` or a `List`. The constructor takes an optional `BuilderConfig`. The data is passed to `build`, which returns the table. `build` returns `null` for `null` or an empty map or list, and throws `IllegalArgumentException` for any other type.

A map becomes a Property / Value table. Nested maps become nested tables, and a list of plain values is joined into one cell. `null` renders as `None`. Booleans render as `True` and `False`.
A map becomes a Property / Value table. Nested maps become nested tables, and a list of plain values is joined into one cell. The `BuilderConfig` provides configurability for how `null`, `True`, and `False` values show up.

A list of strings, numbers, or booleans becomes one Items column with a caption such as `Found 6 items`. A list of maps uses the first matching key field (`name`, then `id`) as the row name. One other field becomes the second column. Further fields are nested under Properties. Long keys, values, and URLs are cut off with `...`.

Expand Down Expand Up @@ -363,6 +363,8 @@ import rickwporter.prettytable.BuilderConfig;
| `setPropertyLabel` / `setValueLabel` | `Property` / `Value` |
| `setPropertiesLabel` / `setValuesLabel` | `Properties` / `Values` |
| `setUnknownLabel` | `Unknown` |
| `setNullValue` | `None` |
| `setTrueValue` / `setFalseValue` | `True` / `False` |
| `setItemsCaption` | `Found {} items` |
| `setEllipsis` | `...` |
| `setWildcardHeader` | `Properties` |
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/rickwporter/prettytable/BuilderConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ public final class BuilderConfig {
private String valueLabel = "Value";
private String valuesLabel = "Values";
private String unknownLabel = "Unknown";
private String nullValue = "None";
private String trueValue = "True";
private String falseValue = "False";
private String itemsCaption = "Found {} items";
private String ellipsis = "...";
private String wildcardHeader = "Properties";
Expand Down Expand Up @@ -80,6 +83,33 @@ public BuilderConfig setUnknownLabel(String label) {
return this;
}

public String getNullValue() {
return this.nullValue;
}

public BuilderConfig setNullValue(String text) {
this.nullValue = Objects.requireNonNull(text);
return this;
}

public String getTrueValue() {
return this.trueValue;
}

public BuilderConfig setTrueValue(String text) {
this.trueValue = Objects.requireNonNull(text);
return this;
}

public String getFalseValue() {
return this.falseValue;
}

public BuilderConfig setFalseValue(String text) {
this.falseValue = Objects.requireNonNull(text);
return this;
}

public String getItemsCaption() {
return this.itemsCaption;
}
Expand Down
20 changes: 10 additions & 10 deletions src/main/java/rickwporter/prettytable/TableBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private PrettyTable createListTable(List<?> items, boolean outer) {

Object other = this.singleOtherKey(first, nameKey);
if (other != MANY_KEYS) {
PrettyTable result = new PrettyTable(this.headerize(nameKey), this.headerize(stringify(other)));
PrettyTable result = new PrettyTable(this.headerize(nameKey), this.headerize(this.stringify(other)));
this.configure(result, outer, true, caption);
for (Object item : items) {
Map<?, ?> map = asMap(item);
Expand All @@ -148,7 +148,7 @@ private PrettyTable createObjectTable(Map<?, ?> obj, boolean outer) {
PrettyTable result = new PrettyTable(this.config.getPropertyLabel(), this.config.getValueLabel());
this.configure(result, outer, false, null);
for (Map.Entry<?, ?> entry : obj.entrySet()) {
String key = this.truncate(stringify(entry.getKey()), this.config.getKeyMaxLen());
String key = this.truncate(this.stringify(entry.getKey()), this.config.getKeyMaxLen());
result.addRow(key, this.cellValue(entry.getValue()));
}
return result;
Expand All @@ -164,10 +164,10 @@ private Object cellValue(Object obj) {
return this.createListTable(list, false);
}
if (!list.isEmpty()) {
return this.truncate(joinList(list), this.config.getValueMaxLen());
return this.truncate(this.joinList(list), this.config.getValueMaxLen());
}
}
String text = stringify(obj);
String text = this.stringify(obj);
int maxLen = this.isUrl(text) ? this.config.getUrlMaxLen() : this.config.getValueMaxLen();
return this.truncate(text, maxLen);
}
Expand Down Expand Up @@ -210,7 +210,7 @@ private Object singleOtherKey(Map<?, ?> item, String nameKey) {

private String nameCell(Map<?, ?> map, String nameKey) {
Object raw = map.containsKey(nameKey) ? map.get(nameKey) : this.config.getUnknownLabel();
return this.truncate(stringify(raw), this.config.getKeyMaxLen());
return this.truncate(this.stringify(raw), this.config.getKeyMaxLen());
}

private boolean isUrl(String text) {
Expand Down Expand Up @@ -240,13 +240,13 @@ private static Map<Object, Object> copyWithout(Map<?, ?> source, Set<?> skip) {
return copy;
}

private static String joinList(List<?> items) {
private String joinList(List<?> items) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < items.size(); i++) {
if (i > 0) {
result.append(", ");
}
result.append(stringify(items.get(i)));
result.append(this.stringify(items.get(i)));
}
return result.toString();
}
Expand All @@ -261,12 +261,12 @@ String headerize(String value) {
return Character.toUpperCase(value.charAt(0)) + value.substring(1);
}

static String stringify(Object value) {
String stringify(Object value) {
if (value == null) {
return "None";
return this.config.getNullValue();
}
if (value instanceof Boolean) {
return ((Boolean) value).booleanValue() ? "True" : "False";
return ((Boolean) value).booleanValue() ? this.config.getTrueValue() : this.config.getFalseValue();
}
return String.valueOf(value);
}
Expand Down
21 changes: 21 additions & 0 deletions src/test/java/rickwporter/prettytable/BuilderConfigTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public void testDefaults() {
Assertions.assertEquals("Value", config.getValueLabel());
Assertions.assertEquals("Values", config.getValuesLabel());
Assertions.assertEquals("Unknown", config.getUnknownLabel());
Assertions.assertEquals("None", config.getNullValue());
Assertions.assertEquals("True", config.getTrueValue());
Assertions.assertEquals("False", config.getFalseValue());
Assertions.assertEquals("Found {} items", config.getItemsCaption());
Assertions.assertEquals("...", config.getEllipsis());
Assertions.assertEquals("Properties", config.getWildcardHeader());
Expand Down Expand Up @@ -50,6 +53,15 @@ public void testSetters() {
Assertions.assertSame(config, config.setUnknownLabel("pluto"));
Assertions.assertEquals("pluto", config.getUnknownLabel());

Assertions.assertSame(config, config.setNullValue("nil"));
Assertions.assertEquals("nil", config.getNullValue());

Assertions.assertSame(config, config.setTrueValue("yes"));
Assertions.assertEquals("yes", config.getTrueValue());

Assertions.assertSame(config, config.setFalseValue("no"));
Assertions.assertEquals("no", config.getFalseValue());

Assertions.assertSame(config, config.setItemsCaption("huey, dewey, louie"));
Assertions.assertEquals("huey, dewey, louie", config.getItemsCaption());

Expand Down Expand Up @@ -112,6 +124,15 @@ public void testSettersRejectNull() {
Assertions.assertThrows(NullPointerException.class, () -> config.setUnknownLabel(null));
Assertions.assertEquals("Unknown", config.getUnknownLabel());

Assertions.assertThrows(NullPointerException.class, () -> config.setNullValue(null));
Assertions.assertEquals("None", config.getNullValue());

Assertions.assertThrows(NullPointerException.class, () -> config.setTrueValue(null));
Assertions.assertEquals("True", config.getTrueValue());

Assertions.assertThrows(NullPointerException.class, () -> config.setFalseValue(null));
Assertions.assertEquals("False", config.getFalseValue());

Assertions.assertThrows(NullPointerException.class, () -> config.setItemsCaption(null));
Assertions.assertEquals("Found {} items", config.getItemsCaption());

Expand Down
47 changes: 41 additions & 6 deletions src/test/java/rickwporter/prettytable/TableBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,22 @@ public void testHeaderize() {
Assertions.assertEquals("Hello", custom.headerize("hello"));
}

@Test
@Test
public void testStringify() {
Assertions.assertEquals("None", TableBuilder.stringify(null));
Assertions.assertEquals("True", TableBuilder.stringify(true));
Assertions.assertEquals("False", TableBuilder.stringify(false));
Assertions.assertEquals("My string", TableBuilder.stringify("My string"));
Assertions.assertEquals("3", TableBuilder.stringify(3));
TableBuilder obj = new TableBuilder();
Assertions.assertEquals("None", obj.stringify(null));
Assertions.assertEquals("True", obj.stringify(true));
Assertions.assertEquals("False", obj.stringify(false));
Assertions.assertEquals("My string", obj.stringify("My string"));
Assertions.assertEquals("3", obj.stringify(3));

TableBuilder custom = new TableBuilder(new BuilderConfig()
.setNullValue("nil")
.setTrueValue("yes")
.setFalseValue("no"));
Assertions.assertEquals("nil", custom.stringify(null));
Assertions.assertEquals("yes", custom.stringify(true));
Assertions.assertEquals("no", custom.stringify(false));
}

@Test
Expand Down Expand Up @@ -370,6 +379,32 @@ public void testNullConfigUsesDefaults() {
this.assertRendered("TableBuilder_simple_dict.text", this.simpleDict(), null);
}

@Test
public void testNullValue() {
BuilderConfig options = new BuilderConfig().setNullValue("nil");
String rendered = new TableBuilder(options).build(this.simpleDict()).toString();
Assertions.assertTrue(rendered.contains("nil"));
Assertions.assertFalse(rendered.contains("None"));

String listed = new TableBuilder(options).build(this.simpleList()).toString();
Assertions.assertTrue(listed.contains("nil"));
Assertions.assertFalse(listed.contains("None"));
}

@Test
public void testBooleanValues() {
BuilderConfig options = new BuilderConfig()
.setTrueValue("yes")
.setFalseValue("no");
String rendered = new TableBuilder(options).build(this.simpleDict()).toString();
Assertions.assertTrue(rendered.contains("no"));
Assertions.assertFalse(rendered.contains("False"));

String nested = new TableBuilder(options).build(this.innerList()).toString();
Assertions.assertTrue(nested.contains("yes"));
Assertions.assertFalse(nested.contains("True"));
}

@Test
public void testUnknownLabel() {
BuilderConfig options = new BuilderConfig()
Expand Down
Loading