| | |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opendj3/legal-notices/CDDLv1_0.txt |
| | | * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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/opendj3/legal-notices/CDDLv1_0.txt. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * file and include the License file at legal-notices/CDDLv1_0.txt. |
| | | * 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 |
| | |
| | | |
| | | package com.forgerock.opendj.ldap.tools; |
| | | |
| | | |
| | | |
| | | import java.util.Enumeration; |
| | | import java.util.Vector; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Utility class for printing aligned columns of text. |
| | | * <P> |
| | |
| | | * John Doe john@foo.com 456-7890 |
| | | * </PRE> |
| | | */ |
| | | final class MultiColumnPrinter |
| | | { |
| | | final class MultiColumnPrinter { |
| | | |
| | | final public static int LEFT = 0; |
| | | final public static int LEFT = 0; |
| | | |
| | | final public static int CENTER = 1; |
| | | final public static int CENTER = 1; |
| | | |
| | | final public static int RIGHT = 2; |
| | | final public static int RIGHT = 2; |
| | | |
| | | private int numCol = 2; |
| | | private int numCol = 2; |
| | | |
| | | private int gap = 4; |
| | | private int gap = 4; |
| | | |
| | | private int align = CENTER; |
| | | private int align = CENTER; |
| | | |
| | | private int titleAlign = CENTER; |
| | | private int titleAlign = CENTER; |
| | | |
| | | private String border = null; |
| | | private String border = null; |
| | | |
| | | private Vector<String[]> titleTable = null; |
| | | private Vector<String[]> titleTable = null; |
| | | |
| | | private Vector<int[]> titleSpanTable = null; |
| | | private Vector<int[]> titleSpanTable = null; |
| | | |
| | | private final int curLength[]; |
| | | private final int[] curLength; |
| | | |
| | | private final ConsoleApplication app; |
| | | private final ConsoleApplication app; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a sorted new MultiColumnPrinter class using LEFT alignment and with |
| | | * no title border. |
| | | * |
| | | * @param numCol |
| | | * number of columns |
| | | * @param gap |
| | | * gap between each column |
| | | */ |
| | | MultiColumnPrinter(final int numCol, final int gap, |
| | | final ConsoleApplication app) |
| | | { |
| | | this(numCol, gap, null, LEFT, app); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a sorted new MultiColumnPrinter class using LEFT alignment. |
| | | * |
| | | * @param numCol |
| | | * number of columns |
| | | * @param gap |
| | | * gap between each column |
| | | * @param border |
| | | * character used to frame the titles |
| | | */ |
| | | MultiColumnPrinter(final int numCol, final int gap, final String border, |
| | | final ConsoleApplication app) |
| | | { |
| | | this(numCol, gap, border, LEFT, app); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new MultiColumnPrinter class. |
| | | * |
| | | * @param numCol |
| | | * number of columns |
| | | * @param gap |
| | | * gap between each column |
| | | * @param border |
| | | * character used to frame the titles |
| | | * @param align |
| | | * type of alignment within columns |
| | | */ |
| | | MultiColumnPrinter(final int numCol, final int gap, final String border, |
| | | final int align, final ConsoleApplication app) |
| | | { |
| | | |
| | | titleTable = new Vector<String[]>(); |
| | | titleSpanTable = new Vector<int[]>(); |
| | | curLength = new int[numCol]; |
| | | |
| | | this.numCol = numCol; |
| | | this.gap = gap; |
| | | this.border = border; |
| | | this.align = align; |
| | | this.titleAlign = LEFT; |
| | | |
| | | this.app = app; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Adds to the row of strings to be used as the title for the table. |
| | | * |
| | | * @param row |
| | | * Array of strings to print in one row of title. |
| | | */ |
| | | void addTitle(final String[] row) |
| | | { |
| | | if (row == null) |
| | | { |
| | | return; |
| | | /** |
| | | * Creates a sorted new MultiColumnPrinter class using LEFT alignment and |
| | | * with no title border. |
| | | * |
| | | * @param numCol |
| | | * number of columns |
| | | * @param gap |
| | | * gap between each column |
| | | */ |
| | | MultiColumnPrinter(final int numCol, final int gap, final ConsoleApplication app) { |
| | | this(numCol, gap, null, LEFT, app); |
| | | } |
| | | |
| | | final int[] span = new int[row.length]; |
| | | for (int i = 0; i < row.length; i++) |
| | | { |
| | | span[i] = 1; |
| | | /** |
| | | * Creates a sorted new MultiColumnPrinter class using LEFT alignment. |
| | | * |
| | | * @param numCol |
| | | * number of columns |
| | | * @param gap |
| | | * gap between each column |
| | | * @param border |
| | | * character used to frame the titles |
| | | */ |
| | | MultiColumnPrinter(final int numCol, final int gap, final String border, |
| | | final ConsoleApplication app) { |
| | | this(numCol, gap, border, LEFT, app); |
| | | } |
| | | |
| | | addTitle(row, span); |
| | | } |
| | | /** |
| | | * Creates a new MultiColumnPrinter class. |
| | | * |
| | | * @param numCol |
| | | * number of columns |
| | | * @param gap |
| | | * gap between each column |
| | | * @param border |
| | | * character used to frame the titles |
| | | * @param align |
| | | * type of alignment within columns |
| | | */ |
| | | MultiColumnPrinter(final int numCol, final int gap, final String border, final int align, |
| | | final ConsoleApplication app) { |
| | | |
| | | titleTable = new Vector<String[]>(); |
| | | titleSpanTable = new Vector<int[]>(); |
| | | curLength = new int[numCol]; |
| | | |
| | | this.numCol = numCol; |
| | | this.gap = gap; |
| | | this.border = border; |
| | | this.align = align; |
| | | this.titleAlign = LEFT; |
| | | |
| | | /** |
| | | * Adds to the row of strings to be used as the title for the table. Also |
| | | * allows for certain title strings to span multiple collumns The span |
| | | * parameter is an array of integers which indicate how many collumns the |
| | | * corresponding title string will occupy. For a row that is 4 collumns wide, |
| | | * it is possible to have some title strings in a row to 'span' multiple |
| | | * collumns: |
| | | * <P> |
| | | * |
| | | * <PRE> |
| | | * ------------------------------------ |
| | | * Name Contact |
| | | * First Last Email Phone |
| | | * ------------------------------------ |
| | | * Bob Jones bob@foo.com 123-4567 |
| | | * John Doe john@foo.com 456-7890 |
| | | * </PRE> |
| | | * |
| | | * In the example above, the title row has a string 'Name' that spans 2 |
| | | * collumns. The string 'Contact' also spans 2 collumns. The above is done by |
| | | * passing in to addTitle() an array that contains: |
| | | * |
| | | * <PRE> |
| | | * span[0] = 2; // spans 2 collumns |
| | | * span[1] = 0; // spans 0 collumns, ignore |
| | | * span[2] = 2; // spans 2 collumns |
| | | * span[3] = 0; // spans 0 collumns, ignore |
| | | * </PRE> |
| | | * <P> |
| | | * A span value of 1 is the default. The method addTitle(String[] row) |
| | | * basically does: |
| | | * |
| | | * <PRE> |
| | | * int[] span = new int[row.length]; |
| | | * for (int i = 0; i < row.length; i++) |
| | | * { |
| | | * span[i] = 1; |
| | | * } |
| | | * addTitle(row, span); |
| | | * </PRE> |
| | | * |
| | | * @param row |
| | | * Array of strings to print in one row of title. |
| | | * @param span |
| | | * Array of integers that reflect the number of collumns the |
| | | * corresponding title string will occupy. |
| | | */ |
| | | void addTitle(final String[] row, final int span[]) |
| | | { |
| | | // Need to create a new instance of it, otherwise the new values |
| | | // will always overwrite the old values. |
| | | |
| | | final String[] rowInstance = new String[(row.length)]; |
| | | for (int i = 0; i < row.length; i++) |
| | | { |
| | | rowInstance[i] = row[i]; |
| | | this.app = app; |
| | | } |
| | | titleTable.addElement(rowInstance); |
| | | |
| | | titleSpanTable.addElement(span); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Clears title strings. |
| | | */ |
| | | void clearTitle() |
| | | { |
| | | titleTable.clear(); |
| | | titleSpanTable.clear(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Adds one row of text to output. |
| | | * |
| | | * @param row |
| | | * Array of strings to print in one row. |
| | | */ |
| | | void printRow(final String... row) |
| | | { |
| | | for (int i = 0; i < numCol; i++) |
| | | { |
| | | if (titleAlign == RIGHT) |
| | | { |
| | | final int spaceBefore = curLength[i] - row[i].length(); |
| | | printSpaces(spaceBefore); |
| | | app.getOutputStream().print(row[i]); |
| | | if (i < numCol - 1) |
| | | { |
| | | printSpaces(gap); |
| | | /** |
| | | * Adds to the row of strings to be used as the title for the table. |
| | | * |
| | | * @param row |
| | | * Array of strings to print in one row of title. |
| | | */ |
| | | void addTitle(final String[] row) { |
| | | if (row == null) { |
| | | return; |
| | | } |
| | | } |
| | | else if (align == CENTER) |
| | | { |
| | | int space1, space2; |
| | | space1 = (curLength[i] - row[i].length()) / 2; |
| | | space2 = curLength[i] - row[i].length() - space1; |
| | | |
| | | printSpaces(space1); |
| | | app.getOutputStream().print(row[i]); |
| | | printSpaces(space2); |
| | | if (i < numCol - 1) |
| | | { |
| | | printSpaces(gap); |
| | | final int[] span = new int[row.length]; |
| | | for (int i = 0; i < row.length; i++) { |
| | | span[i] = 1; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | app.getOutputStream().print(row[i]); |
| | | if (i < numCol - 1) |
| | | { |
| | | printSpaces(curLength[i] - row[i].length() + gap); |
| | | } |
| | | } |
| | | |
| | | addTitle(row, span); |
| | | } |
| | | app.getOutputStream().println(""); |
| | | } |
| | | |
| | | /** |
| | | * Adds to the row of strings to be used as the title for the table. Also |
| | | * allows for certain title strings to span multiple collumns The span |
| | | * parameter is an array of integers which indicate how many collumns the |
| | | * corresponding title string will occupy. For a row that is 4 collumns |
| | | * wide, it is possible to have some title strings in a row to 'span' |
| | | * multiple collumns: |
| | | * <P> |
| | | * |
| | | * <PRE> |
| | | * ------------------------------------ |
| | | * Name Contact |
| | | * First Last Email Phone |
| | | * ------------------------------------ |
| | | * Bob Jones bob@foo.com 123-4567 |
| | | * John Doe john@foo.com 456-7890 |
| | | * </PRE> |
| | | * |
| | | * In the example above, the title row has a string 'Name' that spans 2 |
| | | * collumns. The string 'Contact' also spans 2 collumns. The above is done |
| | | * by passing in to addTitle() an array that contains: |
| | | * |
| | | * <PRE> |
| | | * span[0] = 2; // spans 2 collumns |
| | | * span[1] = 0; // spans 0 collumns, ignore |
| | | * span[2] = 2; // spans 2 collumns |
| | | * span[3] = 0; // spans 0 collumns, ignore |
| | | * </PRE> |
| | | * <P> |
| | | * A span value of 1 is the default. The method addTitle(String[] row) |
| | | * basically does: |
| | | * |
| | | * <PRE> |
| | | * int[] span = new int[row.length]; |
| | | * for (int i = 0; i < row.length; i++) { |
| | | * span[i] = 1; |
| | | * } |
| | | * addTitle(row, span); |
| | | * </PRE> |
| | | * |
| | | * @param row |
| | | * Array of strings to print in one row of title. |
| | | * @param span |
| | | * Array of integers that reflect the number of collumns the |
| | | * corresponding title string will occupy. |
| | | */ |
| | | void addTitle(final String[] row, final int[] span) { |
| | | // Need to create a new instance of it, otherwise the new values |
| | | // will always overwrite the old values. |
| | | |
| | | |
| | | /** |
| | | * Prints the table title |
| | | */ |
| | | void printTitle() |
| | | { |
| | | // Get the longest string for each column and store in curLength[] |
| | | |
| | | // Scan through title rows |
| | | Enumeration<String[]> elm = titleTable.elements(); |
| | | Enumeration<int[]> spanEnum = titleSpanTable.elements(); |
| | | while (elm.hasMoreElements()) |
| | | { |
| | | final String[] row = elm.nextElement(); |
| | | final int[] curSpan = spanEnum.nextElement(); |
| | | |
| | | for (int i = 0; i < numCol; i++) |
| | | { |
| | | // None of the fields should be null, but if it |
| | | // happens to be so, replace it with "-". |
| | | if (row[i] == null) |
| | | { |
| | | row[i] = "-"; |
| | | final String[] rowInstance = new String[(row.length)]; |
| | | for (int i = 0; i < row.length; i++) { |
| | | rowInstance[i] = row[i]; |
| | | } |
| | | titleTable.addElement(rowInstance); |
| | | |
| | | int len = row[i].length(); |
| | | titleSpanTable.addElement(span); |
| | | } |
| | | |
| | | /* |
| | | * If a title string spans multiple collumns, then the space it occupies |
| | | * in each collumn is at most len/span (since we have gap to take into |
| | | * account as well). |
| | | */ |
| | | final int span = curSpan[i]; |
| | | int rem = 0; |
| | | if (span > 1) |
| | | { |
| | | rem = len % span; |
| | | len = len / span; |
| | | } |
| | | /** |
| | | * Clears title strings. |
| | | */ |
| | | void clearTitle() { |
| | | titleTable.clear(); |
| | | titleSpanTable.clear(); |
| | | } |
| | | |
| | | if (curLength[i] < len) |
| | | { |
| | | curLength[i] = len; |
| | | /** |
| | | * Adds one row of text to output. |
| | | * |
| | | * @param row |
| | | * Array of strings to print in one row. |
| | | */ |
| | | void printRow(final String... row) { |
| | | for (int i = 0; i < numCol; i++) { |
| | | if (titleAlign == RIGHT) { |
| | | final int spaceBefore = curLength[i] - row[i].length(); |
| | | printSpaces(spaceBefore); |
| | | app.getOutputStream().print(row[i]); |
| | | if (i < numCol - 1) { |
| | | printSpaces(gap); |
| | | } |
| | | } else if (align == CENTER) { |
| | | int space1, space2; |
| | | space1 = (curLength[i] - row[i].length()) / 2; |
| | | space2 = curLength[i] - row[i].length() - space1; |
| | | |
| | | if ((span > 1) && ((i + span) <= numCol)) |
| | | { |
| | | for (int j = i + 1; j < (i + span); ++j) |
| | | { |
| | | curLength[j] = len; |
| | | printSpaces(space1); |
| | | app.getOutputStream().print(row[i]); |
| | | printSpaces(space2); |
| | | if (i < numCol - 1) { |
| | | printSpaces(gap); |
| | | } |
| | | } else { |
| | | app.getOutputStream().print(row[i]); |
| | | if (i < numCol - 1) { |
| | | printSpaces(curLength[i] - row[i].length() + gap); |
| | | } |
| | | } |
| | | |
| | | /* |
| | | * Add remainder to last collumn in span to avoid round-off errors. |
| | | */ |
| | | curLength[(i + span) - 1] += rem; |
| | | } |
| | | } |
| | | } |
| | | app.getOutputStream().println(""); |
| | | } |
| | | |
| | | printBorder(); |
| | | elm = titleTable.elements(); |
| | | spanEnum = titleSpanTable.elements(); |
| | | /** |
| | | * Prints the table title. |
| | | */ |
| | | void printTitle() { |
| | | // Get the longest string for each column and store in curLength[] |
| | | |
| | | while (elm.hasMoreElements()) |
| | | { |
| | | final String[] row = elm.nextElement(); |
| | | final int[] curSpan = spanEnum.nextElement(); |
| | | // Scan through title rows |
| | | Enumeration<String[]> elm = titleTable.elements(); |
| | | Enumeration<int[]> spanEnum = titleSpanTable.elements(); |
| | | while (elm.hasMoreElements()) { |
| | | final String[] row = elm.nextElement(); |
| | | final int[] curSpan = spanEnum.nextElement(); |
| | | |
| | | for (int i = 0; i < numCol; i++) |
| | | { |
| | | int availableSpace = 0; |
| | | final int span = curSpan[i]; |
| | | for (int i = 0; i < numCol; i++) { |
| | | // None of the fields should be null, but if it |
| | | // happens to be so, replace it with "-". |
| | | if (row[i] == null) { |
| | | row[i] = "-"; |
| | | } |
| | | |
| | | if (span == 0) |
| | | { |
| | | continue; |
| | | int len = row[i].length(); |
| | | |
| | | /* |
| | | * If a title string spans multiple collumns, then the space it |
| | | * occupies in each collumn is at most len/span (since we have |
| | | * gap to take into account as well). |
| | | */ |
| | | final int span = curSpan[i]; |
| | | int rem = 0; |
| | | if (span > 1) { |
| | | rem = len % span; |
| | | len = len / span; |
| | | } |
| | | |
| | | if (curLength[i] < len) { |
| | | curLength[i] = len; |
| | | |
| | | if ((span > 1) && ((i + span) <= numCol)) { |
| | | for (int j = i + 1; j < (i + span); ++j) { |
| | | curLength[j] = len; |
| | | } |
| | | |
| | | /* |
| | | * Add remainder to last collumn in span to avoid |
| | | * round-off errors. |
| | | */ |
| | | curLength[(i + span) - 1] += rem; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | availableSpace = curLength[i]; |
| | | printBorder(); |
| | | elm = titleTable.elements(); |
| | | spanEnum = titleSpanTable.elements(); |
| | | |
| | | if ((span > 1) && ((i + span) <= numCol)) |
| | | { |
| | | for (int j = i + 1; j < (i + span); ++j) |
| | | { |
| | | availableSpace += gap; |
| | | availableSpace += curLength[j]; |
| | | } |
| | | while (elm.hasMoreElements()) { |
| | | final String[] row = elm.nextElement(); |
| | | final int[] curSpan = spanEnum.nextElement(); |
| | | |
| | | for (int i = 0; i < numCol; i++) { |
| | | int availableSpace = 0; |
| | | final int span = curSpan[i]; |
| | | |
| | | if (span == 0) { |
| | | continue; |
| | | } |
| | | |
| | | availableSpace = curLength[i]; |
| | | |
| | | if ((span > 1) && ((i + span) <= numCol)) { |
| | | for (int j = i + 1; j < (i + span); ++j) { |
| | | availableSpace += gap; |
| | | availableSpace += curLength[j]; |
| | | } |
| | | } |
| | | |
| | | if (titleAlign == RIGHT) { |
| | | final int spaceBefore = availableSpace - row[i].length(); |
| | | printSpaces(spaceBefore); |
| | | app.getOutputStream().print(row[i]); |
| | | if (i < numCol - 1) { |
| | | printSpaces(gap); |
| | | } |
| | | } else if (titleAlign == CENTER) { |
| | | int spaceBefore, spaceAfter; |
| | | spaceBefore = (availableSpace - row[i].length()) / 2; |
| | | spaceAfter = availableSpace - row[i].length() - spaceBefore; |
| | | |
| | | printSpaces(spaceBefore); |
| | | app.getOutputStream().print(row[i]); |
| | | printSpaces(spaceAfter); |
| | | if (i < numCol - 1) { |
| | | printSpaces(gap); |
| | | } |
| | | } else { |
| | | app.getOutputStream().print(row[i]); |
| | | if (i < numCol - 1) { |
| | | printSpaces(availableSpace - row[i].length() + gap); |
| | | } |
| | | } |
| | | |
| | | } |
| | | app.getOutputStream().println(""); |
| | | } |
| | | printBorder(); |
| | | } |
| | | |
| | | /** |
| | | * Set alignment for title strings. |
| | | * |
| | | * @param titleAlign |
| | | */ |
| | | void setTitleAlign(final int titleAlign) { |
| | | this.titleAlign = titleAlign; |
| | | } |
| | | |
| | | private void printBorder() { |
| | | if (border == null) { |
| | | return; |
| | | } |
| | | |
| | | if (titleAlign == RIGHT) |
| | | { |
| | | final int spaceBefore = availableSpace - row[i].length(); |
| | | printSpaces(spaceBefore); |
| | | app.getOutputStream().print(row[i]); |
| | | if (i < numCol - 1) |
| | | { |
| | | printSpaces(gap); |
| | | } |
| | | } |
| | | else if (titleAlign == CENTER) |
| | | { |
| | | int spaceBefore, spaceAfter; |
| | | spaceBefore = (availableSpace - row[i].length()) / 2; |
| | | spaceAfter = availableSpace - row[i].length() - spaceBefore; |
| | | |
| | | printSpaces(spaceBefore); |
| | | app.getOutputStream().print(row[i]); |
| | | printSpaces(spaceAfter); |
| | | if (i < numCol - 1) |
| | | { |
| | | printSpaces(gap); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | app.getOutputStream().print(row[i]); |
| | | if (i < numCol - 1) |
| | | { |
| | | printSpaces(availableSpace - row[i].length() + gap); |
| | | } |
| | | // For the value in each column |
| | | for (int i = 0; i < numCol; i++) { |
| | | for (int j = 0; j < curLength[i]; j++) { |
| | | app.getOutputStream().print(border); |
| | | } |
| | | } |
| | | |
| | | } |
| | | app.getOutputStream().println(""); |
| | | } |
| | | printBorder(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Set alignment for title strings |
| | | * |
| | | * @param titleAlign |
| | | */ |
| | | void setTitleAlign(final int titleAlign) |
| | | { |
| | | this.titleAlign = titleAlign; |
| | | } |
| | | |
| | | |
| | | |
| | | private void printBorder() |
| | | { |
| | | if (border == null) |
| | | { |
| | | return; |
| | | // For the gap between each column |
| | | for (int i = 0; i < numCol - 1; i++) { |
| | | for (int j = 0; j < gap; j++) { |
| | | app.getOutputStream().print(border); |
| | | } |
| | | } |
| | | app.getOutputStream().println(""); |
| | | } |
| | | |
| | | // For the value in each column |
| | | for (int i = 0; i < numCol; i++) |
| | | { |
| | | for (int j = 0; j < curLength[i]; j++) |
| | | { |
| | | app.getOutputStream().print(border); |
| | | } |
| | | private void printSpaces(final int count) { |
| | | for (int i = 0; i < count; ++i) { |
| | | app.getOutputStream().print(" "); |
| | | } |
| | | } |
| | | |
| | | // For the gap between each column |
| | | for (int i = 0; i < numCol - 1; i++) |
| | | { |
| | | for (int j = 0; j < gap; j++) |
| | | { |
| | | app.getOutputStream().print(border); |
| | | } |
| | | } |
| | | app.getOutputStream().println(""); |
| | | } |
| | | |
| | | |
| | | |
| | | private void printSpaces(final int count) |
| | | { |
| | | for (int i = 0; i < count; ++i) |
| | | { |
| | | app.getOutputStream().print(" "); |
| | | } |
| | | } |
| | | } |