org.apache.hadoop.hdfs.tools.TableListing.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.hdfs.tools.TableListing.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.hdfs.tools;

import java.util.ArrayList;
import java.util.LinkedList;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.hadoop.classification.InterfaceAudience;

/**
 * This class implements a "table listing" with column headers.
 * 
 * Example:
 * 
 * NAME   OWNER   GROUP   MODE       WEIGHT
 * pool1  andrew  andrew  rwxr-xr-x     100
 * pool2  andrew  andrew  rwxr-xr-x     100
 * pool3  andrew  andrew  rwxr-xr-x     100
 * 
 */
@InterfaceAudience.Private
public class TableListing {
    public enum Justification {
        LEFT, RIGHT;
    }

    private static class Column {
        private final ArrayList<String> rows;
        private final Justification justification;
        private final boolean wrap;

        private int wrapWidth = Integer.MAX_VALUE;
        private int maxWidth;

        Column(String title, Justification justification, boolean wrap) {
            this.rows = new ArrayList<String>();
            this.justification = justification;
            this.wrap = wrap;
            this.maxWidth = 0;
            addRow(title);
        }

        private void addRow(String val) {
            if (val == null) {
                val = "";
            }
            if ((val.length() + 1) > maxWidth) {
                maxWidth = val.length() + 1;
            }
            // Ceiling at wrapWidth, because it'll get wrapped
            if (maxWidth > wrapWidth) {
                maxWidth = wrapWidth;
            }
            rows.add(val);
        }

        private int getMaxWidth() {
            return maxWidth;
        }

        private void setWrapWidth(int width) {
            wrapWidth = width;
            // Ceiling the maxLength at wrapWidth
            if (maxWidth > wrapWidth) {
                maxWidth = wrapWidth;
            }
            // Else we need to traverse through and find the real maxWidth
            else {
                maxWidth = 0;
                for (int i = 0; i < rows.size(); i++) {
                    int length = rows.get(i).length();
                    if (length > maxWidth) {
                        maxWidth = length;
                    }
                }
            }
        }

        /**
         * Return the ith row of the column as a set of wrapped strings, each at
         * most wrapWidth in length.
         */
        String[] getRow(int idx) {
            String raw = rows.get(idx);
            // Line-wrap if it's too long
            String[] lines = new String[] { raw };
            if (wrap) {
                lines = WordUtils.wrap(lines[0], wrapWidth, "\n", true).split("\n");
            }
            for (int i = 0; i < lines.length; i++) {
                if (justification == Justification.LEFT) {
                    lines[i] = StringUtils.rightPad(lines[i], maxWidth);
                } else if (justification == Justification.RIGHT) {
                    lines[i] = StringUtils.leftPad(lines[i], maxWidth);
                }
            }
            return lines;
        }
    }

    public static class Builder {
        private final LinkedList<Column> columns = new LinkedList<Column>();
        private boolean showHeader = true;
        private int wrapWidth = Integer.MAX_VALUE;

        /**
         * Create a new Builder.
         */
        public Builder() {
        }

        public Builder addField(String title) {
            return addField(title, Justification.LEFT, false);
        }

        public Builder addField(String title, Justification justification) {
            return addField(title, justification, false);
        }

        public Builder addField(String title, boolean wrap) {
            return addField(title, Justification.LEFT, wrap);
        }

        /**
         * Add a new field to the Table under construction.
         * 
         * @param title Field title.
         * @param justification Right or left justification. Defaults to left.
         * @param wrap Width at which to auto-wrap the content of the cell.
         *        Defaults to Integer.MAX_VALUE.
         * @return This Builder object
         */
        public Builder addField(String title, Justification justification, boolean wrap) {
            columns.add(new Column(title, justification, wrap));
            return this;
        }

        /**
         * Whether to hide column headers in table output
         */
        public Builder hideHeaders() {
            this.showHeader = false;
            return this;
        }

        /**
         * Whether to show column headers in table output. This is the default.
         */
        public Builder showHeaders() {
            this.showHeader = true;
            return this;
        }

        /**
         * Set the maximum width of a row in the TableListing. Must have one or
         * more wrappable fields for this to take effect.
         */
        public Builder wrapWidth(int width) {
            this.wrapWidth = width;
            return this;
        }

        /**
         * Create a new TableListing.
         */
        public TableListing build() {
            return new TableListing(columns.toArray(new Column[0]), showHeader, wrapWidth);
        }
    }

    private final Column columns[];

    private int numRows;
    private boolean showHeader;
    private int wrapWidth;

    TableListing(Column columns[], boolean showHeader, int wrapWidth) {
        this.columns = columns;
        this.numRows = 0;
        this.showHeader = showHeader;
        this.wrapWidth = wrapWidth;
    }

    /**
     * Add a new row.
     *
     * @param row    The row of objects to add-- one per column.
     */
    public void addRow(String... row) {
        if (row.length != columns.length) {
            throw new RuntimeException("trying to add a row with " + row.length + " columns, but we have "
                    + columns.length + " columns.");
        }
        for (int i = 0; i < columns.length; i++) {
            columns[i].addRow(row[i]);
        }
        numRows++;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        // Calculate the widths of each column based on their maxWidths and
        // the wrapWidth for the entire table
        int width = (columns.length - 1) * 2; // inter-column padding
        for (int i = 0; i < columns.length; i++) {
            width += columns[i].maxWidth;
        }
        // Decrease the column size of wrappable columns until the goal width
        // is reached, or we can't decrease anymore
        while (width > wrapWidth) {
            boolean modified = false;
            for (int i = 0; i < columns.length; i++) {
                Column column = columns[i];
                if (column.wrap) {
                    int maxWidth = column.getMaxWidth();
                    if (maxWidth > 4) {
                        column.setWrapWidth(maxWidth - 1);
                        modified = true;
                        width -= 1;
                        if (width <= wrapWidth) {
                            break;
                        }
                    }
                }
            }
            if (!modified) {
                break;
            }
        }

        int startrow = 0;
        if (!showHeader) {
            startrow = 1;
        }
        String[][] columnLines = new String[columns.length][];
        for (int i = startrow; i < numRows + 1; i++) {
            int maxColumnLines = 0;
            for (int j = 0; j < columns.length; j++) {
                columnLines[j] = columns[j].getRow(i);
                if (columnLines[j].length > maxColumnLines) {
                    maxColumnLines = columnLines[j].length;
                }
            }

            for (int c = 0; c < maxColumnLines; c++) {
                // First column gets no left-padding
                String prefix = "";
                for (int j = 0; j < columns.length; j++) {
                    // Prepend padding
                    builder.append(prefix);
                    prefix = " ";
                    if (columnLines[j].length > c) {
                        builder.append(columnLines[j][c]);
                    } else {
                        builder.append(StringUtils.repeat(" ", columns[j].maxWidth));
                    }
                }
                builder.append("\n");
            }
        }
        return builder.toString();
    }
}