/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
***************************************************************************************
*/
package com.espertech.esper.epl.agg.rollup;
import com.espertech.esper.collection.NumberAscCombinationEnumeration;
import com.espertech.esper.util.CollectionUtil;
import java.util.*;
public class GroupByRollupNodeRollupOrCube extends GroupByRollupNodeBase {
private final boolean cube;
public GroupByRollupNodeRollupOrCube(boolean cube) {
this.cube = cube;
}
public List<int[]> evaluate(GroupByRollupEvalContext context) throws GroupByRollupDuplicateException {
int[][] childIndexes = evaluateChildNodes(context);
// find duplicate entries among child expressions
for (int i = 0; i < childIndexes.length; i++) {
for (int j = i + 1; j < childIndexes.length; j++) {
validateCompare(childIndexes[i], childIndexes[j]);
}
}
List<int[]> rollup;
if (cube) {
rollup = handleCube(childIndexes);
} else {
rollup = handleRollup(childIndexes);
}
rollup.add(new int[0]);
return rollup;
}
private static void validateCompare(int[] one, int[] other) throws GroupByRollupDuplicateException {
if (Arrays.equals(one, other)) {
throw new GroupByRollupDuplicateException(one);
}
}
private List<int[]> handleCube(int[][] childIndexes) {
List<int[]> enumerationSorted = new ArrayList<int[]>();
int size = getChildNodes().size();
NumberAscCombinationEnumeration e = new NumberAscCombinationEnumeration(size);
for (; e.hasMoreElements(); ) {
enumerationSorted.add(e.nextElement());
}
Collections.sort(enumerationSorted, new Comparator<int[]>() {
public int compare(int[] o1, int[] o2) {
int shared = Math.min(o1.length, o2.length);
for (int i = 0; i < shared; i++) {
if (o1[i] < o2[i]) {
return -1;
}
if (o1[i] > o2[i]) {
return 1;
}
}
if (o1.length > o2.length) {
return -1;
}
if (o1.length < o2.length) {
return 1;
}
return 0;
}
});
List<int[]> rollup = new ArrayList<int[]>(enumerationSorted.size() + 1);
Set<Integer> keys = new LinkedHashSet<Integer>();
for (int[] item : enumerationSorted) {
keys.clear();
for (int index : item) {
int[] childIndex = childIndexes[index];
for (int childIndexItem : childIndex) {
keys.add(childIndexItem);
}
}
rollup.add(CollectionUtil.intArray(keys));
}
return rollup;
}
private List<int[]> handleRollup(int[][] childIndexes) {
int size = getChildNodes().size();
List<int[]> rollup = new ArrayList<int[]>(size + 1);
Set<Integer> keyset = new LinkedHashSet<Integer>();
for (int i = 0; i < size; i++) {
keyset.clear();
for (int j = 0; j < size - i; j++) {
int[] childIndex = childIndexes[j];
for (int aChildIndex : childIndex) {
keyset.add(aChildIndex);
}
}
rollup.add(CollectionUtil.intArray(keyset));
}
return rollup;
}
private int[][] evaluateChildNodes(GroupByRollupEvalContext context) throws GroupByRollupDuplicateException {
int size = getChildNodes().size();
int[][] childIndexes = new int[size][];
for (int i = 0; i < size; i++) {
List<int[]> childIndex = getChildNodes().get(i).evaluate(context);
if (childIndex.size() != 1) {
throw new IllegalStateException();
}
childIndexes[i] = childIndex.get(0);
}
return childIndexes;
}
}