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:45 UTC

[knox] 02/02: KNOX-2022 - KnoxShellTable contains Comparables instead of Strings

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 5c2c7a727d8e88e47ce1d14cb803c9a9f4473c29
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Fri Sep 27 18:25:37 2019 +0200

    KNOX-2022 - KnoxShellTable contains Comparables instead of Strings
    
    Closes #157
    
    Signed-off-by: Kevin Risden <kr...@apache.org>
---
 .../shell/table/JDBCKnoxShellTableBuilder.java     |  9 +--
 .../shell/table/JSONKnoxShellTableBuilder.java     |  8 ++-
 .../shell/table/JoinKnoxShellTableBuilder.java     | 22 +++---
 .../knox/gateway/shell/table/KnoxShellTable.java   | 41 ++++++------
 .../gateway/shell/table/KnoxShellTableCell.java    | 23 +++++--
 .../gateway/shell/table/KnoxShellTableFilter.java  | 31 ++++++++-
 .../shell/table/KnoxShellTableFilterException.java | 26 ++++++++
 .../shell/table/KnoxShellTableRenderer.java        | 10 +--
 .../shell/table/KnoxShellTableRowDeserializer.java | 76 +++++++++++++++++++++
 .../shell/table/KnoxShellTableFilterTest.java      | 78 ++++++++++++++++++++++
 .../gateway/shell/table/KnoxShellTableTest.java    |  7 +-
 11 files changed, 280 insertions(+), 51 deletions(-)

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
index d8abaf1..d958c5d 100644
--- 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
@@ -24,6 +24,7 @@ import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.Locale;
 
 public class JDBCKnoxShellTableBuilder extends KnoxShellTableBuilder {
 
@@ -53,13 +54,13 @@ public class JDBCKnoxShellTableBuilder extends KnoxShellTableBuilder {
     try {
       Class.forName(driver).newInstance();
     } catch (ClassNotFoundException e) {
-      System.out.println(String.format("Unable to load the JDBC driver %s. Check your CLASSPATH.", driver));
+      System.out.println(String.format(Locale.US, "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));
+      System.out.println(String.format(Locale.US, "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));
+      System.out.println(String.format(Locale.US, "Not allowed to access the JDBC driver %s", driver));
       throw e;
     }
   }
@@ -85,7 +86,7 @@ public class JDBCKnoxShellTableBuilder extends KnoxShellTableBuilder {
         while (result.next()) {
           table.row();
           for (int i = 1; i < colcount + 1; i++) {
-            table.value(result.getString(metadata.getColumnName(i)));
+            table.value(result.getObject(metadata.getColumnName(i), Comparable.class));
           }
         }
       } finally {
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
index 1be5512..b2a67cf 100644
--- 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
@@ -26,11 +26,17 @@ 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;
+import com.fasterxml.jackson.databind.module.SimpleModule;
 
 public class JSONKnoxShellTableBuilder extends KnoxShellTableBuilder {
 
   public KnoxShellTable fromJson(String json) throws IOException {
-    final KnoxShellTable table = new ObjectMapper(new JsonFactory()).readValue(json, new TypeReference<KnoxShellTable>() {
+    final ObjectMapper mapper = new ObjectMapper(new JsonFactory());
+    final SimpleModule module = new SimpleModule();
+    module.addDeserializer(KnoxShellTable.class, new KnoxShellTableRowDeserializer());
+    mapper.registerModule(module);
+
+    final KnoxShellTable table = mapper.readValue(json, new TypeReference<KnoxShellTable>() {
     });
     if (title != null) {
       table.title(title);
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
index bc504dd..fc74a1d 100644
--- 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
@@ -21,7 +21,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
-public class JoinKnoxShellTableBuilder extends KnoxShellTableBuilder {
+class JoinKnoxShellTableBuilder extends KnoxShellTableBuilder {
 
   private KnoxShellTable left;
   private KnoxShellTable right;
@@ -42,23 +42,29 @@ public class JoinKnoxShellTableBuilder extends KnoxShellTableBuilder {
     return this;
   }
 
-  public KnoxShellTable on(int leftIndex, int rightIndex) {
+  KnoxShellTable on(String columnName) {
+    final int leftIndex = left.headers.indexOf(columnName);
+    final int rightIndex = right.headers.indexOf(columnName);
+    return on(leftIndex, rightIndex);
+  }
+
+  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));
+    for (List<Comparable<? extends Object>> row : left.rows) {
+      joinedTable.rows.add(new ArrayList<Comparable<? extends Object>>(row));
     }
-    ArrayList<String> row;
-    String leftKey;
+    List<Comparable<? extends Object>> row;
+    Comparable<? extends Object> 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();
+    for (Iterator<List<Comparable<? extends Object>>> it = joinedTable.rows.iterator(); it.hasNext();) {
+      row = (List<Comparable<? extends Object>>) it.next();
       leftKey = row.get(leftIndex);
       if (leftKey != null) {
         matchedIndex = right.values(rightIndex).indexOf(leftKey);
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
index cf40a09..1fea1f9 100644
--- 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
@@ -23,6 +23,7 @@ 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
@@ -31,7 +32,7 @@ import org.apache.knox.gateway.util.JsonUtils;
 public class KnoxShellTable {
 
   List<String> headers = new ArrayList<String>();
-  List<List<String>> rows = new ArrayList<List<String>>();
+  List<List<Comparable<? extends Object>>> rows = new ArrayList<List<Comparable<? extends Object>>>();
   String title;
 
   public KnoxShellTable title(String title) {
@@ -45,35 +46,35 @@ public class KnoxShellTable {
   }
 
   public KnoxShellTable row() {
-    rows.add(new ArrayList<String>());
+    rows.add(new ArrayList<Comparable<? extends Object>>());
     return this;
   }
 
-  public KnoxShellTable value(String value) {
+  public KnoxShellTable value(Comparable<? extends Object> value) {
     final int index = rows.isEmpty() ? 0 : rows.size() - 1;
-    final List<String> row = rows.get(index);
+    final List<Comparable<? extends Object>> row = rows.get(index);
     row.add(value);
     return this;
   }
 
-  public KnoxShellTableCell cell(int colIndex, int rowIndex) {
+  public KnoxShellTableCell<? extends Comparable<? extends Object>> cell(int colIndex, int rowIndex) {
     return new KnoxShellTableCell(headers, rows, colIndex, rowIndex);
   }
 
-  public List<String> values(int colIndex) {
-    ArrayList<String> col = new ArrayList<String>();
+  public List<Comparable<? extends Object>> values(int colIndex) {
+    List<Comparable<? extends Object>> col = new ArrayList<Comparable<? extends Object>>();
     rows.forEach(row -> col.add(row.get(colIndex)));
     return col;
   }
 
-  public List<String> values(String colName) {
+  public List<Comparable<? extends Object>> values(String colName) {
     int colIndex = headers.indexOf(colName);
-    ArrayList<String> col = new ArrayList<String>();
+    List<Comparable<? extends Object>> col = new ArrayList<Comparable<? extends Object>>();
     rows.forEach(row -> col.add(row.get(colIndex)));
     return col;
   }
 
-  public KnoxShellTable apply(KnoxShellTableCell cell) {
+  public KnoxShellTable apply(KnoxShellTableCell<? extends Comparable<? extends Object>> cell) {
     if (!headers.isEmpty()) {
       headers.set(cell.colIndex, cell.header);
     }
@@ -87,7 +88,7 @@ public class KnoxShellTable {
     return headers == null || headers.isEmpty() ? null : headers;
   }
 
-  public List<List<String>> getRows() {
+  public List<List<Comparable<? extends Object>>> getRows() {
     return rows;
   }
 
@@ -105,15 +106,15 @@ public class KnoxShellTable {
 
   public KnoxShellTable select(String cols) {
     KnoxShellTable table = new KnoxShellTable();
-    List<List<String>> columns = new ArrayList<List<String>>();
+    List<List<Comparable<? extends Object>>> columns = new ArrayList<List<Comparable<? extends Object>>>();
     String[] colnames = cols.split(",");
     for (String colName : colnames) {
       table.header(colName);
-      columns.add((ArrayList<String>) values(headers.indexOf(colName)));
+      columns.add(values(headers.indexOf(colName)));
     }
     for (int i = 0; i < rows.size(); i++) {
       table.row();
-      for (List<String> col : columns) {
+      for (List<Comparable<? extends Object>> col : columns) {
         table.value(col.get(i));
       }
     }
@@ -123,8 +124,8 @@ public class KnoxShellTable {
   public KnoxShellTable sort(String colName) {
     KnoxShellTable table = new KnoxShellTable();
 
-    String value;
-    List<String> col = values(colName);
+    Comparable<? extends Object> value;
+    List<Comparable<? extends Object>> col = values(colName);
     List<RowIndex> index = new ArrayList<RowIndex>();
     for (int i = 0; i < col.size(); i++) {
       value = col.get(i);
@@ -133,23 +134,23 @@ public class KnoxShellTable {
     Collections.sort(index);
     table.headers = new ArrayList<String>(headers);
     for (RowIndex i : index) {
-      table.rows.add(new ArrayList<String>(this.rows.get(i.index)));
+      table.rows.add(new ArrayList<Comparable<? extends Object>>(this.rows.get(i.index)));
     }
     return table;
   }
 
   private static class RowIndex implements Comparable<RowIndex> {
-    String value;
+    Comparable value;
     int index;
 
-    public RowIndex(String value, int index) {
+    RowIndex(Comparable<? extends Object> value, int index) {
       this.value = value;
       this.index = index;
     }
 
     @Override
     public int compareTo(RowIndex other) {
-      return (this.value.compareTo(other.value));
+      return this.value.compareTo(other.value);
     }
   }
 
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
index d2e885d..1fc0e40 100644
--- 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
@@ -15,18 +15,17 @@
  * 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 {
+class KnoxShellTableCell<T extends Comparable<T>> implements Comparable<KnoxShellTableCell<T>>{
   int rowIndex;
   int colIndex;
   String header;
-  String value;
+  T value;
 
-  KnoxShellTableCell(List<String> headers, List<List<String>> rows, int colIndex, int rowIndex) {
+  KnoxShellTableCell(List<String> headers, List<List<T>> rows, int colIndex, int rowIndex) {
     this.rowIndex = rowIndex;
     this.colIndex = colIndex;
     if (!headers.isEmpty()) {
@@ -37,7 +36,7 @@ class KnoxShellTableCell {
     }
   }
 
-  KnoxShellTableCell(List<String> headers, List<List<String>> rows, String name, int rowIndex) {
+  KnoxShellTableCell(List<String> headers, List<List<T>> rows, String name, int rowIndex) {
     this.rowIndex = rowIndex;
     if (!headers.isEmpty()) {
       this.header = name;
@@ -48,14 +47,24 @@ class KnoxShellTableCell {
     }
   }
 
-  KnoxShellTableCell value(String value) {
+  KnoxShellTableCell<T> value(T value) {
     this.value = value;
     return this;
   }
 
-  KnoxShellTableCell header(String name) {
+  KnoxShellTableCell<T> header(String name) {
     this.header = name;
     return this;
   }
 
+  @Override
+  public String toString() {
+    return value.toString();
+  }
+
+  @Override
+  public int compareTo(KnoxShellTableCell<T> other) {
+    return value.compareTo(other.value);
+  }
+
 }
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
index 3a462cc..0ca5903 100644
--- 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
@@ -18,6 +18,7 @@
 package org.apache.knox.gateway.shell.table;
 
 import java.util.List;
+import java.util.function.Predicate;
 import java.util.regex.Pattern;
 
 public class KnoxShellTableFilter {
@@ -40,12 +41,13 @@ public class KnoxShellTableFilter {
     return this;
   }
 
+  //TODO: this method can be eliminated when the 'equalTo' method is implemented: regex(regex) = equalTo(anyString)
   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()) {
+    for (List<Comparable<?>> row : tableToFilter.rows) {
+      if (pattern.matcher(row.get(index).toString()).matches()) {
         filteredTable.row();
         row.forEach(value -> {
           filteredTable.value(value);
@@ -55,4 +57,29 @@ public class KnoxShellTableFilter {
     return filteredTable;
   }
 
+  @SuppressWarnings("rawtypes")
+  private KnoxShellTable filter(Predicate<Comparable> p) throws KnoxShellTableFilterException {
+    try {
+    final KnoxShellTable filteredTable = new KnoxShellTable();
+    filteredTable.headers.addAll(tableToFilter.headers);
+    for (List<Comparable<? extends Object>> row : tableToFilter.rows) {
+      if (p.test(row.get(index))) {
+        filteredTable.row(); // Adds a new empty row to filtered table
+        // Add each value to the row
+        row.forEach(value -> {
+          filteredTable.value(value);
+        });
+      }
+    }
+    return filteredTable;
+    } catch (Exception e) {
+      throw new KnoxShellTableFilterException(e);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  public KnoxShellTable greaterThan(Comparable<? extends Object> comparable) throws KnoxShellTableFilterException {
+    return filter(s -> s.compareTo(comparable) > 0);
+  }
+
 }
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableFilterException.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableFilterException.java
new file mode 100644
index 0000000..1966b8a
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableFilterException.java
@@ -0,0 +1,26 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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;
+
+@SuppressWarnings("serial")
+class KnoxShellTableFilterException extends Exception {
+
+  KnoxShellTableFilterException(Throwable e) {
+    super("Error while filtering KnoxShellTable: " + e.getMessage());
+  }
+
+}
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
index dd7295e..b38cac8 100644
--- 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
@@ -49,7 +49,7 @@ class KnoxShellTableRenderer {
         csv.append('\n');
       }
     }
-    for (List<String> row : tableToRender.rows) {
+    for (List<Comparable<? extends Object>> row : tableToRender.rows) {
       for (int ii = 0; ii < row.size(); ii++) {
         csv.append(row.get(ii));
         if (ii < row.size() - 1) {
@@ -92,11 +92,11 @@ class KnoxShellTableRenderer {
     }
     createBorder(sb, colCount, widthMap);
 
-    for (List<String> row : tableToRender.rows) {
+    for (List<Comparable<? extends Object>> 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);
+        sb.append(centerString(widthMap.get(i) + 4, row.get(i).toString())).append(CELL_WALL_CHAR);
       }
     }
 
@@ -150,9 +150,9 @@ class KnoxShellTableRenderer {
     }
     // 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 (List<Comparable<? extends Object>> row : tableToRender.rows) {
       for (int i = 0; i < row.size(); i++) {
-        cellValue = ensureEvenLength(row.get(i));
+        cellValue = ensureEvenLength(row.get(i).toString());
         if (map.get(i) == null || cellValue.length() > map.get(i)) {
           map.put(i, cellValue.length());
         }
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableRowDeserializer.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableRowDeserializer.java
new file mode 100644
index 0000000..cd372d5
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTableRowDeserializer.java
@@ -0,0 +1,76 @@
+/*
+ * 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 com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.TreeNode;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+/**
+ * A custom @JsonDeserializer in order to be able to deserialize a previously
+ * serialzed @KnoxShellTable. It is requiored because Jackson is not capable of
+ * constructing instance of `java.lang.Comparable` (which we have int he table
+ * cells)
+ *
+ */
+@SuppressWarnings("serial")
+public class KnoxShellTableRowDeserializer extends StdDeserializer<KnoxShellTable> {
+
+  KnoxShellTableRowDeserializer() {
+    this(KnoxShellTable.class);
+  }
+
+  protected KnoxShellTableRowDeserializer(Class<?> vc) {
+    super(vc);
+  }
+
+  @Override
+  public KnoxShellTable deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
+    final TreeNode jsonContent = parser.readValueAsTree();
+    final KnoxShellTable table = new KnoxShellTable();
+    if (jsonContent.get("title").size() != 0) {
+      table.title(trimJSONQuotes(jsonContent.get("title").toString()));
+    }
+
+    final TreeNode headers = jsonContent.get("headers");
+    for (int i = 0; i < headers.size(); i++) {
+      table.header(trimJSONQuotes(headers.get(i).toString()));
+    }
+    final TreeNode rows = jsonContent.get("rows");
+    for (int i = 0; i < rows.size(); i++) {
+      TreeNode row = rows.get(i);
+      table.row();
+      for (int j = 0; j < row.size(); j++) {
+        table.value(trimJSONQuotes(row.get(j).toString()));
+      }
+    }
+    return table;
+  }
+
+  /*
+   * When serializing an object as JSON all elements within the table receive a surrounding quote pair (e.g. the cell contains myValue -> the JSON serialized string will be "myValue")
+   */
+  private String trimJSONQuotes(String toBeTrimmed) {
+    return toBeTrimmed.replaceAll("\"", "");
+  }
+
+}
diff --git a/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableFilterTest.java b/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableFilterTest.java
new file mode 100644
index 0000000..a30b22f
--- /dev/null
+++ b/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableFilterTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class KnoxShellTableFilterTest {
+  private static final DateFormat TEST_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
+
+  private static final KnoxShellTable TABLE = new KnoxShellTable();
+
+  @BeforeClass
+  public static void init() throws ParseException {
+    TABLE.header("Column Integer").header("Column Double").header("Column String").header("Column Date");
+    synchronized (TEST_DATE_FORMAT) { //sync is needed due to https://pmd.github.io/latest/pmd_rules_java_multithreading.html#unsynchronizedstaticformatter
+      TABLE.row().value(10).value(20d).value("text30").value(TEST_DATE_FORMAT.parse("2010-01-01"));
+      TABLE.row().value(30).value(40d).value("text50").value(TEST_DATE_FORMAT.parse("2012-01-01"));
+    }
+  }
+
+  @Test
+  public void testRegexFilter() throws KnoxShellTableFilterException {
+    final KnoxShellTable filtered = TABLE.filter().name("Column Integer").regex("30");
+    assertEquals(filtered.getRows().size(), 1);
+  }
+
+  @Test
+  public void testGreaterThanFilter() throws KnoxShellTableFilterException, ParseException {
+    assertEquals(TABLE.filter().name("Column Integer").greaterThan(5).getRows().size(), 2);
+    assertEquals(TABLE.filter().name("Column Integer").greaterThan(25).getRows().size(), 1);
+
+    assertEquals(TABLE.filter().name("Column Double").greaterThan(10d).getRows().size(), 2);
+    assertEquals(TABLE.filter().name("Column Double").greaterThan(30d).getRows().size(), 1);
+
+    assertEquals(TABLE.filter().name("Column String").greaterThan("text20").getRows().size(), 2);
+    assertEquals(TABLE.filter().name("Column String").greaterThan("text30").getRows().size(), 1);
+
+    synchronized (TEST_DATE_FORMAT) {
+      assertEquals(TABLE.filter().name("Column Date").greaterThan(TEST_DATE_FORMAT.parse("2009-12-31")).getRows().size(), 2);
+      assertEquals(TABLE.filter().name("Column Date").greaterThan(TEST_DATE_FORMAT.parse("2011-01-01")).getRows().size(), 1);
+    }
+  }
+
+  @Test
+  public void testIncomparableColumns() {
+    boolean failed = false;
+    try {
+      TABLE.filter().name("Column Double").greaterThan("20");
+    } catch (KnoxShellTableFilterException e) {
+      failed = true;
+    }
+    assertTrue(failed);
+  }
+}
diff --git a/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java b/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java
index 766a0ad..3141afe 100644
--- a/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java
+++ b/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java
@@ -35,8 +35,6 @@ import java.sql.ResultSetMetaData;
 import java.sql.Statement;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.knox.gateway.shell.table.KnoxShellTable;
-import org.apache.knox.gateway.shell.table.KnoxShellTableCell;
 import org.easymock.IAnswer;
 import org.junit.Test;
 
@@ -199,6 +197,7 @@ public class KnoxShellTableTest {
   }
 
   @Test
+  @SuppressWarnings({ "rawtypes", "unchecked" })
   public void testCells() throws IOException {
     KnoxShellTable table = new KnoxShellTable();
 
@@ -289,8 +288,8 @@ public class KnoxShellTableTest {
         return false;
       }
     }).times(2);
-    expect(resultSet.getString("BOOK_ID")).andReturn("1").times(1);
-    expect(resultSet.getString("TITLE")).andReturn("Apache Knox: The Definitive Guide").times(1);
+    expect(resultSet.getObject("BOOK_ID", Comparable.class)).andReturn("1").times(1);
+    expect(resultSet.getObject("TITLE", Comparable.class)).andReturn("Apache Knox: The Definitive Guide").times(1);
     expect(metadata.getTableName(1)).andReturn("BOOK");
     expect(metadata.getColumnCount()).andReturn(2);
     expect(metadata.getColumnName(1)).andReturn("BOOK_ID").anyTimes();