/*
* Copyright 2010 Proofpoint, Inc.
*
* 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.
*/
package com.netflix.governator.configuration;
// copied from https://raw.github.com/proofpoint/platform/master/bootstrap/src/main/java/com/proofpoint/bootstrap/ColumnPrinter.java
import com.google.common.collect.Lists;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A utility for outputting columnar text
*/
class ColumnPrinter
{
private final List<List<String>> data = Lists.newArrayList();
private final List<String> columnNames = Lists.newArrayList();
private int margin;
private static final int DEFAULT_MARGIN = 2;
ColumnPrinter()
{
margin = DEFAULT_MARGIN;
}
/**
* Add a column
*
* @param columnName name of the column
*/
void addColumn(String columnName)
{
data.add(new ArrayList<String>());
columnNames.add(columnName);
}
/**
* Add a value to the first column with the given name
*
* @param columnName name of the column to add to
* @param value value to add
*/
void addValue(String columnName, String value)
{
addValue(columnNames.indexOf(columnName), value);
}
/**
* Add a value to the nth column
*
* @param columnIndex n
* @param value value to add
*/
void addValue(int columnIndex, String value)
{
if ( (columnIndex < 0) || (columnIndex >= data.size()) )
{
throw new IllegalArgumentException();
}
List<String> stringList = data.get(columnIndex);
stringList.add(value);
}
/**
* Change the margin from the default
*
* @param margin new margin between columns
*/
void setMargin(int margin)
{
this.margin = margin;
}
/**
* Output the columns/data
*
* @param out stream
*/
void print(PrintWriter out)
{
for ( String s : generate() )
{
out.println(s);
}
}
/**
* Generate the output as a list of string lines
*
* @return lines
*/
List<String> generate()
{
List<String> lines = Lists.newArrayList();
StringBuilder workStr = new StringBuilder();
List<AtomicInteger> columnWidths = getColumnWidths();
List<Iterator<String>> dataIterators = getDataIterators();
Iterator<AtomicInteger> columnWidthIterator = columnWidths.iterator();
for ( String columnName : columnNames )
{
int thisWidth = columnWidthIterator.next().intValue();
printValue(workStr, columnName, thisWidth);
}
pushLine(lines, workStr);
boolean done = false;
while ( !done )
{
boolean hadValue = false;
Iterator<Iterator<String>> rowIterator = dataIterators.iterator();
for ( AtomicInteger width : columnWidths )
{
Iterator<String> thisDataIterator = rowIterator.next();
if ( thisDataIterator.hasNext() )
{
hadValue = true;
String value = thisDataIterator.next();
printValue(workStr, value, width.intValue());
}
else
{
printValue(workStr, "", width.intValue());
}
}
pushLine(lines, workStr);
if ( !hadValue )
{
done = true;
}
}
return lines;
}
private void pushLine(List<String> lines, StringBuilder workStr)
{
lines.add(workStr.toString());
workStr.setLength(0);
}
private void printValue(StringBuilder str, String value, int thisWidth)
{
str.append(String.format(widthSpec(thisWidth), value));
}
private String widthSpec(int thisWidth)
{
return "%-" + (thisWidth + margin) + "s";
}
private List<Iterator<String>> getDataIterators()
{
List<Iterator<String>> dataIterators = Lists.newArrayList();
for ( List<String> valueList : data )
{
dataIterators.add(valueList.iterator());
}
return dataIterators;
}
private List<AtomicInteger> getColumnWidths()
{
List<AtomicInteger> columnWidths = Lists.newArrayList();
for ( String columnName : columnNames )
{
columnWidths.add(new AtomicInteger(columnName.length()));
}
int columnIndex = 0;
for ( List<String> valueList : data )
{
AtomicInteger width = columnWidths.get(columnIndex++);
for ( String value : valueList )
{
width.set(Math.max(value.length(), width.intValue()));
}
}
return columnWidths;
}
}