TableRow newRow = new TableRow();
for (TableCell sourceCell : sourceRow.getCells()) {
newRow.addCell(sourceCell);
}
for (ScalarFunctionColumn column : groupAndPivotScalarFunctionColumns) {
newRow.addCell(new TableCell(column.getValue(lookup, sourceRow)));
}
try {
tempTable.addRow(newRow);
} catch (TypeMismatchException e) {
// Should not happen, given that the original table is OK.
}
}
table = tempTable;
// Calculate the aggregations.
TableAggregator aggregator = new TableAggregator(groupAndPivotIds,
Sets.newHashSet(aggregationIds), table);
Set<AggregationPath> paths = aggregator.getPathsToLeaves();
// These variables will hold the "titles" of the rows and columns.
// They are TreeSets because their order matters.
SortedSet<RowTitle> rowTitles =
Sets.newTreeSet(GroupingComparators.ROW_TITLE_COMPARATOR);
SortedSet<ColumnTitle> columnTitles = Sets.newTreeSet(
GroupingComparators.getColumnTitleDynamicComparator(columnAggregations));
// A tree set containing all pivot value lists (the set is for the
// uniqueness and the tree for the order).
TreeSet<List<Value>> pivotValuesSet =
Sets.newTreeSet(GroupingComparators.VALUE_LIST_COMPARATOR);
// This MetaTable holds all the data in the table, this data is then
// dumped into the real table.
MetaTable metaTable = new MetaTable();
for (AggregationColumn columnAggregation : columnAggregations) {
for (AggregationPath path : paths) {
// A ColumnTitle is composed of all the values for the pivot-by
// columns, and a ColumnAggregation. That is why it is necessary to iterate over all
// ColumnAggregations and create a ColumnTitle for each one.
List<Value> originalValues = path.getValues();
// Separate originalValues into the rowValues and columnValues. The
// rowValues are the values of the group-by columns and the columnValues
// are the values of the pivot-by columns.
List<Value> rowValues = originalValues.subList(0, groupByIds.size());
RowTitle rowTitle = new RowTitle(rowValues);
rowTitles.add(rowTitle);
List<Value> columnValues = originalValues.subList(groupByIds.size(), originalValues.size());
pivotValuesSet.add(columnValues);
ColumnTitle columnTitle = new ColumnTitle(columnValues,
columnAggregation, (columnAggregations.size() > 1));
columnTitles.add(columnTitle);
metaTable.put(rowTitle, columnTitle, new TableCell(aggregator.getAggregationValue(path,
columnAggregation.getAggregatedColumn().getId(),
columnAggregation.getAggregationType())));
}
}
// Create the scalar function column titles for the scalar function columns
// that contain aggregations.
List<ScalarFunctionColumnTitle> scalarFunctionColumnTitles =
Lists.newArrayList();
for (ScalarFunctionColumn scalarFunctionColumn :
selectedScalarFunctionColumns) {
if (scalarFunctionColumn.getAllAggregationColumns().size() != 0) {
for (List<Value> columnValues : pivotValuesSet) {
scalarFunctionColumnTitles.add(new ScalarFunctionColumnTitle(columnValues,
scalarFunctionColumn));
}
}
}
// Create the new table description.
DataTable result = createDataTable(groupByIds, columnTitles, table, scalarFunctionColumnTitles);
List<ColumnDescription> colDescs = result.getColumnDescriptions();
// Fill the columnIndices and columnLookups parameters for the group-by
// columns and the aggregation columns.
columnIndices.clear();
int columnIndex = 0;
if (group != null) {
List<Value> empytListOfValues = Lists.newArrayList();
columnLookups.put(empytListOfValues, new GenericColumnLookup());
for (AbstractColumn column : group.getColumns()) {
columnIndices.put(column, columnIndex);
if (!(column instanceof ScalarFunctionColumn)) {
((GenericColumnLookup) columnLookups.get(empytListOfValues)).put(column, columnIndex);
for (List<Value> columnValues : pivotValuesSet) {
if (!columnLookups.containsKey(columnValues)) {
columnLookups.put(columnValues, new GenericColumnLookup());
}
((GenericColumnLookup) columnLookups.get(columnValues)).put(column, columnIndex);
}
}
columnIndex++;
}
}
for (ColumnTitle title : columnTitles) {
columnIndices.put(title.aggregation, columnIndex);
List<Value> values = title.getValues();
if (!columnLookups.containsKey(values)) {
columnLookups.put(values, new GenericColumnLookup());
}
((GenericColumnLookup) columnLookups.get(values)).put(title.aggregation, columnIndex);
columnIndex++;
}
// Dump the data from the metaTable to the result DataTable.
for (RowTitle rowTitle : rowTitles) {
TableRow curRow = new TableRow();
// Add the group-by columns cells.
for (Value v : rowTitle.values) {
curRow.addCell(new TableCell(v));
}
Map<ColumnTitle, TableCell> rowData = metaTable.getRow(rowTitle);
int i = 0;
// Add the aggregation columns cells.
for (ColumnTitle colTitle : columnTitles) {
TableCell cell = rowData.get(colTitle);
curRow.addCell((cell != null) ? cell : new TableCell(
Value.getNullValueFromValueType(colDescs.get(i + rowTitle.values.size()).getType())));
i++;
}
// Add the scalar function columns cells.
for (ScalarFunctionColumnTitle columnTitle : scalarFunctionColumnTitles) {
curRow.addCell(new TableCell(columnTitle.scalarFunctionColumn.
getValue(columnLookups.get(columnTitle.getValues()), curRow)));
}
result.addRow(curRow);
}