/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2008 Sun Microsystems, Inc. */ package org.opends.server.util.table; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.opends.messages.Message; /** * A class which can be used to construct tables of information to be * displayed in a terminal. Once built the table can be output using a * {@link TableSerializer}. */ public final class TableBuilder { // The current column number in the current row where 0 represents // the left-most column in the table. private int column = 0; // The current with of each column. private List<Integer> columnWidths = new ArrayList<Integer>(); // The list of column headings. private List<Message> header = new ArrayList<Message>(); // The current number of rows in the table. private int height = 0; // The list of table rows. private List<List<String>> rows = new ArrayList<List<String>>(); // The linked list of sort keys comparators. private List<Comparator<String>> sortComparators = new ArrayList<Comparator<String>>(); // The linked list of sort keys. private List<Integer> sortKeys = new ArrayList<Integer>(); // The current number of columns in the table. private int width = 0; /** * Creates a new table printer. */ public TableBuilder() { // No implementation required. } /** * Adds a table sort key. The table will be sorted according to the * case-insensitive string ordering of the cells in the specified * column. * * @param column * The column which will be used as a sort key. */ public void addSortKey(int column) { addSortKey(column, String.CASE_INSENSITIVE_ORDER); } /** * Adds a table sort key. The table will be sorted according to the * provided string comparator. * * @param column * The column which will be used as a sort key. * @param comparator * The string comparator. */ public void addSortKey(int column, Comparator<String> comparator) { sortKeys.add(column); sortComparators.add(comparator); } /** * Appends a new blank cell to the current row. */ public void appendCell() { appendCell(""); } /** * Appends a new cell to the current row containing the provided * boolean value. * * @param value * The boolean value. */ public void appendCell(boolean value) { appendCell(String.valueOf(value)); } /** * Appends a new cell to the current row containing the provided * byte value. * * @param value * The byte value. */ public void appendCell(byte value) { appendCell(String.valueOf(value)); } /** * Appends a new cell to the current row containing the provided * char value. * * @param value * The char value. */ public void appendCell(char value) { appendCell(String.valueOf(value)); } /** * Appends a new cell to the current row containing the provided * double value. * * @param value * The double value. */ public void appendCell(double value) { appendCell(String.valueOf(value)); } /** * Appends a new cell to the current row containing the provided * float value. * * @param value * The float value. */ public void appendCell(float value) { appendCell(String.valueOf(value)); } /** * Appends a new cell to the current row containing the provided * integer value. * * @param value * The boolean value. */ public void appendCell(int value) { appendCell(String.valueOf(value)); } /** * Appends a new cell to the current row containing the provided * long value. * * @param value * The long value. */ public void appendCell(long value) { appendCell(String.valueOf(value)); } /** * Appends a new cell to the current row containing the provided * object value. * * @param value * The object value. */ public void appendCell(Object value) { // Make sure that the first row has been created. if (height == 0) { startRow(); } // Create the cell. String s = String.valueOf(value); rows.get(height - 1).add(s); column++; // Update statistics. if (column > width) { width = column; columnWidths.add(s.length()); } else if (columnWidths.get(column - 1) < s.length()) { columnWidths.set(column - 1, s.length()); } } /** * Appends a new blank column heading to the header row. */ public void appendHeading() { appendHeading(Message.EMPTY); } /** * Appends a new column heading to the header row. * * @param value * The column heading value. */ public void appendHeading(Message value) { header.add(value); // Update statistics. if (header.size() > width) { width = header.size(); columnWidths.add(value.length()); } else if (columnWidths.get(header.size() - 1) < value.length()) { columnWidths.set(header.size() - 1, value.length()); } } /** * Gets the width of the current row. * * @return Returns the width of the current row. */ public int getRowWidth() { return column; } /** * Gets the number of rows in table. * * @return Returns the number of rows in table. */ public int getTableHeight() { return height; } /** * Gets the number of columns in table. * * @return Returns the number of columns in table. */ public int getTableWidth() { return width; } /** * Prints the table in its current state using the provided table * printer. * * @param printer * The table printer. */ public void print(TablePrinter printer) { // Create a new printer instance. TableSerializer serializer = printer.getSerializer(); // First sort the table. List<List<String>> sortedRows = new ArrayList<List<String>>(rows); Comparator<List<String>> comparator = new Comparator<List<String>>() { public int compare(List<String> row1, List<String> row2) { for (int i = 0; i < sortKeys.size(); i++) { String cell1 = row1.get(sortKeys.get(i)); String cell2 = row2.get(sortKeys.get(i)); int rc = sortComparators.get(i).compare(cell1, cell2); if (rc != 0) { return rc; } } // Both rows are equal. return 0; } }; Collections.sort(sortedRows, comparator); // Now output the table. serializer.startTable(height, width); for (int i = 0; i < width; i++) { serializer.addColumn(columnWidths.get(i)); } // Column headings. serializer.startHeader(); for (Message s : header) { serializer.addHeading(s.toString()); } serializer.endHeader(); // Table contents. serializer.startContent(); for (List<String> row : sortedRows) { serializer.startRow(); // Print each cell in the row, padding missing trailing cells. for (int i = 0; i < width; i++) { if (i < row.size()) { serializer.addCell(row.get(i)); } else { serializer.addCell(""); } } serializer.endRow(); } serializer.endContent(); serializer.endTable(); } /** * Appends a new row to the table. */ public void startRow() { rows.add(new ArrayList<String>()); height++; column = 0; } }