| opends/src/server/org/opends/server/util/table/CSVTablePrinter.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/util/table/TabSeparatedTablePrinter.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/util/table/TableBuilder.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/util/table/TablePrinter.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/util/table/TableSerializer.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/util/table/TextTablePrinter.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/util/table/package-info.java | ●●●●● patch | view | raw | blame | history |
opends/src/server/org/opends/server/util/table/CSVTablePrinter.java
New file @@ -0,0 +1,253 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.util.table; import java.io.BufferedWriter; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.Writer; /** * An interface for creating a CSV formatted table. */ public final class CSVTablePrinter extends TablePrinter { /** * Table serializer implementation. */ private static final class Serializer extends TableSerializer { // The current column being output. private int column = 0; // Indicates whether or not the headings should be output. private final boolean displayHeadings; // Counts the number of separators that should be output the next // time a non-empty cell is displayed. The comma separators are // not displayed immediately so that we can avoid displaying // unnecessary trailing separators. private int requiredSeparators = 0; // The output destination. private final PrintWriter writer; // Private constructor. private Serializer(PrintWriter writer, boolean displayHeadings) { this.writer = writer; this.displayHeadings = displayHeadings; } /** * {@inheritDoc} */ @Override public void addCell(String s) { // Avoid printing comma separators for trailing empty cells. if (s.length() == 0) { requiredSeparators++; } else { for (int i = 0; i < requiredSeparators; i++) { writer.print(','); } requiredSeparators = 1; } boolean needsQuoting = false; if (s.contains(",")) { needsQuoting = true; } if (s.contains("\n")) { needsQuoting = true; } if (s.contains("\r")) { needsQuoting = true; } if (s.contains("\"")) { needsQuoting = true; s = s.replace("\"", "\"\""); } if (s.startsWith(" ")) { needsQuoting = true; } if (s.endsWith(" ")) { needsQuoting = true; } StringBuilder builder = new StringBuilder(); if (needsQuoting) { builder.append("\""); } builder.append(s); if (needsQuoting) { builder.append("\""); } writer.print(builder.toString()); column++; } /** * {@inheritDoc} */ @Override public void addHeading(String s) { if (displayHeadings) { addCell(s); } } /** * {@inheritDoc} */ @Override public void endHeader() { if (displayHeadings) { writer.println(); } } /** * {@inheritDoc} */ @Override public void endRow() { writer.println(); } /** * {@inheritDoc} */ @Override public void endTable() { writer.flush(); } /** * {@inheritDoc} */ @Override public void startHeader() { column = 0; requiredSeparators = 0; } /** * {@inheritDoc} */ @Override public void startRow() { column = 0; requiredSeparators = 0; } } // Indicates whether or not the headings should be output. private boolean displayHeadings = false; // The output destination. private PrintWriter writer = null; /** * Creates a new CSV table printer for the specified output stream. * Headings will not be displayed by default. * * @param stream * The stream to output tables to. */ public CSVTablePrinter(OutputStream stream) { this(new BufferedWriter(new OutputStreamWriter(stream))); } /** * Creates a new CSV table printer for the specified writer. * Headings will not be displayed by default. * * @param writer * The writer to output tables to. */ public CSVTablePrinter(Writer writer) { this.writer = new PrintWriter(writer); } /** * Specify whether or not table headings should be displayed. * * @param displayHeadings * <code>true</code> if table headings should be * displayed. */ public void setDisplayHeadings(boolean displayHeadings) { this.displayHeadings = displayHeadings; } /** * {@inheritDoc} */ @Override protected TableSerializer getSerializer() { return new Serializer(writer, displayHeadings); } } opends/src/server/org/opends/server/util/table/TabSeparatedTablePrinter.java
New file @@ -0,0 +1,220 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.util.table; import java.io.BufferedWriter; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.Writer; /** * An interface for creating a tab-separated formatted table. * <p> * This table printer will replace any tab, line-feeds, or carriage * return control characters encountered in a cell with a single * space. */ public final class TabSeparatedTablePrinter extends TablePrinter { /** * Table serializer implementation. */ private static final class Serializer extends TableSerializer { // The current column being output. private int column = 0; // Indicates whether or not the headings should be output. private final boolean displayHeadings; // Counts the number of separators that should be output the next // time a non-empty cell is displayed. The tab separators are // not displayed immediately so that we can avoid displaying // unnecessary trailing separators. private int requiredSeparators = 0; // The output destination. private final PrintWriter writer; // Private constructor. private Serializer(PrintWriter writer, boolean displayHeadings) { this.writer = writer; this.displayHeadings = displayHeadings; } /** * {@inheritDoc} */ @Override public void addCell(String s) { // Avoid printing tab separators for trailing empty cells. if (s.length() == 0) { requiredSeparators++; } else { for (int i = 0; i < requiredSeparators; i++) { writer.print('\t'); } requiredSeparators = 1; } // Replace all new-lines and tabs with a single space. writer.print(s.replaceAll("[\\t\\n\\r]", " ")); column++; } /** * {@inheritDoc} */ @Override public void addHeading(String s) { if (displayHeadings) { addCell(s); } } /** * {@inheritDoc} */ @Override public void endHeader() { if (displayHeadings) { writer.println(); } } /** * {@inheritDoc} */ @Override public void endRow() { writer.println(); } /** * {@inheritDoc} */ @Override public void endTable() { writer.flush(); } /** * {@inheritDoc} */ @Override public void startHeader() { column = 0; requiredSeparators = 0; } /** * {@inheritDoc} */ @Override public void startRow() { column = 0; requiredSeparators = 0; } } // Indicates whether or not the headings should be output. private boolean displayHeadings = false; // The output destination. private PrintWriter writer = null; /** * Creates a new tab separated table printer for the specified * output stream. Headings will not be displayed by default. * * @param stream * The stream to output tables to. */ public TabSeparatedTablePrinter(OutputStream stream) { this(new BufferedWriter(new OutputStreamWriter(stream))); } /** * Creates a new tab separated table printer for the specified * writer. Headings will not be displayed by default. * * @param writer * The writer to output tables to. */ public TabSeparatedTablePrinter(Writer writer) { this.writer = new PrintWriter(writer); } /** * Specify whether or not table headings should be displayed. * * @param displayHeadings * <code>true</code> if table headings should be * displayed. */ public void setDisplayHeadings(boolean displayHeadings) { this.displayHeadings = displayHeadings; } /** * {@inheritDoc} */ @Override protected TableSerializer getSerializer() { return new Serializer(writer, displayHeadings); } } opends/src/server/org/opends/server/util/table/TableBuilder.java
New file @@ -0,0 +1,381 @@ /* * 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 * * * Portions Copyright 2007 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; /** * 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<String> header = new ArrayList<String>(); // 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(String.valueOf(value)); 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(""); } /** * Appends a new column heading to the header row. * * @param value * The column heading value. */ public void appendHeading(String 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 ouput the table. serializer.startTable(height, width); for (int i = 0; i < width; i++) { serializer.addColumn(columnWidths.get(i)); } // Column headings. serializer.startHeader(); for (String s : header) { serializer.addHeading(s); } 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; } } opends/src/server/org/opends/server/util/table/TablePrinter.java
New file @@ -0,0 +1,56 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.util.table; /** * An interface for incrementally configuring a table serializer. Once * configured, the table printer can be used to create a new * {@link TableSerializer} instance using the {@link #getSerializer()} * method. */ public abstract class TablePrinter { /** * Creates a new abstract table printer. */ protected TablePrinter() { // No implementation required. } /** * Creates a new table serializer based on the configuration of this * table printer. * * @return Returns a new table serializer based on the configuration * of this table printer. */ protected abstract TableSerializer getSerializer(); } opends/src/server/org/opends/server/util/table/TableSerializer.java
New file @@ -0,0 +1,160 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.util.table; /** * An interface for serializing tables. * <p> * The default implementation for each method is to do nothing. * Implementations must override methods as required. */ public abstract class TableSerializer { /** * Create a new table serializer. */ protected TableSerializer() { // No implementation required. } /** * Prints a table cell. * * @param s * The cell contents. */ public void addCell(String s) { // Default implementation. } /** * Defines a column in the table. * * @param width * The width of the column in characters. */ public void addColumn(int width) { // Default implementation. } /** * Prints a column heading. * * @param s * The column heading. */ public void addHeading(String s) { // Default implementation. } /** * Finish printing the table contents. */ public void endContent() { // Default implementation. } /** * Finish printing the column headings. */ public void endHeader() { // Default implementation. } /** * Finish printing the current row of the table. */ public void endRow() { // Default implementation. } /** * Finish printing the table. */ public void endTable() { // Default implementation. } /** * Prepare to start printing the table contents. */ public void startContent() { // Default implementation. } /** * Prepare to start printing the column headings. */ public void startHeader() { // Default implementation. } /** * Prepare to start printing a new row of the table. */ public void startRow() { // Default implementation. } /** * Start a new table having the specified number of rows and * columns. * * @param height * The number of rows in the table. * @param width * The number of columns in the table. */ public void startTable(int height, int width) { // Default implementation. } } opends/src/server/org/opends/server/util/table/TextTablePrinter.java
New file @@ -0,0 +1,531 @@ /* * 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.util.table; import static org.opends.server.util.ServerConstants.*; import java.io.BufferedWriter; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * An interface for creating a text based table. Tables have * configurable column widths, padding, and column separators. */ public final class TextTablePrinter extends TablePrinter { /** * Table serializer implementation. */ private static final class Serializer extends TableSerializer { // The current column being output. private int column = 0; // The string which should be used to separate one column // from the next (not including padding). private final String columnSeparator; // The real column widths taking into account size constraints but // not including padding or separators. private final List<Integer> columnWidths = new ArrayList<Integer>(); // The cells in the current row. private final List<String> currentRow = new ArrayList<String>(); // Indicates whether or not the headings should be output. private final boolean displayHeadings; // Table indicating whether or not a column is fixed width. private final Map<Integer, Integer> fixedColumns; // The character which should be used to separate the table // heading row from the rows beneath. private final char headingSeparator; // The padding which will be used to separate a cell's // contents from its adjacent column separators. private final int padding; // Width of the table in columns. private int totalColumns = 0; // Total permitted width for the table which expandable columns // can use up. private final int totalWidth; // The output writer. private final PrintWriter writer; // Private constructor. private Serializer(PrintWriter writer, String columnSeparator, Map<Integer, Integer> fixedColumns, boolean displayHeadings, char headingSeparator, int padding, int totalWidth) { this.writer = writer; this.columnSeparator = columnSeparator; this.fixedColumns = new HashMap<Integer, Integer>(fixedColumns); this.displayHeadings = displayHeadings; this.headingSeparator = headingSeparator; this.padding = padding; this.totalWidth = totalWidth; } /** * {@inheritDoc} */ @Override public void addCell(String s) { currentRow.add(s); column++; } /** * {@inheritDoc} */ @Override public void addColumn(int width) { columnWidths.add(width); totalColumns++; } /** * {@inheritDoc} */ @Override public void addHeading(String s) { if (displayHeadings) { addCell(s); } } /** * {@inheritDoc} */ @Override public void endHeader() { if (displayHeadings) { endRow(); // Print the header separator. StringBuilder builder = new StringBuilder(); for (int i = 0; i < totalColumns; i++) { int width = columnWidths.get(i); if (totalColumns > 1) { if (i == 0 || i == (totalColumns - 1)) { // Only one lot of padding for first and last columns. width += padding; } else { width += padding * 2; } } for (int j = 0; j < width; j++) { builder.append(headingSeparator); } if (i < (totalColumns - 1)) { builder.append(columnSeparator); } } writer.println(builder.toString()); } } /** * {@inheritDoc} */ @Override public void endRow() { boolean isRemainingText; do { isRemainingText = false; for (int i = 0; i < currentRow.size(); i++) { int width = columnWidths.get(i); String contents = currentRow.get(i); // Determine what parts of contents can be displayed on this // line. String head; String tail = null; if (contents == null) { // This cell has been displayed fully. head = ""; } else if (contents.length() > width) { // We're going to have to split the cell on next word // boundary. int endIndex = contents.lastIndexOf(' ', width); if (endIndex == -1) { // Problem - we have a word which is too big to fit in // the // cell. head = contents.substring(0, width); tail = contents.substring(width); } else { head = contents.substring(0, endIndex); tail = contents.substring(endIndex + 1); } } else { // The contents fits ok. head = contents; } // Display this line. StringBuilder builder = new StringBuilder(); if (i > 0) { // Add right padding for previous cell. for (int j = 0; j < padding; j++) { builder.append(' '); } // Add separator. builder.append(columnSeparator); // Add left padding for this cell. for (int j = 0; j < padding; j++) { builder.append(' '); } } // Add cell contents. builder.append(head); // Now pad with extra space to make up the width. for (int j = head.length(); j < width; j++) { builder.append(' '); } writer.print(builder.toString()); // Update the row contents. currentRow.set(i, tail); if (tail != null) { isRemainingText = true; } } writer.println(); } while (isRemainingText); } /** * {@inheritDoc} */ @Override public void endTable() { writer.flush(); } /** * {@inheritDoc} */ @Override public void startHeader() { determineColumnWidths(); column = 0; currentRow.clear(); } /** * {@inheritDoc} */ @Override public void startRow() { column = 0; currentRow.clear(); } // We need to calculate the effective width of each column. private void determineColumnWidths() { // First calculate the minimum width so that we know how much // expandable columns can expand. int minWidth = 0; int expandableColumnSize = 0; for (int i = 0; i < totalColumns; i++) { int actualSize = columnWidths.get(i); if (fixedColumns.containsKey(i)) { int requestedSize = fixedColumns.get(i); if (requestedSize == 0) { expandableColumnSize += actualSize; } else { columnWidths.set(i, requestedSize); minWidth += requestedSize; } } else { minWidth += actualSize; } // Must also include padding and separators. if (i > 0) { minWidth += padding * 2 + columnSeparator.length(); } } if (minWidth > totalWidth) { // The table is too big: leave expandable columns at their // requested width, as there's not much else that can be done. } else { int available = totalWidth - minWidth; if (expandableColumnSize > available) { // Only modify column sizes if necessary. for (int i = 0; i < totalColumns; i++) { int actualSize = columnWidths.get(i); if (fixedColumns.containsKey(i)) { int requestedSize = fixedColumns.get(i); if (requestedSize == 0) { // Calculate size based on requested actual size as a // proportion of the total. requestedSize = ((actualSize * available) / expandableColumnSize); columnWidths.set(i, requestedSize); } } } } } } } /** * The default string which should be used to separate one column * from the next (not including padding). */ private static final String DEFAULT_COLUMN_SEPARATOR = ""; /** * The default character which should be used to separate the table * heading row from the rows beneath. */ private static final char DEFAULT_HEADING_SEPARATOR = '-'; /** * The default padding which will be used to separate a cell's * contents from its adjacent column separators. */ private static final int DEFAULT_PADDING = 1; // The string which should be used to separate one column // from the next (not including padding). private String columnSeparator = DEFAULT_COLUMN_SEPARATOR; // Indicates whether or not the headings should be output. private boolean displayHeadings = true; // Table indicating whether or not a column is fixed width. private final Map<Integer, Integer> fixedColumns = new HashMap<Integer, Integer>(); // The character which should be used to separate the table // heading row from the rows beneath. private char headingSeparator = DEFAULT_HEADING_SEPARATOR; // The padding which will be used to separate a cell's // contents from its adjacent column separators. private int padding = DEFAULT_PADDING; // Total permitted width for the table which expandable columns // can use up. private int totalWidth = MAX_LINE_WIDTH; // The output destination. private PrintWriter writer = null; /** * Creates a new text table printer for the specified output stream. * The text table printer will have the following initial settings: * <ul> * <li>headings will be displayed * <li>no separators between columns * <li>columns are padded by one character * </ul> * * @param stream * The stream to output tables to. */ public TextTablePrinter(OutputStream stream) { this(new BufferedWriter(new OutputStreamWriter(stream))); } /** * Creates a new text table printer for the specified writer. The * text table printer will have the following initial settings: * <ul> * <li>headings will be displayed * <li>no separators between columns * <li>columns are padded by one character * </ul> * * @param writer * The writer to output tables to. */ public TextTablePrinter(Writer writer) { this.writer = new PrintWriter(writer); } /** * Sets the column separator which should be used to separate one * column from the next (not including padding). * * @param columnSeparator * The column separator. */ public final void setColumnSeparator(String columnSeparator) { this.columnSeparator = columnSeparator; } /** * Set the maximum width for a column. If a cell is too big to fit * in its column then it will be wrapped. * * @param column * The column to make fixed width (0 is the first column). * @param width * The width of the column (this should not include column * separators or padding), or <code>0</code> to indicate * that this column should be expandable. * @throws IllegalArgumentException * If column is less than 0 . */ public final void setColumnWidth(int column, int width) throws IllegalArgumentException { if (column < 0) { throw new IllegalArgumentException("Negative column " + column); } if (width < 0) { throw new IllegalArgumentException("Negative width " + width); } fixedColumns.put(column, width); } /** * Specify whether the column headings should be displayed or not. * * @param displayHeadings * <code>true</code> if column headings should be * displayed. */ public final void setDisplayHeadings(boolean displayHeadings) { this.displayHeadings = displayHeadings; } /** * Sets the heading separator which should be used to separate the * table heading row from the rows beneath. * * @param headingSeparator * The heading separator. */ public final void setHeadingSeparator(char headingSeparator) { this.headingSeparator = headingSeparator; } /** * Sets the padding which will be used to separate a cell's contents * from its adjacent column separators. * * @param padding * The padding. */ public final void setPadding(int padding) { this.padding = padding; } /** * Sets the total permitted width for the table which expandable * columns can use up. * * @param totalWidth * The total width. */ public final void setTotalWidth(int totalWidth) { this.totalWidth = totalWidth; } /** * {@inheritDoc} */ @Override protected TableSerializer getSerializer() { return new Serializer(writer, columnSeparator, fixedColumns, displayHeadings, headingSeparator, padding, totalWidth); } } opends/src/server/org/opends/server/util/table/package-info.java
New file @@ -0,0 +1,80 @@ /* * 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 * * * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ /** * Provides support for construction and display of tables in text based * applications. Applications construct tables using the {@link TableBuilder} * class and display them using on of the {@link TablePrinter} * implementations. At the moment two types of table output are supported: * <ul> * <li>{@link CSVTablePrinter} - displays a table in comma-separated * value format * <li>{@link TabSeparatedTablePrinter} - displays a table in tab separated * format * <li>{@link TextTablePrinter} - displays a table in a human-readable * format. Using this implementation it is possible to configure * constraints on column widths. The implementation will take care of * wrapping table cells where required. * </ul> * The following code illustrates the construction of a text-based table: * <pre> * TableBuilder builder = new TableBuilder(); * * builder.appendHeading("Name"); * builder.appendHeading("Age"); * builder.addSortKey(0); * * builder.startRow(); * builder.appendCell("Bob"); * builder.appendCell(11); * * builder.startRow(); * builder.appendCell("Alice"); * builder.appendCell(22); * * builder.startRow(); * builder.appendCell("Charlie"); * builder.appendCell(33); * * TextTablePrinter printer = new TextTablePrinter(System.out); * printer.setColumnSeparator(":"); * builder.print(printer); * </pre> * * Which will display the following table: * <pre> * Name : Age * --------:---- * Alice : 22 * Bob : 11 * Charlie : 33 * </pre> */ package org.opends.server.util.table;