This is an automated email from the ASF dual-hosted git repository. lmccay pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push: new 5d3acde KNOX-2002 - Add a KnoxShellTable to Represent and Render Output in Tabular Format 5d3acde is described below commit 5d3acde92d6d82da15f32bf1289999b63f6d82dd Author: lmccay <lmc...@apache.org> AuthorDate: Thu Aug 29 22:42:43 2019 -0400 KNOX-2002 - Add a KnoxShellTable to Represent and Render Output in Tabular Format --- .../apache/knox/gateway/shell/KnoxShellTable.java | 151 +++++++++++++++++++++ .../knox/gateway/shell/KnoxShellTableTest.java | 108 +++++++++++++++ 2 files changed, 259 insertions(+) diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxShellTable.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxShellTable.java new file mode 100644 index 0000000..9905c42 --- /dev/null +++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxShellTable.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.knox.gateway.shell; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** +* Simple table representation and text based rendering of a table via toString(). +* Headers are optional but when used must have the same count as columns +* within the rows. +*/ +public class KnoxShellTable { + private static int CELL_PAD_SIZE = 2; + private static char CELL_CORNER_CHAR = '+'; + private static char CELL_WALL_CHAR = '|'; + private static char CELL_DASH_CHAR = '-'; + + private List<String> headers = new ArrayList<String>(); + private List<List<String>> rows = new ArrayList<List<String>>(); + + public KnoxShellTable header(String header) { + headers.add(header); + return this; + } + + public KnoxShellTable row() { + List<String> row = new ArrayList<String>(); + rows.add(row); + return this; + } + + public KnoxShellTable value(String value) { + int index = rows.size() - 1; + if (index == -1) { + index = 0; + } + List<String> row = rows.get(index); + row.add(value); + return this; + } + + @Override + public String toString() { + if (!headers.isEmpty() && headers.size() != rows.get(0).size()) { + throw new IllegalStateException("Number of columns within rows and headers must be the same."); + } + StringBuilder sb = new StringBuilder(); + Map<Integer, Integer> widthMap = getWidthMap(); + + int colCount = rows.get(0).size(); + if (!headers.isEmpty()) { + createBorder(sb, colCount, widthMap); + newLine(sb, 1); + + sb.append(CELL_WALL_CHAR); + for (int i = 0; i < colCount; i++) { + sb.append(centerString(widthMap.get(i) + 4, headers.get(i))).append(CELL_WALL_CHAR); + } + newLine(sb, 1); + } + createBorder(sb, colCount, widthMap); + + for (List<String> row : rows) { + newLine(sb, 1); + sb.append(CELL_WALL_CHAR); + for (int i = 0; i < row.size(); i++) { + sb.append(centerString(widthMap.get(i) + 4, row.get(i))).append(CELL_WALL_CHAR); + } + } + + newLine(sb, 1); + createBorder(sb, colCount, widthMap); + newLine(sb, 1); + + return sb.toString(); + } + + private void newLine(StringBuilder sb, int count) { + for (int i = 0; i < count; i++) { + sb.append('\n'); + } + } + + private String centerString(int width, String s) { + s = ensureEvenLength(s); + return String.format(Locale.ROOT, "%-" + width + "s", String.format(Locale.ROOT, "%" + (s.length() + (width - s.length()) / 2) + "s", s)); + } + + private String ensureEvenLength(String s) { + if (s.length() % 2 != 0) { + s = s + " "; + } + return s; + } + + private void createBorder(StringBuilder sb, int headerCount, Map<Integer, Integer> widthMap) { + for (int i = 0; i < headerCount; i++) { + if (i == 0) { + sb.append(CELL_CORNER_CHAR); + } + + for (int j = 0; j < widthMap.get(i) + CELL_PAD_SIZE * 2; j++) { + sb.append(CELL_DASH_CHAR); + } + sb.append(CELL_CORNER_CHAR); + } + } + + private Map<Integer, Integer> getWidthMap() { + Map<Integer, Integer> map = new HashMap<>(); + String cellValue = null; + String headerValue = null; + + // set max's to header sizes for each col + for (int i = 0; i < headers.size(); i++) { + headerValue = ensureEvenLength(headers.get(i)); + map.put(i, headerValue.length()); + } + // if there are any cell values longer than the header length set max to longest + // cell value length + for (List<String> row : rows) { + for (int i = 0; i < row.size(); i++) { + cellValue = ensureEvenLength(row.get(i)); + if (map.get(i) == null || cellValue.length() > map.get(i)) { + map.put(i, cellValue.length()); + } + } + } + + return map; + } +} diff --git a/gateway-shell/src/test/java/org/apache/knox/gateway/shell/KnoxShellTableTest.java b/gateway-shell/src/test/java/org/apache/knox/gateway/shell/KnoxShellTableTest.java new file mode 100644 index 0000000..62dd8c9 --- /dev/null +++ b/gateway-shell/src/test/java/org/apache/knox/gateway/shell/KnoxShellTableTest.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.knox.gateway.shell; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import org.junit.Test; + +public class KnoxShellTableTest { + + @Test + public void testSimpleTableRendering() { + String expectedResult = "+------------+------------+------------+\n" + + "| Column A | Column B | Column C |\n" + "+------------+------------+------------+\n" + + "| 123 | 456 | 3 |\n" + "+------------+------------+------------+\n"; + + KnoxShellTable table = new KnoxShellTable(); + + table.header("Column A").header("Column B").header("Column C"); + + table.row().value("123").value("456").value("3"); + + assertEquals(expectedResult, table.toString()); + } + + @Test + public void testValueLongerThanHeader() { + String expectedResult = "+------------+------------+--------------+\n" + + "| Column A | Column B | Column C |\n" + "+------------+------------+--------------+\n" + + "| 123 | 456 | 344444444 |\n" + "+------------+------------+--------------+\n"; + + KnoxShellTable table = new KnoxShellTable(); + + table.header("Column A").header("Column B").header("Column C"); + + table.row().value("123").value("456").value("344444444"); + + assertEquals(expectedResult, table.toString()); + + } + + @Test + public void testMultipleRowsTableRendering() { + String expectedResult = "+------------+------------+--------------+\n" + + "| Column A | Column B | Column C |\n" + "+------------+------------+--------------+\n" + + "| 123 | 456 | 344444444 |\n" + + "| 789 | 012 | 844444444 |\n" + "+------------+------------+--------------+\n"; + + KnoxShellTable table = new KnoxShellTable(); + + table.header("Column A").header("Column B").header("Column C"); + + table.row().value("123").value("456").value("344444444"); + table.row().value("789").value("012").value("844444444"); + + assertEquals(expectedResult, table.toString()); + + } + + @Test + public void testMultipleRowsTableNoHeadersRendering() { + String expectedResult = "+--------+--------+--------------+\n" + + "| 123 | 456 | 344444444 |\n" + + "| 789 | 012 | 844444444 |\n" + "+--------+--------+--------------+\n"; + + KnoxShellTable table = new KnoxShellTable(); + + table.row().value("123").value("456").value("344444444"); + table.row().value("789").value("012").value("844444444"); + + assertEquals(expectedResult, table.toString()); + + } + + @Test + public void testMultipleRowsTableMismatchedColAndHeadersCountError() { + KnoxShellTable table = new KnoxShellTable(); + + table.header("Column A").header("Column B"); + + table.row().value("123").value("456").value("344444444"); + table.row().value("789").value("012").value("844444444"); + + try { + table.toString(); + fail("IllegalStateException expected."); + } + catch (IllegalStateException ise) { + // expected + } + } +}