class PivotTable {

  public static Table pivot(
      Table table,
      CategoricalColumn<?> column1,
      CategoricalColumn<?> column2,
      NumericColumn<?> values,
      AggregateFunction<?, ?> aggregateFunction) {

    TableSliceGroup tsg = table.splitOn(column1);

    Table pivotTable = Table.create("Pivot: " + column1.name() + " x " + column2.name());
    pivotTable.addColumns(column1.type().create(column1.name()));

    List<String> valueColumnNames = getValueColumnNames(table, column2);

    for (String colName : valueColumnNames) {
      pivotTable.addColumns(DoubleColumn.create(colName));
    }

    int valueIndex = table.columnIndex(column2);
    int keyIndex = table.columnIndex(column1);

    String key;

    for (TableSlice slice : tsg.getSlices()) {
      key = String.valueOf(slice.get(0, keyIndex));
      pivotTable.column(0).appendCell(key);

      Map<String, Double> valueMap =
          getValueMap(column1, column2, values, valueIndex, slice, aggregateFunction);

      for (String columnName : valueColumnNames) {
        Double aDouble = valueMap.get(columnName);
        NumericColumn<?> pivotValueColumn = pivotTable.numberColumn(columnName);
        if (aDouble == null) {
          pivotValueColumn.appendMissing();
        } else {
          pivotValueColumn.appendObj(aDouble);
        }
      }
    }

    return pivotTable;
  }

}