package com.tinkerpop.pipes.util.structures; import com.tinkerpop.pipes.PipeFunction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * A Table is a collection of rows with various table-style access methods. * * @author Marko A. Rodriguez (http://markorodriguez.com) */ public class Table extends ArrayList<Row> { private List<String> columnNames; private int tableWidth = -1; public Table() { this.columnNames = new ArrayList<String>(); } public Table(final String... columnNames) { this(); this.columnNames.addAll(Arrays.asList(columnNames)); this.tableWidth = columnNames.length; } public Table apply(final PipeFunction... functions) { Table table = new Table(); for (final Row row : this) { List temp = new ArrayList(); for (int i = 0; i < row.size(); i++) { temp.add(functions[i % functions.length].compute(row.get(i))); } table.addRow(temp); } return table; } public void addRow(final List row) { if (this.tableWidth == -1) { this.tableWidth = row.size(); } else { if (row.size() != tableWidth) { throw new RuntimeException("Table width is " + this.tableWidth + " and row width is " + row.size()); } } this.add(new Row(row, this.getColumnNames())); } public void addRow(final Object... row) { this.addRow(Arrays.asList(row)); } public void setColumnNames(final String... columnNames) { if (tableWidth != -1 && columnNames.length != tableWidth) { throw new RuntimeException("Table width is " + this.tableWidth + " and there are " + columnNames.length + " column names"); } this.columnNames.clear(); this.columnNames.addAll(Arrays.asList(columnNames)); this.tableWidth = this.columnNames.size(); } public List<String> getColumnNames() { return this.columnNames; } public int getRowCount() { return this.size(); } public int getColumnCount() { return tableWidth; } public Object get(final int row, final int column) { return this.get(row).get(column); } public Object get(final int row, final String columnName) { return this.get(row).get(this.columnNames.indexOf(columnName)); } public Row getRow(final int row) { return this.get(row); } public List getColumn(final int column) { final List temp = new ArrayList(); for (final Row row : this) { temp.add(row.get(column)); } return temp; } public List getColumn(final String columnName) { return this.getColumn(this.columnNames.indexOf(columnName)); } /** * Filter out duplicates according to a default comparator * * @return a newly created table with unique rows */ public Table unique() { final Table temp = Table.cloneTableStructure(this); final SortedSet<Row> set = new TreeSet<Row>(Table.getDefaultRowComparator()); for (final Row row : this) { set.add(row); } for (final Row row : set) { temp.addRow(row); } return temp; } /** * Filter out duplicates according to the provided comparator * * @param comparator a row comparator * @return a newly created table with unique rows */ public Table unique(final Comparator<Row> comparator) { final Table temp = Table.cloneTableStructure(this); final SortedSet<Row> set = new TreeSet<Row>(comparator); for (final Row row : this) { set.add(row); } for (final Row row : set) { temp.addRow(row); } return temp; } /** * Sort the rows of the table according to a default comparator * * @return a newly created sorted table */ public Table sort() { final Table temp = Table.cloneTableStructure(this); final List<Row> rows = new ArrayList<Row>(); for (final Row row : this) { rows.add(row); } Collections.sort(rows, Table.getDefaultRowComparator()); temp.addAll(rows); return temp; } /** * Sort the rows of the table according to provided comparator * * @param comparator a row comparator * @return a newly created sorted table */ public Table sort(Comparator<Row> comparator) { final Table temp = Table.cloneTableStructure(this); final List<Row> rows = new ArrayList<Row>(); for (final Row row : this) { rows.add(row); } Collections.sort(rows, comparator); temp.addAll(rows); return temp; } /** * Create a new table with the same column names as provided table * * @param table a table * @return a new table with same column names */ public static Table cloneTableStructure(final Table table) { if (table.getColumnNames().size() > 0) return new Table(table.columnNames.toArray(new String[table.columnNames.size()])); else return new Table(); } public void clear() { super.clear(); this.tableWidth = -1; this.columnNames = new ArrayList<String>(); } private static Comparator<Row> getDefaultRowComparator() { return new Comparator<Row>() { @Override public int compare(final Row a, final Row b) { int comp = 0; for (int i = 0; i < a.size(); i++) { comp = comp + ((Comparable) a.get(i)).compareTo(b.get(i)); } return comp; } }; } }