package cosmos.sql.console;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map.Entry;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import cosmos.records.values.RecordValue;
import cosmos.results.Column;
public class TableOutputFormat {
public static final String COLUMN_SEPARATOR = "|", CORNER = "+", SPACE = " ", HYPHEN = "-", NEWLINE = "\n";
public void print(ResultSet results, Stopwatch timer) throws SQLException {
final ResultSetMetaData metadata = results.getMetaData();
final int columnCount = metadata.getColumnCount();
List<String> columns = Lists.newArrayListWithExpectedSize(columnCount);
List<Integer> columnWidths = Lists.newArrayListWithExpectedSize(columnCount);
for (int i = 1; i <= columnCount; i++) {
String columnName = metadata.getColumnName(i);
columns.add(columnName);
// Account for padding
columnWidths.add(Math.max(8, columnName.length()));
}
final StringBuilder line = new StringBuilder(1024);
final StringBuilder sb = new StringBuilder(256);
long linesWritten = 0;
while (results.next()) {
for (int i = 0; i < columns.size(); i++) {
String column = columns.get(i);
List<Entry<Column,RecordValue>> sValues = (List<Entry<Column,RecordValue>>) results.getObject(column);
if (null != sValues && !sValues.isEmpty()) {
for (Entry<Column,RecordValue> values : sValues) {
sb.append(values.getValue().toString());
}
}
if (columnWidths.get(i) < sb.length()) {
columnWidths.set(i, sb.length());
} else {
padColumnValueToWidth(sb, columnWidths.get(i));
}
if (0 == i) {
line.append(COLUMN_SEPARATOR);
}
line.append(padColumnValue(sb)).append(COLUMN_SEPARATOR);
sb.setLength(0);
}
if (0 == linesWritten) {
for (Integer columnWidth : columnWidths) {
sb.append(CORNER);
// +2 to account for the space we place around the "fixed" width of the column
// done in {@link #padColumnValue(StringBuilder)}
for (int i = 0; i < columnWidth + 2; i++) {
sb.append(HYPHEN);
}
}
sb.append(CORNER).append(NEWLINE);
sb.append(COLUMN_SEPARATOR);
for (int i = 0; i < columns.size(); i++) {
String column = columns.get(i);
StringBuilder columnHeader = padColumnValueToWidth(column, columnWidths.get(i));
padColumnValue(columnHeader).append(COLUMN_SEPARATOR);
sb.append(columnHeader);
}
sb.append(NEWLINE);
for (Integer columnWidth : columnWidths) {
sb.append(CORNER);
// +2 to account for the space we place around the "fixed" width of the column
// done in {@link #padColumnValue(StringBuilder)}
for (int i = 0; i < columnWidth + 2; i++) {
sb.append(HYPHEN);
}
}
sb.append(CORNER).append(NEWLINE);
line.insert(0, sb.toString());
sb.setLength(0);
}
System.out.println(line);
line.setLength(0);
linesWritten++;
}
timer.stop();
for (Integer columnWidth : columnWidths) {
line.append(CORNER);
// +2 to account for the space we place around the "fixed" width of the column
// done in {@link #padColumnValue(StringBuilder)}
for (int i = 0; i < columnWidth + 2; i++) {
line.append(HYPHEN);
}
}
line.append(CORNER);
System.out.println(line);
System.out.println(linesWritten + " rows in set (" + timer + ")\n");
return;
}
protected StringBuilder padColumnValue(StringBuilder columnValue) {
return columnValue.append(SPACE).insert(0, SPACE);
}
protected StringBuilder padColumnValueToWidth(String columnValue, int width) {
return padColumnValueToWidth(new StringBuilder(columnValue), width);
}
protected StringBuilder padColumnValueToWidth(StringBuilder columnValue, int width) {
int charsToAdd = width - columnValue.length();
for (int i = 0; i < charsToAdd; i++) {
columnValue.append(SPACE);
}
return columnValue;
}
}