/* * Copyright 2009-2013 the original author or authors. * * 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. */ package org.springframework.xd.shell.util; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang.StringUtils; import com.google.common.base.Splitter; /** * Contains utility methods for rendering data to a formatted console output. E.g. it provides helper methods for * rendering ASCII-based data tables. * * @author Gunnar Hillert * @author Thomas Risberg * @since 1.0 * */ public final class UiUtils { public static final String HORIZONTAL_LINE = "-------------------------------------------------------------------------------\n"; public static final int COLUMN_1 = 1; public static final int COLUMN_2 = 2; public static final int COLUMN_3 = 3; public static final int COLUMN_4 = 4; public static final int COLUMN_5 = 5; public static final int COLUMN_6 = 6; /** * Prevent instantiation. * */ private UiUtils() { throw new AssertionError(); } /** * Renders a textual representation of the list of provided Map data * * @param columns List of Maps * @return The rendered table representation as String * */ public static String renderMapDataAsTable(List<Map<String, Object>> data, List<String> columns) { Table table = new Table(); int col = 0; for (String colName : columns) { col++; table.getHeaders().put(col, new TableHeader(colName)); if (col >= 6) { break; } } for (Map<String, Object> dataRow : data) { TableRow tableRow = new TableRow(); for (int i = 0; i < col; i++) { String value = dataRow.get(columns.get(i)).toString(); table.getHeaders().get(i + 1).updateWidth(value.length()); tableRow.addValue(i + 1, value); } table.getRows().add(tableRow); } return renderTextTable(table); } public static String renderParameterInfoDataAsTable(Map<String, String> parameters, boolean withHeader, int lastColumnMaxWidth) { final Table table = new Table(); table.getHeaders().put(COLUMN_1, new TableHeader("Parameter")); final TableHeader tableHeader2 = new TableHeader("Value (Configured or Default)"); tableHeader2.setMaxWidth(lastColumnMaxWidth); table.getHeaders().put(COLUMN_2, tableHeader2); for (Entry<String, String> entry : parameters.entrySet()) { final TableRow tableRow = new TableRow(); table.getHeaders().get(COLUMN_1).updateWidth(entry.getKey().length()); tableRow.addValue(COLUMN_1, entry.getKey()); int width = entry.getValue() != null ? entry.getValue().length() : 0; table.getHeaders().get(COLUMN_2).updateWidth(width); tableRow.addValue(COLUMN_2, entry.getValue()); table.getRows().add(tableRow); } return renderTextTable(table, withHeader); } /** * Renders a textual representation of provided parameter map. * * @param parameters Map of parameters (key, value) * @return The rendered table representation as String * */ public static String renderParameterInfoDataAsTable(Map<String, String> parameters) { return renderParameterInfoDataAsTable(parameters, true, -1); } public static String renderTextTable(Table table) { return renderTextTable(table, true); } /** * Renders a textual representation of the provided {@link Table} * * @param table Table data {@link Table} * @return The rendered table representation as String */ public static String renderTextTable(Table table, boolean withHeader) { table.calculateColumnWidths(); final String padding = " "; final String headerBorder = getHeaderBorder(table.getHeaders()); final StringBuilder textTable = new StringBuilder(); if (withHeader) { final StringBuilder headerline = new StringBuilder(); for (TableHeader header : table.getHeaders().values()) { if (header.getName().length() > header.getWidth()) { Iterable<String> chunks = Splitter.fixedLength(header.getWidth()).split(header.getName()); int length = headerline.length(); boolean first = true; for (String chunk : chunks) { final String lineToAppend; if (first) { lineToAppend = padding + CommonUtils.padRight(chunk, header.getWidth()); } else { lineToAppend = StringUtils.leftPad("", length) + padding + CommonUtils.padRight(chunk, header.getWidth()); } first = false; headerline.append(lineToAppend); headerline.append("\n"); } headerline.deleteCharAt(headerline.lastIndexOf("\n")); } else { String lineToAppend = padding + CommonUtils.padRight(header.getName(), header.getWidth()); headerline.append(lineToAppend); } } textTable.append(org.springframework.util.StringUtils.trimTrailingWhitespace(headerline.toString())); textTable.append("\n"); } textTable.append(headerBorder); for (TableRow row : table.getRows()) { StringBuilder rowLine = new StringBuilder(); for (Entry<Integer, TableHeader> entry : table.getHeaders().entrySet()) { String value = row.getValue(entry.getKey()); if (null != value && (value.length() > entry.getValue().getWidth())) { Iterable<String> chunks = Splitter.fixedLength(entry.getValue().getWidth()).split(value); int length = rowLine.length(); boolean first = true; for (String chunk : chunks) { final String lineToAppend; if (first) { lineToAppend = padding + CommonUtils.padRight(chunk, entry.getValue().getWidth()); } else { lineToAppend = StringUtils.leftPad("", length) + padding + CommonUtils.padRight(chunk, entry.getValue().getWidth()); } first = false; rowLine.append(lineToAppend); rowLine.append("\n"); } rowLine.deleteCharAt(rowLine.lastIndexOf("\n")); } else { String lineToAppend = padding + CommonUtils.padRight(value, entry.getValue().getWidth()); rowLine.append(lineToAppend); } } textTable.append(org.springframework.util.StringUtils.trimTrailingWhitespace(rowLine.toString())); textTable.append("\n"); } if (!withHeader) { textTable.append(headerBorder); } return textTable.toString(); } /** * Renders the Table header border, based on the map of provided headers. * * @param headers Map of headers containing meta information e.g. name+width of header * @return Returns the rendered header border as String */ public static String getHeaderBorder(Map<Integer, TableHeader> headers) { final StringBuilder headerBorder = new StringBuilder(); for (TableHeader header : headers.values()) { headerBorder.append(CommonUtils.padRight(" ", header.getWidth() + 2, '-')); } headerBorder.append("\n"); return headerBorder.toString(); } }