/** * Copyright 2014 Yahoo! Inc. Licensed 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. * See accompanying LICENSE file. */ package com.yahoo.sql4d.sql4ddriver; import static java.lang.String.format; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * Partial code modified from a publication here * http://stackoverflow.com/questions/11383070/pretty-print-2d-array-in-java * @author srikalyan */ public final class PrettyPrint { private static final char BORDER_KNOT = '+'; private static final char HORIZONTAL_BORDER = '-'; private static final char VERTICAL_BORDER = '|'; private static final String asNull = "(NULL)"; public static void print(Mapper4All mapper4All) { int rowsSize = mapper4All.baseAllRows.size() + 1;// +1 for headers String[][] table = new String[rowsSize][]; table[0] = mapper4All.baseFieldNames.toArray(new String[0]); int index = 1; for (List<Object> row: mapper4All.baseAllRows) { table[index] = new String[row.size()]; int i = 0; for (Object col:row) { table[index][i++] = col.toString(); } index++; } print(table); } public static void print(Joiner4All joiner4All) { int rowsSize = joiner4All.baseAllRows.size() + 1;// +1 for headers String[][] table = new String[rowsSize][]; table[0] = joiner4All.baseFieldNames.toArray(new String[0]); int index = 1; for (List<Object> row: joiner4All.baseAllRows.values()) { table[index] = new String[row.size()]; int i = 0; for (Object col:row) { table[index][i++] = col.toString(); } index++; } print(table); } public static void print(String[][] table) { if ( table == null ) { throw new IllegalArgumentException("No tabular data provided"); } if ( table.length == 0 ) { return; } final int[] widths = new int[getMaxColumns(table)]; adjustColumnWidths(table, widths); printPreparedTable(table, widths, getHorizontalBorder(widths)); } private static void printPreparedTable(String[][] table, int widths[], String horizontalBorder) { final int lineLength = horizontalBorder.length(); Util.println(horizontalBorder); for ( final String[] row : table ) { if (row != null) { Util.println(getRow(row, widths, lineLength)); Util.println(horizontalBorder); } } } private static String getRow(String[] row, int[] widths, int lineLength) { final StringBuilder builder = new StringBuilder(lineLength).append(VERTICAL_BORDER); final int maxWidths = widths.length; for ( int i = 0; i < maxWidths; i++ ) { builder.append(padRight(getCellValue(safeGet(row, i, null)), widths[i])).append(VERTICAL_BORDER); } return builder.toString(); } private static int getMaxColumns(String[][] rows) { int max = 0; for ( final String[] row : rows ) { if ( row != null && row.length > max ) { max = row.length; } } return max; } private static String getHorizontalBorder(int[] widths) { final StringBuilder builder = new StringBuilder(256); builder.append(BORDER_KNOT); for ( final int w : widths ) { for ( int i = 0; i < w; i++ ) { builder.append(HORIZONTAL_BORDER); } builder.append(BORDER_KNOT); } return builder.toString(); } private static void adjustColumnWidths(String[][] rows, int[] widths) { for ( final String[] row : rows ) { if ( row != null ) { for ( int c = 0; c < widths.length; c++ ) { final String cv = getCellValue(safeGet(row, c, asNull)); final int l = cv.length(); if ( widths[c] < l ) { widths[c] = l; } } } } } private static String safeGet(String[] array, int index, String defaultValue) { return index < array.length ? array[index] : defaultValue; } private static String getCellValue(Object value) { return value == null ? asNull : value.toString(); } /////////// Bean based input for pretty printing /////////////// public static <T> void print(List<T> table) { if (table == null ) { throw new IllegalArgumentException("No tabular data provided"); } if (table.isEmpty()) { return; } final int[] widths = new int[getMaxColumns(table)]; adjustColumnWidths(table, widths); printPreparedTable(table, widths, getHorizontalBorder(widths)); } private static <T> void printPreparedTable(List<T> table, int widths[], String horizontalBorder) { final int lineLength = horizontalBorder.length(); Util.println(horizontalBorder); boolean makeCall = false; for (final T row : table) { if (row != null) { Util.println(getRow(row, widths, lineLength, makeCall)); Util.println(horizontalBorder); if (!makeCall) { makeCall = true; // Print again because though 1st row has data we only printed the header. Util.println(getRow(row, widths, lineLength, makeCall)); Util.println(horizontalBorder); } } } } private static <T> String getRow(T row, int[] widths, int lineLength, boolean makeCall) { final StringBuilder builder = new StringBuilder(lineLength).append(VERTICAL_BORDER); final int maxWidths = widths.length; for (int i = 0; i < maxWidths; i++ ) { builder.append(padRight(getCellValue(safeGet(row, i, null, makeCall)), widths[i])).append(VERTICAL_BORDER); } return builder.toString(); } private static <T> int getMaxColumns(List<T> table) { if (table != null && !table.isEmpty()) { return Util.getAllGetters(table.get(0).getClass()).size(); } return 0; } private static <T> void adjustColumnWidths(List<T> rows, int[] widths) { boolean makeCall = false; for (final T row : rows ) { if (row != null ) { for (int c = 0; c < widths.length; c++ ) { final String cv = getCellValue(safeGet(row, c, asNull, makeCall)); final int l = cv.length(); if (widths[c] < l ) { widths[c] = l; } } } if (!makeCall) { makeCall = true; } } } private static String padRight(String s, int n) { return format("%1$-" + n + "s", s); } private static <T> String safeGet(T bean, int index, String defaultValue, boolean makeCall) { List<Method> getters = Util.getAllGetters(bean.getClass()); if (index < getters.size()) { try { if (!makeCall) { return getters.get(index).getName().substring(3); } Object value = getters.get(index).invoke(bean); if (value != null) { return value.toString(); } } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { Logger.getLogger(PrettyPrint.class.getName()).log(Level.SEVERE, null, ex); } } return defaultValue; } }