package net.sourceforge.mayfly.evaluation;
import net.sourceforge.mayfly.MayflyException;
import net.sourceforge.mayfly.MayflyInternalException;
import net.sourceforge.mayfly.datastore.Cell;
import net.sourceforge.mayfly.evaluation.select.Evaluator;
import net.sourceforge.mayfly.evaluation.what.Selected;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class GroupedRows {
private Map groups = new LinkedHashMap();
private List<Expression> keyColumns = null;
private GroupByKeys keys;
public int groupCount() {
return groups.size();
}
public void add(GroupByKeys keys, ResultRow row, Evaluator evaluator) {
ResultRow resultRow = row;
GroupByCells cells = keys.evaluate(resultRow, evaluator);
addRowToGroup(cells, resultRow);
this.keys = keys;
this.keyColumns = keys.expressions();
}
public void add(GroupByKeys keys, ResultRow row) {
add(keys, row, Evaluator.NO_SUBSELECT_NEEDED);
}
private void addRowToGroup(GroupByCells keys, ResultRow resultRow) {
ResultRows start;
if (groups.containsKey(keys)) {
start = (ResultRows) groups.get(keys);
}
else {
start = new ResultRows();
}
ResultRows modified = start.with(resultRow);
groups.put(keys, modified);
}
public Iterator iteratorForFirstKeys() {
List firstKeys = new ArrayList();
for (Iterator iter = groups.keySet().iterator(); iter.hasNext();) {
GroupByCells keys = (GroupByCells) iter.next();
firstKeys.add(keys.firstKey());
}
return firstKeys.iterator();
}
public ResultRows getRows(GroupByCells keys) {
return (ResultRows) groups.get(keys);
}
public ResultRows ungroup(Selected selected) {
ResultRows result = new ResultRows();
Iterator iter = groups.keySet().iterator();
while (iter.hasNext()) {
GroupByCells keys = (GroupByCells) iter.next();
result = result.with(
rowForKey(keys, getRows(keys), selected));
}
return result;
}
private ResultRow rowForKey(
GroupByCells cells, ResultRows rowsForKey, Selected selected) {
ResultRow result = new ResultRow();
result = addColumnsForWhat(rowsForKey, selected, result);
result = addColumnsForKeys(cells, selected, result);
return result;
}
private ResultRow addColumnsForWhat(
ResultRows rowsForKey, Selected selected, ResultRow accumulator) {
for (int i = 0; i < selected.size(); ++i) {
Expression expression = selected.element(i);
accumulator =
addColumnsForExpression(rowsForKey, expression, accumulator);
}
return accumulator;
}
private ResultRow addColumnsForExpression(
ResultRows rowsForKey, Expression expression, ResultRow accumulator) {
if (keys.containsExpresion(expression)) {
/** Just let addColumnsForKeys add it. */
}
else if (expression.firstAggregate() != null) {
Cell aggregated = expression.aggregate(rowsForKey);
accumulator = accumulator.with(expression, aggregated);
}
else {
throw new MayflyException(
expression.displayName() +
" is not aggregate or mentioned in GROUP BY"
);
}
return accumulator;
}
private ResultRow addColumnsForKeys(
GroupByCells cells, Selected selected, ResultRow accumulator) {
if (keys.keyCount() != cells.size()) {
throw new MayflyInternalException(
"have " + keyColumns.size() +
" columns but " + cells.size() + " values");
}
for (int i = 0; i < cells.size(); ++i) {
Cell cell = cells.get(i);
Expression expression = keyColumns.get(i);
accumulator = accumulator.with(expression, cell);
}
return accumulator;
}
}