You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by kr...@apache.org on 2019/09/27 20:18:44 UTC
[knox] 01/02: KNOX-2022 - Splitting up KnoxShellTable and do minor
cleanup
This is an automated email from the ASF dual-hosted git repository.
krisden pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
commit 8e7e9d93bceb09fb77fe0bb77fdf01ab5ef6dbf7
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Thu Sep 26 17:27:16 2019 +0200
KNOX-2022 - Splitting up KnoxShellTable and do minor cleanup
---
.../apache/knox/gateway/shell/KnoxShellTable.java | 658 ---------------------
.../java/org/apache/knox/gateway/shell/Shell.java | 1 +
.../shell/table/CSVKnoxShellTableBuilder.java | 72 +++
.../shell/table/JDBCKnoxShellTableBuilder.java | 117 ++++
.../shell/table/JSONKnoxShellTableBuilder.java | 44 ++
.../shell/table/JoinKnoxShellTableBuilder.java | 75 +++
.../knox/gateway/shell/table/KnoxShellTable.java | 169 ++++++
.../gateway/shell/table/KnoxShellTableBuilder.java | 44 ++
.../gateway/shell/table/KnoxShellTableCell.java | 61 ++
.../gateway/shell/table/KnoxShellTableFilter.java | 58 ++
.../shell/table/KnoxShellTableRenderer.java | 164 +++++
.../shell/{ => table}/KnoxShellTableTest.java | 22 +-
12 files changed, 816 insertions(+), 669 deletions(-)
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
deleted file mode 100644
index dfbbf09..0000000
--- a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxShellTable.java
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * 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.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.charset.StandardCharsets;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.knox.gateway.util.JsonUtils;
-
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-/**
-* 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>>();
- private String title;
-
- public KnoxShellTable title(String title) {
- this.title = title;
- return this;
- }
-
- 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;
- }
-
- public KnoxShellTableCell cell(int colIndex, int rowIndex) {
- return new KnoxShellTableCell(colIndex, rowIndex);
- }
-
- public List<String> values(int colIndex) {
- ArrayList<String> col = new ArrayList<String>();
- rows.forEach(row -> col.add(row.get(colIndex)));
- return col;
- }
-
- public List<String> values(String colName) {
- int colIndex = headers.indexOf(colName);
- ArrayList<String> col = new ArrayList<String>();
- rows.forEach(row -> col.add(row.get(colIndex)));
- return col;
- }
-
- public KnoxShellTable apply(KnoxShellTableCell cell) {
- if (!headers.isEmpty()) {
- headers.set(cell.colIndex, cell.header);
- }
- if (!rows.isEmpty()) {
- rows.get(cell.rowIndex).set(cell.colIndex, cell.value);
- }
- return this;
- }
-
- public class KnoxShellTableCell {
- private int colIndex;
- private int rowIndex;
- private String header;
- private String value;
-
- KnoxShellTableCell(int colIndex, int rowIndex) {
- this.colIndex = colIndex;
- this.rowIndex = rowIndex;
- if (!headers.isEmpty()) {
- this.header = headers.get(colIndex);
- }
- if (!rows.isEmpty()) {
- this.value = rows.get(rowIndex).get(colIndex);
- }
- }
-
- KnoxShellTableCell(String name, int rowIndex) {
- this.rowIndex = rowIndex;
- if (!headers.isEmpty()) {
- this.header = name;
- this.colIndex = headers.indexOf(name);
- }
- if (!rows.isEmpty()) {
- this.value = rows.get(rowIndex).get(colIndex);
- }
- }
-
- public KnoxShellTableCell value(String value) {
- this.value = value;
- return this;
- }
-
- public KnoxShellTableCell header(String name) {
- this.header = name;
- return this;
- }
-
- public String value() {
- return this.value;
- }
-
- public String header() {
- return this.header;
- }
- }
-
- public List<String> getHeaders() {
- if (headers.isEmpty()) {
- return null;
- }
- return headers;
- }
-
- public List<List<String>> getRows() {
- return rows;
- }
-
- public String getTitle() {
- return title;
- }
-
- @Override
- public String toString() {
- if (!headers.isEmpty() && !rows.isEmpty() && headers.size() != rows.get(0).size()) {
- throw new IllegalStateException("Number of columns and headers must be the same.");
- }
- StringBuilder sb = new StringBuilder();
- Map<Integer, Integer> widthMap = getWidthMap();
-
- if (title != null && !title.isEmpty()) {
- sb.append(this.title);
- newLine(sb, 1);
- }
- int colCount = 0;
- if (!rows.isEmpty()) {
- colCount = rows.get(0).size();
- }
- if (!headers.isEmpty()) {
- colCount = headers.size();
- 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;
- }
-
- public static KnoxShellTableBuilder builder() {
- return new KnoxShellTableBuilder();
- }
-
- public static class KnoxShellTableBuilder {
- protected String title;
-
- public KnoxShellTableBuilder title(String title) {
- this.title = title;
- return this;
- }
-
- public CSVKnoxShellTableBuilder csv() {
- return new CSVKnoxShellTableBuilder();
- }
-
- public JSONKnoxShellTableBuilder json() {
- return new JSONKnoxShellTableBuilder();
- }
-
- public JoinKnoxShellTableBuilder join() {
- return new JoinKnoxShellTableBuilder();
- }
-
- public JDBCKnoxShellTableBuilder jdbc() {
- return new JDBCKnoxShellTableBuilder();
- }
- }
-
- public static class JoinKnoxShellTableBuilder extends KnoxShellTableBuilder {
- private KnoxShellTable left;
- private KnoxShellTable right;
- private int leftIndex = -1;
- private int rightIndex = -1;
-
- public JoinKnoxShellTableBuilder() {
- }
-
- @Override
- public JoinKnoxShellTableBuilder title(String title) {
- this.title = title;
- return this;
- }
-
- public JoinKnoxShellTableBuilder left(KnoxShellTable left) {
- this.left = left;
- return this;
- }
-
- public JoinKnoxShellTableBuilder right(KnoxShellTable right) {
- this.right = right;
- return this;
- }
-
- public KnoxShellTable on(int leftIndex, int rightIndex) {
- KnoxShellTable joined = new KnoxShellTable();
- if (title != null) {
- joined.title(title);
- }
-
- this.leftIndex = leftIndex;
- this.rightIndex = rightIndex;
-
- joined.headers.addAll(new ArrayList<String>(left.headers));
- for (List<String> row : left.rows) {
- joined.rows.add(new ArrayList<String>(row));
- }
- List<String> col = right.values(rightIndex);
- ArrayList<String> row;
- String leftKey;
- int matchedIndex;
-
- joined.headers.addAll(new ArrayList<String>(right.headers));
- for (Iterator<List<String>> it = joined.rows.iterator(); it.hasNext();) {
- row = (ArrayList<String>) it.next();
- leftKey = row.get(leftIndex);
- if (leftKey != null) {
- matchedIndex = col.indexOf(leftKey);
- if (matchedIndex > -1) {
- row.addAll(right.rows.get(matchedIndex));
- }
- else {
- it.remove();
- }
- }
- }
- return joined;
- }
- }
-
- public static class JSONKnoxShellTableBuilder extends KnoxShellTableBuilder {
- boolean withHeaders;
-
- @Override
- public JSONKnoxShellTableBuilder title(String title) {
- this.title = title;
- return this;
- }
-
- public JSONKnoxShellTableBuilder withHeaders() {
- withHeaders = true;
- return this;
- }
-
- public KnoxShellTable string(String json) throws IOException {
- KnoxShellTable table = getKnoxShellTableFromJsonString(json);
- return table;
- }
-
- public KnoxShellTable path(String path) throws IOException {
- String json = FileUtils.readFileToString(new File(path), StandardCharsets.UTF_8);
- KnoxShellTable table = getKnoxShellTableFromJsonString(json);
- return table;
- }
-
- public KnoxShellTable getKnoxShellTableFromJsonString(String json) throws IOException {
- KnoxShellTable table = null;
- JsonFactory factory = new JsonFactory();
- ObjectMapper mapper = new ObjectMapper(factory);
- TypeReference<KnoxShellTable> typeRef
- = new TypeReference<KnoxShellTable>() {};
- table = mapper.readValue(json, typeRef);
- if (title != null) {
- table.title(title);
- }
- return table;
- }
- }
-
- public static class CSVKnoxShellTableBuilder extends KnoxShellTableBuilder {
- boolean withHeaders;
-
- @Override
- public CSVKnoxShellTableBuilder title(String title) {
- this.title = title;
- return this;
- }
-
- public CSVKnoxShellTableBuilder withHeaders() {
- withHeaders = true;
- return this;
- }
-
- public KnoxShellTable url(String url) throws IOException {
- int rowIndex = 0;
- URLConnection connection;
- BufferedReader csvReader = null;
- KnoxShellTable table = null;
- try {
- URL urlToCsv = new URL(url);
- connection = urlToCsv.openConnection();
- csvReader = new BufferedReader(new InputStreamReader(
- connection.getInputStream(), StandardCharsets.UTF_8));
- table = new KnoxShellTable();
- if (title != null) {
- table.title(title);
- }
- String row = null;
- while ((row = csvReader.readLine()) != null) {
- boolean addingHeaders = (withHeaders && rowIndex == 0);
- if (!addingHeaders) {
- table.row();
- }
- String[] data = row.split(",");
-
- for (String value : data) {
- if (addingHeaders) {
- table.header(value);
- }
- else {
- table.value(value);
- }
- }
- rowIndex++;
- }
- }
- finally {
- csvReader.close();
- }
- return table;
- }
- }
-
- public static class JDBCKnoxShellTableBuilder extends KnoxShellTableBuilder {
- private String connect;
- private String username;
- private String pwd;
- private String driver;
- private Connection conn;
- private boolean tableManagedConnection = true;
-
- @Override
- public JDBCKnoxShellTableBuilder title(String title) {
- this.title = title;
- return this;
- }
-
- public JDBCKnoxShellTableBuilder connect(String connect) {
- this.connect = connect;
- return this;
- }
-
- public JDBCKnoxShellTableBuilder username(String username) {
- this.username = username;
- return this;
- }
-
- public JDBCKnoxShellTableBuilder pwd(String pwd) {
- this.pwd = pwd;
- return this;
- }
-
- public JDBCKnoxShellTableBuilder driver(String driver) {
- this.driver = driver;
- return this;
- }
-
- public JDBCKnoxShellTableBuilder connection(Connection connection) {
- this.conn = connection;
- this.tableManagedConnection = false;
- return this;
- }
-
- public KnoxShellTable sql(String sql) throws IOException, SQLException {
- KnoxShellTable table = null;
- Statement statement = null;
- ResultSet result = null;
- if (conn == null) {
- conn = DriverManager.getConnection(connect);
- }
- try {
- if (conn != null) {
- statement = conn.createStatement();
- //table.builder().jdbc().connect("jdbc:derby:codejava/webdb1").username("lmccay").password("xxxx").sql("SELECT * FROM book");
- result = statement.executeQuery(sql);
- table = new KnoxShellTable();
- ResultSetMetaData metadata = result.getMetaData();
- table.title(metadata.getTableName(1));
- int colcount = metadata.getColumnCount();
- for(int i = 1; i < colcount + 1; i++) {
- table.header(metadata.getColumnName(i));
- }
- while (result.next()) {
- table.row();
- for(int i = 1; i < colcount + 1; i++) {
- table.value(result.getString(metadata.getColumnName(i)));
- }
- }
- }
- }
- finally {
- result.close();
- if (conn != null && tableManagedConnection) {
- conn.close();
- }
- if (statement != null) {
- statement.close();
- }
- if (result != null && !result.isClosed()) {
- result.close();
- }
- }
- return table;
- }
- }
-
- public String toJSON() {
- return JsonUtils.renderAsJsonString(this);
- }
-
- public String toCSV() {
- StringBuilder csv = new StringBuilder();
- String header;
- for(int i = 0; i < headers.size(); i++) {
- header = headers.get(i);
- csv.append(header);
- if (i < headers.size() - 1) {
- csv.append(',');
- }
- else {
- csv.append('\n');
- }
- }
- for(List<String> row : rows) {
- for(int ii = 0; ii < row.size(); ii++) {
- csv.append(row.get(ii));
- if (ii < row.size() - 1) {
- csv.append(',');
- }
- else {
- csv.append('\n');
- }
- }
- }
-
- return csv.toString();
- }
-
- public KnoxShellTable select(String cols) {
- KnoxShellTable table = new KnoxShellTable();
- List<ArrayList<String>> columns = new ArrayList<ArrayList<String>>();
- String[] colnames = cols.split(",");
- for (String colName : colnames) {
- table.header(colName);
- columns.add((ArrayList<String>) values(headers.indexOf(colName)));
- }
- for (int i = 0; i < rows.size(); i ++) {
- table.row();
- for (List<String> col : columns) {
- table.value(col.get(i));
- }
- }
- return table;
- }
-
- public KnoxShellTable sort(String colName) {
- KnoxShellTable table = new KnoxShellTable();
-
- String value;
- List<String> col = values(colName);
- List<RowIndex> index = new ArrayList<RowIndex>();
- for (int i = 0; i < col.size(); i++) {
- value = col.get(i);
- index.add(new RowIndex(value, i));
- }
- Collections.sort(index);
- table.headers = new ArrayList<String>(headers);
- for (RowIndex i : index) {
- table.rows.add(new ArrayList<String>(this.rows.get(i.index)));
- }
- return table;
- }
-
- public static class RowIndex implements Comparable<RowIndex> {
- String value;
- int index;
-
- public RowIndex(String value, int index) {
- this.value = value;
- this.index = index;
- }
-
- @Override
- public int compareTo(RowIndex other) {
- return (this.value.compareTo(other.value));
- }
- }
-
- public KnoxShellTableFilter filter() {
- return new KnoxShellTableFilter();
- }
-
- public class KnoxShellTableFilter {
- String name;
- int index;
-
- public KnoxShellTableFilter name(String name) {
- this.name = name;
- index = headers.indexOf(name);
- return this;
- }
-
- public KnoxShellTableFilter index(int index) {
- this.index = index;
- return this;
- }
-
- public KnoxShellTable regex(String regex) {
- KnoxShellTable table = new KnoxShellTable();
- table.headers.addAll(headers);
- for (List<String> row : rows) {
- if (Pattern.matches(regex, row.get(index))) {
- table.row();
- row.forEach(value -> {
- table.value(value);
- });
- }
- }
- return table;
- }
- }
-}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/Shell.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/Shell.java
index f0aaf41..a674979 100644
--- a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/Shell.java
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/Shell.java
@@ -22,6 +22,7 @@ import org.apache.knox.gateway.shell.hbase.HBase;
import org.apache.knox.gateway.shell.hdfs.Hdfs;
import org.apache.knox.gateway.shell.job.Job;
import org.apache.knox.gateway.shell.manager.Manager;
+import org.apache.knox.gateway.shell.table.KnoxShellTable;
import org.apache.knox.gateway.shell.workflow.Workflow;
import org.apache.knox.gateway.shell.yarn.Yarn;
import org.apache.log4j.PropertyConfigurator;
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/CSVKnoxShellTableBuilder.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/CSVKnoxShellTableBuilder.java
new file mode 100644
index 0000000..db5a9e7
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/CSVKnoxShellTableBuilder.java
@@ -0,0 +1,72 @@
+/*
+ * 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.table;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+
+public class CSVKnoxShellTableBuilder extends KnoxShellTableBuilder {
+
+ private boolean withHeaders;
+
+ public CSVKnoxShellTableBuilder withHeaders() {
+ withHeaders = true;
+ return this;
+ }
+
+ public KnoxShellTable url(String url) throws IOException {
+ int rowIndex = 0;
+ URLConnection connection;
+ BufferedReader csvReader = null;
+ KnoxShellTable table = null;
+ try {
+ URL urlToCsv = new URL(url);
+ connection = urlToCsv.openConnection();
+ csvReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
+ table = new KnoxShellTable();
+ if (title != null) {
+ table.title(title);
+ }
+ String row = null;
+ while ((row = csvReader.readLine()) != null) {
+ boolean addingHeaders = (withHeaders && rowIndex == 0);
+ if (!addingHeaders) {
+ table.row();
+ }
+ String[] data = row.split(",");
+
+ for (String value : data) {
+ if (addingHeaders) {
+ table.header(value);
+ } else {
+ table.value(value);
+ }
+ }
+ rowIndex++;
+ }
+ } finally {
+ csvReader.close();
+ }
+ return table;
+ }
+
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JDBCKnoxShellTableBuilder.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JDBCKnoxShellTableBuilder.java
new file mode 100644
index 0000000..d8abaf1
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JDBCKnoxShellTableBuilder.java
@@ -0,0 +1,117 @@
+/*
+ * 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.table;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+public class JDBCKnoxShellTableBuilder extends KnoxShellTableBuilder {
+
+ private String connectionUrl;
+ private String driver;
+ private Connection conn;
+ private boolean tableManagedConnection = true;
+
+ @Override
+ public JDBCKnoxShellTableBuilder title(String title) {
+ this.title = title;
+ return this;
+ }
+
+ public JDBCKnoxShellTableBuilder connectTo(String connectionUrl) {
+ this.connectionUrl = connectionUrl;
+ return this;
+ }
+
+ public JDBCKnoxShellTableBuilder driver(String driver) throws Exception {
+ this.driver = driver;
+ loadDriver();
+ return this;
+ }
+
+ private void loadDriver() throws Exception {
+ try {
+ Class.forName(driver).newInstance();
+ } catch (ClassNotFoundException e) {
+ System.out.println(String.format("Unable to load the JDBC driver %s. Check your CLASSPATH.", driver));
+ throw e;
+ } catch (InstantiationException e) {
+ System.out.println(String.format("Unable to instantiate the JDBC driver %s", driver));
+ throw e;
+ } catch (IllegalAccessException e) {
+ System.out.println(String.format("Not allowed to access the JDBC driver %s", driver));
+ throw e;
+ }
+ }
+
+ public JDBCKnoxShellTableBuilder connection(Connection connection) {
+ this.conn = connection;
+ this.tableManagedConnection = false;
+ return this;
+ }
+
+ public KnoxShellTable sql(String sql) throws IOException, SQLException {
+ KnoxShellTable table = null;
+ conn = conn == null ? DriverManager.getConnection(connectionUrl) : conn;
+ if (conn != null) {
+ try (Statement statement = conn.createStatement(); ResultSet result = statement.executeQuery(sql);) {
+ table = new KnoxShellTable();
+ final ResultSetMetaData metadata = result.getMetaData();
+ table.title(metadata.getTableName(1));
+ int colcount = metadata.getColumnCount();
+ for (int i = 1; i < colcount + 1; i++) {
+ table.header(metadata.getColumnName(i));
+ }
+ while (result.next()) {
+ table.row();
+ for (int i = 1; i < colcount + 1; i++) {
+ table.value(result.getString(metadata.getColumnName(i)));
+ }
+ }
+ } finally {
+ if (conn != null && tableManagedConnection) {
+ conn.close();
+ }
+ }
+ }
+ return table;
+ }
+
+ public KnoxShellTable build(ResultSet resultSet) throws SQLException {
+ KnoxShellTable table = new KnoxShellTable();
+ ResultSetMetaData metadata = resultSet.getMetaData();
+ table.title(metadata.getTableName(1));
+ int colcount = metadata.getColumnCount();
+ for (int i = 1; i < colcount + 1; i++) {
+ table.header(metadata.getColumnName(i));
+ }
+ while (resultSet.next()) {
+ table.row();
+ for (int i = 1; i < colcount + 1; i++) {
+ table.value(resultSet.getString(metadata.getColumnName(i)));
+ }
+ }
+ return table;
+ }
+
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JSONKnoxShellTableBuilder.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JSONKnoxShellTableBuilder.java
new file mode 100644
index 0000000..1be5512
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JSONKnoxShellTableBuilder.java
@@ -0,0 +1,44 @@
+/*
+ * 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.table;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.commons.io.FileUtils;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class JSONKnoxShellTableBuilder extends KnoxShellTableBuilder {
+
+ public KnoxShellTable fromJson(String json) throws IOException {
+ final KnoxShellTable table = new ObjectMapper(new JsonFactory()).readValue(json, new TypeReference<KnoxShellTable>() {
+ });
+ if (title != null) {
+ table.title(title);
+ }
+ return table;
+ }
+
+ public KnoxShellTable path(String path) throws IOException {
+ return fromJson(FileUtils.readFileToString(new File(path), StandardCharsets.UTF_8));
+ }
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JoinKnoxShellTableBuilder.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JoinKnoxShellTableBuilder.java
new file mode 100644
index 0000000..bc504dd
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JoinKnoxShellTableBuilder.java
@@ -0,0 +1,75 @@
+/*
+ * 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.table;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class JoinKnoxShellTableBuilder extends KnoxShellTableBuilder {
+
+ private KnoxShellTable left;
+ private KnoxShellTable right;
+
+ @Override
+ public JoinKnoxShellTableBuilder title(String title) {
+ this.title = title;
+ return this;
+ }
+
+ public JoinKnoxShellTableBuilder left(KnoxShellTable left) {
+ this.left = left;
+ return this;
+ }
+
+ public JoinKnoxShellTableBuilder right(KnoxShellTable right) {
+ this.right = right;
+ return this;
+ }
+
+ public KnoxShellTable on(int leftIndex, int rightIndex) {
+ final KnoxShellTable joinedTable = new KnoxShellTable();
+ if (title != null) {
+ joinedTable.title(title);
+ }
+
+ joinedTable.headers.addAll(new ArrayList<String>(left.headers));
+ for (List<String> row : left.rows) {
+ joinedTable.rows.add(new ArrayList<String>(row));
+ }
+ ArrayList<String> row;
+ String leftKey;
+ int matchedIndex;
+
+ joinedTable.headers.addAll(new ArrayList<String>(right.headers));
+ for (Iterator<List<String>> it = joinedTable.rows.iterator(); it.hasNext();) {
+ row = (ArrayList<String>) it.next();
+ leftKey = row.get(leftIndex);
+ if (leftKey != null) {
+ matchedIndex = right.values(rightIndex).indexOf(leftKey);
+ if (matchedIndex > -1) {
+ row.addAll(right.rows.get(matchedIndex));
+ } else {
+ it.remove();
+ }
+ }
+ }
+ return joinedTable;
+ }
+
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTable.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTable.java
new file mode 100644
index 0000000..cf40a09
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTable.java
@@ -0,0 +1,169 @@
+/*
+ * 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.table;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.knox.gateway.util.JsonUtils;
+
+/**
+ * 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 {
+
+ List<String> headers = new ArrayList<String>();
+ List<List<String>> rows = new ArrayList<List<String>>();
+ String title;
+
+ public KnoxShellTable title(String title) {
+ this.title = title;
+ return this;
+ }
+
+ public KnoxShellTable header(String header) {
+ headers.add(header);
+ return this;
+ }
+
+ public KnoxShellTable row() {
+ rows.add(new ArrayList<String>());
+ return this;
+ }
+
+ public KnoxShellTable value(String value) {
+ final int index = rows.isEmpty() ? 0 : rows.size() - 1;
+ final List<String> row = rows.get(index);
+ row.add(value);
+ return this;
+ }
+
+ public KnoxShellTableCell cell(int colIndex, int rowIndex) {
+ return new KnoxShellTableCell(headers, rows, colIndex, rowIndex);
+ }
+
+ public List<String> values(int colIndex) {
+ ArrayList<String> col = new ArrayList<String>();
+ rows.forEach(row -> col.add(row.get(colIndex)));
+ return col;
+ }
+
+ public List<String> values(String colName) {
+ int colIndex = headers.indexOf(colName);
+ ArrayList<String> col = new ArrayList<String>();
+ rows.forEach(row -> col.add(row.get(colIndex)));
+ return col;
+ }
+
+ public KnoxShellTable apply(KnoxShellTableCell cell) {
+ if (!headers.isEmpty()) {
+ headers.set(cell.colIndex, cell.header);
+ }
+ if (!rows.isEmpty()) {
+ rows.get(cell.rowIndex).set(cell.colIndex, cell.value);
+ }
+ return this;
+ }
+
+ public List<String> getHeaders() {
+ return headers == null || headers.isEmpty() ? null : headers;
+ }
+
+ public List<List<String>> getRows() {
+ return rows;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public static KnoxShellTableBuilder builder() {
+ return new KnoxShellTableBuilder();
+ }
+
+ public KnoxShellTableFilter filter() {
+ return new KnoxShellTableFilter().table(this);
+ }
+
+ public KnoxShellTable select(String cols) {
+ KnoxShellTable table = new KnoxShellTable();
+ List<List<String>> columns = new ArrayList<List<String>>();
+ String[] colnames = cols.split(",");
+ for (String colName : colnames) {
+ table.header(colName);
+ columns.add((ArrayList<String>) values(headers.indexOf(colName)));
+ }
+ for (int i = 0; i < rows.size(); i++) {
+ table.row();
+ for (List<String> col : columns) {
+ table.value(col.get(i));
+ }
+ }
+ return table;
+ }
+
+ public KnoxShellTable sort(String colName) {
+ KnoxShellTable table = new KnoxShellTable();
+
+ String value;
+ List<String> col = values(colName);
+ List<RowIndex> index = new ArrayList<RowIndex>();
+ for (int i = 0; i < col.size(); i++) {
+ value = col.get(i);
+ index.add(new RowIndex(value, i));
+ }
+ Collections.sort(index);
+ table.headers = new ArrayList<String>(headers);
+ for (RowIndex i : index) {
+ table.rows.add(new ArrayList<String>(this.rows.get(i.index)));
+ }
+ return table;
+ }
+
+ private static class RowIndex implements Comparable<RowIndex> {
+ String value;
+ int index;
+
+ public RowIndex(String value, int index) {
+ this.value = value;
+ this.index = index;
+ }
+
+ @Override
+ public int compareTo(RowIndex other) {
+ return (this.value.compareTo(other.value));
+ }
+ }
+
+ @Override
+ public String toString() {
+ return new KnoxShellTableRenderer(this).toString();
+ }
+
+ public String toJSON() {
+ return JsonUtils.renderAsJsonString(this);
+ }
+
+ public String toCSV() {
+ return new KnoxShellTableRenderer(this).toCSV();
+ }
+
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableBuilder.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableBuilder.java
new file mode 100644
index 0000000..5dcc5af
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableBuilder.java
@@ -0,0 +1,44 @@
+/*
+ * 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.table;
+
+
+public class KnoxShellTableBuilder {
+ protected String title;
+
+ public KnoxShellTableBuilder title(String title) {
+ this.title = title;
+ return this;
+ }
+
+ public CSVKnoxShellTableBuilder csv() {
+ return new CSVKnoxShellTableBuilder();
+ }
+
+ public JSONKnoxShellTableBuilder json() {
+ return new JSONKnoxShellTableBuilder();
+ }
+
+ public JoinKnoxShellTableBuilder join() {
+ return new JoinKnoxShellTableBuilder();
+ }
+
+ public JDBCKnoxShellTableBuilder jdbc() {
+ return new JDBCKnoxShellTableBuilder();
+ }
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableCell.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableCell.java
new file mode 100644
index 0000000..d2e885d
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableCell.java
@@ -0,0 +1,61 @@
+/*
+ * 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.table;
+
+import java.util.List;
+
+class KnoxShellTableCell {
+ int rowIndex;
+ int colIndex;
+ String header;
+ String value;
+
+ KnoxShellTableCell(List<String> headers, List<List<String>> rows, int colIndex, int rowIndex) {
+ this.rowIndex = rowIndex;
+ this.colIndex = colIndex;
+ if (!headers.isEmpty()) {
+ this.header = headers.get(colIndex);
+ }
+ if (!rows.isEmpty()) {
+ this.value = rows.get(rowIndex).get(colIndex);
+ }
+ }
+
+ KnoxShellTableCell(List<String> headers, List<List<String>> rows, String name, int rowIndex) {
+ this.rowIndex = rowIndex;
+ if (!headers.isEmpty()) {
+ this.header = name;
+ this.colIndex = headers.indexOf(name);
+ }
+ if (!rows.isEmpty()) {
+ this.value = rows.get(rowIndex).get(colIndex);
+ }
+ }
+
+ KnoxShellTableCell value(String value) {
+ this.value = value;
+ return this;
+ }
+
+ KnoxShellTableCell header(String name) {
+ this.header = name;
+ return this;
+ }
+
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableFilter.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableFilter.java
new file mode 100644
index 0000000..3a462cc
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableFilter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.table;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+public class KnoxShellTableFilter {
+
+ private KnoxShellTable tableToFilter;
+ private int index;
+
+ public KnoxShellTableFilter table(KnoxShellTable table) {
+ this.tableToFilter = table;
+ return this;
+ }
+
+ public KnoxShellTableFilter name(String name) {
+ index = tableToFilter == null ? -1 : tableToFilter.headers.indexOf(name);
+ return this;
+ }
+
+ public KnoxShellTableFilter index(int index) {
+ this.index = index;
+ return this;
+ }
+
+ public KnoxShellTable regex(String regex) {
+ final Pattern pattern = Pattern.compile(regex);
+ final KnoxShellTable filteredTable = new KnoxShellTable();
+ filteredTable.headers.addAll(tableToFilter.headers);
+ for (List<String> row : tableToFilter.rows) {
+ if (pattern.matcher(row.get(index)).matches()) {
+ filteredTable.row();
+ row.forEach(value -> {
+ filteredTable.value(value);
+ });
+ }
+ }
+ return filteredTable;
+ }
+
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableRenderer.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableRenderer.java
new file mode 100644
index 0000000..dd7295e
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableRenderer.java
@@ -0,0 +1,164 @@
+/*
+ * 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.table;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+
+class KnoxShellTableRenderer {
+
+ 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 final KnoxShellTable tableToRender;
+
+ KnoxShellTableRenderer(KnoxShellTable tableToRender) {
+ this.tableToRender = tableToRender;
+ }
+
+ String toCSV() {
+ final StringBuilder csv = new StringBuilder();
+ String header;
+ for (int i = 0; i < tableToRender.headers.size(); i++) {
+ header = tableToRender.headers.get(i);
+ csv.append(header);
+ if (i < tableToRender.headers.size() - 1) {
+ csv.append(',');
+ } else {
+ csv.append('\n');
+ }
+ }
+ for (List<String> row : tableToRender.rows) {
+ for (int ii = 0; ii < row.size(); ii++) {
+ csv.append(row.get(ii));
+ if (ii < row.size() - 1) {
+ csv.append(',');
+ } else {
+ csv.append('\n');
+ }
+ }
+ }
+
+ return csv.toString();
+ }
+
+ @Override
+ public String toString() {
+ if (!tableToRender.headers.isEmpty() && !tableToRender.rows.isEmpty() && tableToRender.headers.size() != tableToRender.rows.get(0).size()) {
+ throw new IllegalStateException("Number of columns and headers must be the same.");
+ }
+ StringBuilder sb = new StringBuilder();
+ Map<Integer, Integer> widthMap = getWidthMap();
+
+ if (StringUtils.isNoneBlank(tableToRender.title)) {
+ sb.append(tableToRender.title);
+ newLine(sb, 1);
+ }
+ int colCount = 0;
+ if (!tableToRender.rows.isEmpty()) {
+ colCount = tableToRender.rows.get(0).size();
+ }
+ if (!tableToRender.headers.isEmpty()) {
+ colCount = tableToRender.headers.size();
+ 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, tableToRender.headers.get(i))).append(CELL_WALL_CHAR);
+ }
+ newLine(sb, 1);
+ }
+ createBorder(sb, colCount, widthMap);
+
+ for (List<String> row : tableToRender.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 < tableToRender.headers.size(); i++) {
+ headerValue = ensureEvenLength(tableToRender.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 : tableToRender.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/table/KnoxShellTableTest.java
similarity index 95%
rename from gateway-shell/src/test/java/org/apache/knox/gateway/shell/KnoxShellTableTest.java
rename to gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java
index a2c7e0f..766a0ad 100644
--- a/gateway-shell/src/test/java/org/apache/knox/gateway/shell/KnoxShellTableTest.java
+++ b/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.knox.gateway.shell;
+package org.apache.knox.gateway.shell.table;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
@@ -35,7 +35,8 @@ import java.sql.ResultSetMetaData;
import java.sql.Statement;
import org.apache.commons.io.FileUtils;
-import org.apache.knox.gateway.shell.KnoxShellTable.KnoxShellTableCell;
+import org.apache.knox.gateway.shell.table.KnoxShellTable;
+import org.apache.knox.gateway.shell.table.KnoxShellTableCell;
import org.easymock.IAnswer;
import org.junit.Test;
@@ -179,7 +180,7 @@ public class KnoxShellTableTest {
String json = table.toJSON();
- KnoxShellTable table2 = KnoxShellTable.builder().json().string(json);
+ KnoxShellTable table2 = KnoxShellTable.builder().json().fromJson(json);
assertEquals(table.toString(), table2.toString());
}
@@ -207,13 +208,13 @@ public class KnoxShellTableTest {
table.row().value("789").value("012").value("844444444");
KnoxShellTableCell cell = table.cell(1, 1);
- assertEquals(cell.header(), "Column B");
- assertEquals(cell.value(), "012");
+ assertEquals(cell.header, "Column B");
+ assertEquals(cell.value, "012");
cell.header("Column Beeee");
cell.value("234");
table.apply(cell);
- assertEquals(table.cell(1, 1).value(), "234");
- assertEquals(table.cell(1, 1).header(), "Column Beeee");
+ assertEquals(table.cell(1, 1).value, "234");
+ assertEquals(table.cell(1, 1).header, "Column Beeee");
}
@Test
@@ -251,15 +252,15 @@ public class KnoxShellTableTest {
assertEquals(joined.getRows().size(), 1);
assertEquals(joined.getTitle(), "Joined Table");
- assertEquals(joined.cell(0, 0).value(), "123");
+ assertEquals(joined.cell(0, 0).value, "123");
String json = joined.toJSON();
- KnoxShellTable zombie = KnoxShellTable.builder().json().string(json);
+ KnoxShellTable zombie = KnoxShellTable.builder().json().fromJson(json);
zombie.title("Zombie Table");
assertEquals(zombie.getRows().size(), 1);
assertEquals(zombie.getTitle(), "Zombie Table");
- assertEquals(zombie.cell(0, 0).value(), "123");
+ assertEquals(zombie.cell(0, 0).value, "123");
KnoxShellTable joined2 = KnoxShellTable.builder().join().title("Joined Table 2").left(table).right(table2).on(1, 3);
assertEquals(1, joined2.getRows().size());
}
@@ -288,7 +289,6 @@ public class KnoxShellTableTest {
return false;
}
}).times(2);
- expect(resultSet.isClosed()).andReturn(true);
expect(resultSet.getString("BOOK_ID")).andReturn("1").times(1);
expect(resultSet.getString("TITLE")).andReturn("Apache Knox: The Definitive Guide").times(1);
expect(metadata.getTableName(1)).andReturn("BOOK");