// Copyright 2015 ThoughtWorks, Inc. // This file is part of Gauge-Java. // This program is free software. // // It is dual-licensed under: // 1) the GNU General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version; // or // 2) the Eclipse Public License v1.0. // // You can redistribute it and/or modify it under the terms of either license. // We would then provide copied of each license in a separate .txt file with the name of the license as the title of the file. package com.thoughtworks.gauge; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.Lists; import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * Custom Table structure used as parameter in steps. */ public class Table { private static final String LINE_SEPARATOR = System.getProperty("line.separator"); private static final String DASH = "-"; private static final String PIPE = "|"; private static final char SPACE_AS_CHAR = " ".charAt(0); private final List<String> headers; private final List<List<String>> rows; private final List<TableRow> tableRows; public Table(List<String> headers) { this.headers = headers; rows = new ArrayList<List<String>>(); tableRows = new ArrayList<TableRow>(); } public void addRow(List<String> row) { if (row.size() != headers.size()) { throw new RowSizeMismatchException(String.format("Row size mismatch. Expected row size: %d. Obtained row size: %d.", headers.size(), row.size())); } rows.add(row); TableRow rowToAdd = new TableRow(); for (String header : headers) { rowToAdd.addCell(header, row.get(headers.indexOf(header))); } tableRows.add(rowToAdd); } /** * @return List of Names of the Columns on the table */ public List<String> getColumnNames() { return headers; } /** * Gets a Column name by index. * @param columnIndex * @return a single column name by given column index. */ public String getColumnName(int columnIndex) { if (columnIndex < 0 || columnIndex >= getColumnNames().size()) { throw new IndexOutOfBoundsException(String.format("Column with index %d not found. Actual column size: %d.", columnIndex, getColumnNames().size())); } return getColumnNames().get(columnIndex); } /** * @return List of Rows in the table. Each Row is represented by a TableRow. */ public List<TableRow> getTableRows() { return tableRows; } /** * @return List of TableRows in the table. Each Row is represented by a List of String values * according to the order of column names * @deprecated Use getTableRows() method instead of this. */ @Deprecated public List<List<String>> getRows() { return rows; } /** * Get all the values of a column in Table. * * @param columnName - The column name of the Table * @return List of values against a column in Table. */ public List<String> getColumnValues(String columnName) { int columnIndex = headers.indexOf(columnName); return getColumnValues(columnIndex); } /** * Get all the values of a column in a Table. * * @param columnIndex - The column index of the table * @return List of row values of a given column index in a Table. */ public List<String> getColumnValues(int columnIndex) { List<String> columnValues = new ArrayList<String>(); if (columnIndex >= 0) { for (List<String> row : rows) { columnValues.add(row.get(columnIndex)); } } return columnValues; } @Override public String toString() { int maxStringLength = getMaxStringLength(); if (maxStringLength >= 0) { return formatAsMarkdownTable(maxStringLength); } return StringUtils.EMPTY; } private String formatAsMarkdownTable( int maxStringLength) { List<String> formattedHeaderAndRows = new ArrayList<String>(); addHeader(maxStringLength, formattedHeaderAndRows); addDashes(maxStringLength, formattedHeaderAndRows); addValues(maxStringLength, formattedHeaderAndRows); return Joiner.on(LINE_SEPARATOR).join(formattedHeaderAndRows); } private void addDashes( int maxStringLength, List<String> formattedHeaderAndRows) { String dashesString = Joiner.on(StringUtils.EMPTY).join(Collections.nCopies(maxStringLength, DASH)); List<String> dashes = Collections.nCopies(headers.size(), dashesString); String formattedDashes = formattedRow(dashes, maxStringLength); formattedHeaderAndRows.add(formattedDashes); } private void addHeader( int maxStringLength, List<String> formattedHeaderAndRows) { String formattedHeaders = formattedRow(headers, maxStringLength); formattedHeaderAndRows.add(formattedHeaders); } private void addValues( int maxStringLength, List<String> formattedHeaderAndRows) { for (TableRow tableRow : tableRows) { formattedHeaderAndRows.add(formattedRow(tableRow.getCellValues(), maxStringLength)); } } private String formattedRow(List<String> strings, int maxStringLength) { List<String> formattedStrings = Lists.transform(strings, format(maxStringLength)); return PIPE + Joiner.on(PIPE).join(formattedStrings) + PIPE; } private Function<String, String> format( final int maxStringLength) { return new Function<String, String>() { @Override public String apply( String input) { return Strings.padEnd(input, maxStringLength, SPACE_AS_CHAR); } }; } private Integer getMaxStringLength() { List<Integer> maxs = new ArrayList<Integer>(); maxs.add(getMaxStringSize(headers)); for (TableRow tableRow : tableRows) { maxs.add(getMaxStringSize(tableRow.getCellValues())); } return Collections.max(maxs); } private int getMaxStringSize(List<String> candidates) { if (candidates == null || candidates.isEmpty()) { return -1; } return Collections.max(candidates, maxStringLength()).length(); } private Comparator<String> maxStringLength() { return new Comparator<String>() { @Override public int compare( String o1, String o2) { if (o1.length() < o2.length()) { return -1; } return 1; } }; } }