final Row inputRow = dataSet.getRow();
for (SelectItem item : functionItems) {
final AggregateBuilder<?> aggregateBuilder = aggregateBuilders.get(item);
final Column column = item.getColumn();
if (column != null) {
Object value = inputRow.getValue(new SelectItem(column));
aggregateBuilder.add(value);
} else if (SelectItem.isCountAllItem(item)) {
// Just use the empty string, since COUNT(*) don't
// evaluate values (but null values should be prevented)
aggregateBuilder.add("");
} else {
throw new IllegalArgumentException("Expression function not supported: " + item);
}
}
// If the result should also contain non-aggregated values, we
// will keep those in the rows list
if (!onlyAggregates) {
final Object[] values = new Object[header.size()];
for (int i = 0; i < header.size(); i++) {
final Object value = inputRow.getValue(header.getSelectItem(i));
if (value != null) {
values[i] = value;
}
}
resultRows.add(new DefaultRow(header, values));
}
}
dataSet.close();
// Collect the aggregates
Map<SelectItem, Object> functionResult = new HashMap<SelectItem, Object>();
for (SelectItem item : functionItems) {
AggregateBuilder<?> aggregateBuilder = aggregateBuilders.get(item);
Object result = aggregateBuilder.getAggregate();
functionResult.put(item, result);
}
// if there are no result rows (no matching records at all), we still
// need to return a record with the aggregates
final boolean noResultRows = resultRows.isEmpty();
if (onlyAggregates || noResultRows) {
// We will only create a single row with all the aggregates
Object[] values = new Object[header.size()];
for (int i = 0; i < header.size(); i++) {
values[i] = functionResult.get(header.getSelectItem(i));
}
Row row = new DefaultRow(header, values);
resultRows.add(row);
} else {
// We will create the aggregates as well as regular values
for (int i = 0; i < resultRows.size(); i++) {
Row row = resultRows.get(i);
Object[] values = row.getValues();
for (Entry<SelectItem, Object> entry : functionResult.entrySet()) {
SelectItem item = entry.getKey();
int itemIndex = row.indexOf(item);
if (itemIndex != -1) {
Object value = entry.getValue();
values[itemIndex] = value;
}