All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gemstone.gemfire.management.internal.cli.result.TableBuilder Maven / Gradle / Ivy

/*
 * Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
 *
 * Licensed 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. See accompanying
 * LICENSE file.
 */
package com.gemstone.gemfire.management.internal.cli.result;

/**
 * Helper class to build rows of columnized strings & build a table from those 
 * rows.
 * 
 * Sample usage:
 * 
 * 
 *     public final Table createTable() {
 *       Table resultTable = TableBuilder.newTable();
 *       resultTable.setColumnSeparator(" | ");
 *            
 *       resultTable.newBlankRow();
 *       resultTable.newRow().newLeftCol("Displaying all fields for member: " + memberName);
 *       resultTable.newBlankRow();
 *       RowGroup rowGroup = resultTable.newRowGroup();
 *       rowGroup.newRow().newCenterCol("FIELD1").newCenterCol("FIELD2");
 *       rowGroup.newRowSeparator('-');    
 *       for (int i = 0; i < counter; i++) {
 *         rowGroup.newRow().newLeftCol(myFirstField[i]).newLeftCol(mySecondField[i]);
 *       }        
 *       resultTable.newBlankRow();
 *     
 *       return resultTable;
 *     }
 * 
 * 
 * Will result in this:
 * 
 * 
 *     
 *     Displaying all fields for member: Member1
 *     
 *         FIELD1     |     FIELD2
 *     -------------- | ---------------
 *     My First Field | My Second Field
 *     Another Fld1   | Another Fld2  
 *     Last Fld1      | Last Fld2
 *     
 * 
 * 
 * @author David Hoots
 * 
 * @since 7.0
 */
import java.util.ArrayList;
import java.util.List;

import com.gemstone.gemfire.management.internal.cli.GfshParser;

public class TableBuilder {

  public static Table newTable() {
    return new Table();
  }

  public static class Table {
    private final List rowGroups = new ArrayList();
    private String columnSeparator = "   ";

    public void setColumnSeparator(final String columnSeparator) {
      this.columnSeparator = columnSeparator;
    }

    public String getColumnSeparator() {
      return this.columnSeparator;
    }

    public RowGroup newRowGroup() {
      RowGroup rowGroup = new RowGroup(this);
      this.rowGroups.add(rowGroup);
      return rowGroup;
    }

    public Row newRow() {
      RowGroup rowGroup = newRowGroup();
      return rowGroup.newRow();
    }

    public void newBlankRow() {
      RowGroup rowGroup = newRowGroup();
      rowGroup.newBlankRow();
    }
    
    /**
     * Computes total Max Row Length across table - for all row groups.
     */
    private int getMaxLength() {
      int rowGroupMaxTotalLength = 0;
      for (RowGroup rowGroup : this.rowGroups) {
        List rows = rowGroup.rows;
        int rowGroupTotalLength = 0;
        
        int rowMaxTotalLength = 0;
        for (Row row : rows) {
          int rowTotalLength = 0;
          for (int i = 0; i < row.getNumCols(); i++) {
            rowTotalLength += row.getMaxColLength(i);
          }
          
          if (rowGroup.getColumnSeparator() != null) {
            rowTotalLength += row.getNumCols() * rowGroup.getColumnSeparator().length();
          }
          if (rowMaxTotalLength < rowTotalLength) {
            rowMaxTotalLength = rowTotalLength;
          }
        }
        
        rowGroupTotalLength += rowMaxTotalLength;
        if (rowGroupMaxTotalLength < rowGroupTotalLength) {
          rowGroupMaxTotalLength = rowGroupTotalLength;
        }
      }
      return (int)(rowGroupMaxTotalLength * 1.1);
    }

    public String buildTable() {
      StringBuffer stringBuffer = new StringBuffer();
      for (RowGroup rowGroup : this.rowGroups) {
        stringBuffer.append(rowGroup.buildRowGroup());
      }

      return stringBuffer.toString();
    }

    public List buildTableList() {
      List list = new ArrayList();
      for (RowGroup rowGroup : this.rowGroups) {
        list.add(rowGroup.buildRowGroup());
      }

      return list;
    }

    @Override
    public String toString() {
      return "Table [rowGroups=" + rowGroups + "]";
    }
  }

  /**
   * A group of rows. Widths for all columns within a group will be the same and
   * when built will automatically be set to the length of the longest value in
   * the column.
   * 
   * @author David Hoots
   * @since 7.0
   */
  public static class RowGroup {
    private final Table table;
    private final List rows = new ArrayList();
    private int[] colSizes;
    
    private String columnSeparator;

    private RowGroup(final Table table) {
      this.table = table;
    }

    private Table getTable() {
      return this.table;
    }

    public Row newRow() {
      Row row = new Row(this);
      rows.add(row);
      return row;
    }

    public void newRowSeparator(Character character, boolean isTablewideSeparator) {
      Row row = new Row(this, character, isTablewideSeparator);
      rows.add(row);
    }

    public void newBlankRow() {
      Row row = newRow();
      row.newCenterCol("");
      row.isBlank = true;
    }

    public String buildRowGroup() {
      this.colSizes = computeColSizes();

      StringBuffer stringBuffer = new StringBuffer();
      for (Row row : rows) {
        String builtRow = row.buildRow();
        stringBuffer.append(builtRow);
        if (!builtRow.trim().isEmpty() || row.isBlank) {
          stringBuffer.append(GfshParser.LINE_SEPARATOR);
        }
      }
      return stringBuffer.toString();
    }

