final SelectItem[] groupBySelects = new SelectItem[groupByItems.length];
for (int i = 0; i < groupBySelects.length; i++) {
groupBySelects[i] = groupByItems[i].getSelectItem();
}
final DataSetHeader groupByHeader = new CachingDataSetHeader(groupBySelects);
// Creates a list of SelectItems that have functions
List<SelectItem> functionItems = getFunctionSelectItems(selectItems);
// Loop through the dataset and identify groups
while (dataSet.next()) {
Row row = dataSet.getRow();
// Subselect a row prototype with only the unique values that
// define the group
Row uniqueRow = row.getSubSelection(groupByHeader);
// function input is the values used for calculating aggregate
// functions in the group
Map<SelectItem, List<Object>> functionInput;
if (!uniqueRows.containsKey(uniqueRow)) {
// If this group already exist, use an existing function
// input
functionInput = new HashMap<SelectItem, List<Object>>();
for (SelectItem item : functionItems) {
functionInput.put(item, new ArrayList<Object>());
}
uniqueRows.put(uniqueRow, functionInput);
} else {
// If this is a new group, create a new function input
functionInput = uniqueRows.get(uniqueRow);
}
// Loop through aggregate functions to check for validity
for (SelectItem item : functionItems) {
List<Object> objects = functionInput.get(item);
Column column = item.getColumn();
if (column != null) {
Object value = row.getValue(new SelectItem(column));
objects.add(value);
} else if (SelectItem.isCountAllItem(item)) {
// Just use the empty string, since COUNT(*) don't
// evaluate values (but null values should be prevented)
objects.add("");
} else {
throw new IllegalArgumentException("Expression function not supported: " + item);
}
}
}
dataSet.close();
final List<Row> resultData = new ArrayList<Row>();
final DataSetHeader resultHeader = new CachingDataSetHeader(selectItems);
// Loop through the groups to generate aggregates
for (Entry<Row, Map<SelectItem, List<Object>>> entry : uniqueRows.entrySet()) {
Row row = entry.getKey();
Map<SelectItem, List<Object>> functionInput = entry.getValue();