| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| NiceTable |
|
| 1.6153846153846154;1.615 |
| 1 | /** | |
| 2 | * Copyright (c) 2012, University of Konstanz, Distributed Systems Group | |
| 3 | * All rights reserved. | |
| 4 | * | |
| 5 | * Redistribution and use in source and binary forms, with or without | |
| 6 | * modification, are permitted provided that the following conditions are met: | |
| 7 | * * Redistributions of source code must retain the above copyright | |
| 8 | * notice, this list of conditions and the following disclaimer. | |
| 9 | * * Redistributions in binary form must reproduce the above copyright | |
| 10 | * notice, this list of conditions and the following disclaimer in the | |
| 11 | * documentation and/or other materials provided with the distribution. | |
| 12 | * * Neither the name of the University of Konstanz nor the | |
| 13 | * names of its contributors may be used to endorse or promote products | |
| 14 | * derived from this software without specific prior written permission. | |
| 15 | * | |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
| 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| 19 | * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY | |
| 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 26 | */ | |
| 27 | package org.perfidix.ouput.asciitable; | |
| 28 | ||
| 29 | import java.util.ArrayList; | |
| 30 | import java.util.List; | |
| 31 | ||
| 32 | import org.perfidix.ouput.asciitable.AbstractTabularComponent.Alignment; | |
| 33 | ||
| 34 | /** | |
| 35 | * This class represents a table which allows formatting of data as an ascii | |
| 36 | * table. it takes care of automatically adjusting widths of the tables. A word | |
| 37 | * on the orientations: at the current point of development, the orientation | |
| 38 | * works on COLUMNS and NOT on ROWs. so you can set the orientation of a full | |
| 39 | * ROW, but you cannot set the orientation for each field[x][y] in the table. | |
| 40 | * | |
| 41 | * @author Alexander Onea, neue Couch | |
| 42 | * @author Sebastian Graf, University of Konstanz | |
| 43 | */ | |
| 44 | public final class NiceTable { | |
| 45 | ||
| 46 | /** | |
| 47 | * Container for all rows. | |
| 48 | */ | |
| 49 | private transient final List<AbstractTabularComponent> rows; | |
| 50 | ||
| 51 | /** | |
| 52 | * Storing the length of chars in the different columns. | |
| 53 | */ | |
| 54 | private transient final int[] columnLengths; | |
| 55 | ||
| 56 | /** | |
| 57 | * An array holding the orientations of columns. | |
| 58 | */ | |
| 59 | private transient final Alignment[] orientations; | |
| 60 | ||
| 61 | /** | |
| 62 | * Constructor. needs the number of columns to show. | |
| 63 | * | |
| 64 | * @param numberOfColumns | |
| 65 | * the number of columns to display. | |
| 66 | */ | |
| 67 | 95 | public NiceTable(final int numberOfColumns) { |
| 68 | ||
| 69 | 95 | columnLengths = new int[numberOfColumns]; |
| 70 | 95 | orientations = new Alignment[numberOfColumns]; |
| 71 | 95 | rows = new ArrayList<AbstractTabularComponent>(); |
| 72 | 95 | } |
| 73 | ||
| 74 | /** | |
| 75 | * Adds a header. | |
| 76 | * | |
| 77 | * @param title | |
| 78 | * the text to display within the header | |
| 79 | */ | |
| 80 | public void addHeader(final String title) { | |
| 81 | 20 | addHeader(title, '=', Alignment.Left); |
| 82 | 20 | } |
| 83 | ||
| 84 | /** | |
| 85 | * Adds a header row to the table. can be used to give a table some title. | |
| 86 | * | |
| 87 | * <pre> | |
| 88 | * addHeader("hello",'.',NiceTable.LEFT) | |
| 89 | * would produce a row like | |
| 90 | * ... hello .......................... | |
| 91 | * {rows in here.} | |
| 92 | * </pre> | |
| 93 | * | |
| 94 | * @param title | |
| 95 | * the string to display as a header | |
| 96 | * @param mark | |
| 97 | * the mark to use for the rest of the column | |
| 98 | * @param orientation | |
| 99 | * the orientation of the header column. | |
| 100 | */ | |
| 101 | public void addHeader(final String title, final char mark, final Alignment orientation) { | |
| 102 | 224 | final Header header = new Header(title, mark, orientation, this); |
| 103 | 224 | rows.add(header); |
| 104 | 224 | } |
| 105 | ||
| 106 | /** | |
| 107 | * Adds a string row. checks that the strings added do not contain newlines, | |
| 108 | * because if so, it has to split them in order to make them fit the row. | |
| 109 | * | |
| 110 | * @param data | |
| 111 | * the array of data. | |
| 112 | */ | |
| 113 | public void addRow(final String[] data) { | |
| 114 | 195 | if (anyStringContainsNewLine(data)) { |
| 115 | 5 | final String[][] theMatrix = Util.createMatrix(data); |
| 116 | 20 | for (int i = 0; i < theMatrix.length; i++) { |
| 117 | 15 | addRow(theMatrix[i]); |
| 118 | } | |
| 119 | 5 | } else { |
| 120 | 190 | final Row myRow = new Row(this, data); |
| 121 | 190 | rows.add(myRow); |
| 122 | } | |
| 123 | ||
| 124 | 195 | } |
| 125 | ||
| 126 | /** | |
| 127 | * allows the addition of lines. think of it as a horizontal rule in a | |
| 128 | * table. | |
| 129 | * | |
| 130 | * @param fill | |
| 131 | * any character with which to draw the line. | |
| 132 | */ | |
| 133 | public void addLine(final char fill) { | |
| 134 | 86 | rows.add(new DynamicLine(fill, this)); |
| 135 | 86 | } |
| 136 | ||
| 137 | /** | |
| 138 | * the main method doing the work. draws everyting. | |
| 139 | * | |
| 140 | * @return the formatted table. | |
| 141 | */ | |
| 142 | @Override | |
| 143 | public String toString() { | |
| 144 | ||
| 145 | 80 | final StringBuilder builder = new StringBuilder(); |
| 146 | ||
| 147 | 580 | for (int i = 0; i < rows.size(); i++) { |
| 148 | 500 | final AbstractTabularComponent myObj = rows.get(i); |
| 149 | 500 | builder.append(myObj.draw()); |
| 150 | } | |
| 151 | 80 | return builder.toString(); |
| 152 | } | |
| 153 | ||
| 154 | /** | |
| 155 | * Returns the global column width at index columnIndex. | |
| 156 | * | |
| 157 | * @param columnIndex | |
| 158 | * the index of the column for which to fetch the width. | |
| 159 | * @return the width (in number of chars) for the column index. | |
| 160 | */ | |
| 161 | protected int getColumnWidth(final int columnIndex) { | |
| 162 | ||
| 163 | 40745 | return columnLengths[columnIndex]; |
| 164 | } | |
| 165 | ||
| 166 | /** | |
| 167 | * Performs an update on the column lengths. | |
| 168 | * | |
| 169 | * @param index | |
| 170 | * the index of the column | |
| 171 | * @param newSize | |
| 172 | * the new size of the column | |
| 173 | */ | |
| 174 | protected void updateColumnWidth(final int index, final int newSize) { | |
| 175 | 1320 | columnLengths[index] = Math.max(columnLengths[index], newSize); |
| 176 | 1320 | } |
| 177 | ||
| 178 | /** | |
| 179 | * Returns the actual number of columns this table has got. | |
| 180 | * | |
| 181 | * @return the number of columns the table may contain. | |
| 182 | */ | |
| 183 | private int numColumns() { | |
| 184 | 310 | return this.columnLengths.length; |
| 185 | } | |
| 186 | ||
| 187 | /** | |
| 188 | * Returns the orientation of a column. | |
| 189 | * | |
| 190 | * @param columnIndex | |
| 191 | * integer | |
| 192 | * @return Alignment for the column | |
| 193 | */ | |
| 194 | protected Alignment getOrientation(final int columnIndex) { | |
| 195 | ||
| 196 | 1320 | return orientations[columnIndex]; |
| 197 | } | |
| 198 | ||
| 199 | /** | |
| 200 | * Returns the row width. | |
| 201 | * | |
| 202 | * @return int the width of the row | |
| 203 | */ | |
| 204 | private int getRowWidth() { | |
| 205 | 310 | int returnVal = 1; |
| 206 | 310 | if (rows.size() < 1) { |
| 207 | 0 | returnVal = 0; |
| 208 | } | |
| 209 | 13375 | for (int i = 0; i < rows.size(); i++) { |
| 210 | 13065 | if (rows.get(i) instanceof Row) { |
| 211 | 4405 | returnVal = ((Row)rows.get(i)).getRowWidth(); |
| 212 | } | |
| 213 | } | |
| 214 | 310 | return returnVal; |
| 215 | } | |
| 216 | ||
| 217 | /** | |
| 218 | * Returns the total width of the table. | |
| 219 | * | |
| 220 | * @return int the width of the table | |
| 221 | */ | |
| 222 | protected int getTotalWidth() { | |
| 223 | 310 | return this.getRowWidth() + 3 * numColumns() + 1; |
| 224 | } | |
| 225 | ||
| 226 | /** | |
| 227 | * Tests whether any string contains a newline symbol. | |
| 228 | * | |
| 229 | * @param data | |
| 230 | * the array to check. | |
| 231 | * @return whether any of the strings contains a newline symbol. | |
| 232 | */ | |
| 233 | private boolean anyStringContainsNewLine(final String[] data) { | |
| 234 | 195 | boolean returnVal = false; |
| 235 | 1525 | for (int i = 0; i < data.length; i++) { |
| 236 | 1330 | if (Util.containsNewlines(data[i])) { |
| 237 | 10 | returnVal = true; |
| 238 | } | |
| 239 | } | |
| 240 | 195 | return returnVal; |
| 241 | } | |
| 242 | ||
| 243 | } |