    private int getColSize(final int colNum) {
      return this.colSizes[colNum];
    }

    private int[] computeColSizes() {
      final int[] localColSizes = new int[getNumCols()];

      for (int i = 0; i < localColSizes.length; i++) {
        localColSizes[i] = getMaxColLength(i);
      }
      return localColSizes;
    }

    private int getNumCols() {
      int maxNumCols = 0;

      for (Row row : rows) {
        int numCols = row.getNumCols();
        if (numCols > maxNumCols) {
          maxNumCols = numCols;
        }
      }

      return maxNumCols;
    }

    private int getMaxColLength(final int colNum) {
      int maxLength = 0;

      for (Row row : rows) {
        int colLength = row.getMaxColLength(colNum);
        if (colLength > maxLength) {
          maxLength = colLength;
        }
      }

      return maxLength;
    }

    public void setColumnSeparator(final String columnSeparator) {
      this.columnSeparator = columnSeparator;
    }

    public String getColumnSeparator() {
      return this.columnSeparator != null ? this.columnSeparator : table.getColumnSeparator();
    }

    @Override
    public String toString() {
      return "RowGroup [rows=" + rows + "]";
    }
  }

  public static class Row {
    private final RowGroup rowGroup;
    private final Character rowSeparator;
    private final List columns = new ArrayList();
    boolean isBlank;
    private boolean isTablewideSeparator;

    private String columnSeparator;

    private Row(final RowGroup rowGroup) {
      this.rowGroup = rowGroup;
      this.rowSeparator = null;
    }

    private Row(final RowGroup rowGroup, final Character rowSeparator, final boolean isTablewideSeparator) {
      this.rowGroup = rowGroup;
      this.rowSeparator = rowSeparator;
      this.isTablewideSeparator = isTablewideSeparator;
    }

    public Row newLeftCol(Object value) {
      Column column = new Column(value, Align.LEFT);
      this.columns.add(column);
      return this;
    }

    public Row newRightCol(Object value) {
      Column column = new Column(value, Align.RIGHT);
      this.columns.add(column);
      return this;
    }

    public Row newCenterCol(Object value) {
      Column column = new Column(value, Align.CENTER);
      this.columns.add(column);
      return this;
    }
    
    public boolean isEmpty() {
      return columns.isEmpty();
    }

    private int getNumCols() {
      return this.columns.size();
    }

    private int getMaxColLength(final int colNum) {
      if (colNum >= this.columns.size())
        return 0;

      return this.columns.get(colNum).getLength();
    }
    
    public void setColumnSeparator(final String columnSeparator) {
      this.columnSeparator = columnSeparator;
    }

    public String getColumnSeparator() {
      return this.columnSeparator != null ? this.columnSeparator : rowGroup.getColumnSeparator();
    }

    private String buildRow() {
      StringBuffer stringBuffer = new StringBuffer();
      if (this.rowSeparator != null) {
        if (isTablewideSeparator) {
          int maxColLength = this.rowGroup.getTable().getMaxLength();
          for (int j = 0; j < maxColLength; j++) {
            stringBuffer.append(this.rowSeparator);
          }
        } else {
          int maxNumCols = this.rowGroup.getNumCols();
  
          for (int i = 0; i < maxNumCols; i++) {
            int maxColLength = this.rowGroup.getMaxColLength(i);
            for (int j = 0; j < maxColLength; j++) {
              stringBuffer.append(this.rowSeparator);
            }
            if (i < (maxNumCols - 1)) {
              stringBuffer.append(this.rowGroup.getColumnSeparator());
            }
          }
        }
      } else {
// saj hook
        for (int i = 0; i < this.columns.size(); i++) {
          boolean lastColumn = !(i < (this.columns.size() - 1));
          stringBuffer.append(this.columns.get(i).buildColumn(
              this.rowGroup.getColSize(i), lastColumn));
          if (!lastColumn) {
            stringBuffer.append(getColumnSeparator());
          }
        }
      }

      return stringBuffer.toString();
    }

    @Override
    public String toString() {
      return "Row [columns=" + columns + "]";
    }
  }

  private static enum Align {
    LEFT, RIGHT, CENTER;
  };

  private static class Column {

    private final Align align;
    private final String stringValue;

    private Column(final Object value, final Align align) {
      if (value == null) {
        this.stringValue = "";
      } else {
        this.stringValue = value.toString();
      }

      this.align = align;
    }

    private int getLength() {
      return this.stringValue.length();
    }

    private String buildColumn(int colWidth, boolean trimIt) {
      
      int numSpaces = colWidth - this.stringValue.length();
      if(trimIt) numSpaces=0;
      
      StringBuffer stringBuffer = new StringBuffer();

      switch (align) {
      case LEFT:
        stringBuffer.append(stringValue);
        for (int i = 0; i < numSpaces; i++) {
          stringBuffer.append(" ");
        }
        break;
      case RIGHT:
        for (int i = 0; i < numSpaces; i++) {
          stringBuffer.append(" ");
        }
        stringBuffer.append(stringValue);
        break;
      case CENTER:
        int i = 0;
        for (; i < numSpaces / 2; i++) {
          stringBuffer.append(" ");
        }
        stringBuffer.append(stringValue);
        for (; i < numSpaces; i++) {
          stringBuffer.append(" ");
        }
        break;
      }

      return stringBuffer.toString();
      
    }
    
    private String buildColumn(int colWidth) {
      return buildColumn(colWidth, false);
    }

    @Override
    public String toString() {
      return "Column [align=" + align + ", stringValue=" + stringValue + "]";
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy