/*
***************************************************************************************
* 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.service;
import com.espertech.esper.epl.agg.access.AggregationAccessor;
import com.espertech.esper.epl.agg.access.AggregationAccessorSlotPair;
import com.espertech.esper.epl.agg.access.AggregationStateKey;
import com.espertech.esper.epl.expression.baseagg.ExprAggregateLocalGroupByDesc;
import com.espertech.esper.epl.expression.baseagg.ExprAggregateNode;
import com.espertech.esper.epl.expression.core.ExprNodeUtility;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
public class AggregationMultiFunctionAnalysisHelper {
// handle accessor aggregation (direct data window by-group access to properties)
public static AggregationMultiFunctionAnalysisResult analyzeAccessAggregations(List<AggregationServiceAggExpressionDesc> aggregations) {
int currentSlot = 0;
Deque<AggregationMFIdentifier> accessProviderSlots = new ArrayDeque<AggregationMFIdentifier>();
List<AggregationAccessorSlotPair> accessorPairs = new ArrayList<AggregationAccessorSlotPair>();
List<AggregationStateFactory> stateFactories = new ArrayList<AggregationStateFactory>();
for (AggregationServiceAggExpressionDesc aggregation : aggregations) {
ExprAggregateNode aggregateNode = aggregation.getAggregationNode();
if (!aggregateNode.getFactory().isAccessAggregation()) {
continue;
}
AggregationStateKey providerKey = aggregateNode.getFactory().getAggregationStateKey(false);
AggregationMFIdentifier existing = findExisting(accessProviderSlots, providerKey, aggregateNode.getOptionalLocalGroupBy());
int slot;
if (existing == null) {
accessProviderSlots.add(new AggregationMFIdentifier(providerKey, aggregateNode.getOptionalLocalGroupBy(), currentSlot));
slot = currentSlot++;
AggregationStateFactory providerFactory = aggregateNode.getFactory().getAggregationStateFactory(false);
stateFactories.add(providerFactory);
} else {
slot = existing.getSlot();
}
AggregationAccessor accessor = aggregateNode.getFactory().getAccessor();
accessorPairs.add(new AggregationAccessorSlotPair(slot, accessor));
}
AggregationAccessorSlotPair[] pairs = accessorPairs.toArray(new AggregationAccessorSlotPair[accessorPairs.size()]);
AggregationStateFactory[] accessAggregations = stateFactories.toArray(new AggregationStateFactory[stateFactories.size()]);
return new AggregationMultiFunctionAnalysisResult(pairs, accessAggregations);
}
private static AggregationMFIdentifier findExisting(Deque<AggregationMFIdentifier> accessProviderSlots, AggregationStateKey providerKey, ExprAggregateLocalGroupByDesc optionalOver) {
for (AggregationMFIdentifier ident : accessProviderSlots) {
if (!providerKey.equals(ident.getAggregationStateKey())) {
continue;
}
if (optionalOver == null && ident.optionalLocalGroupBy == null) {
return ident;
}
if (optionalOver != null &&
ident.optionalLocalGroupBy != null &&
ExprNodeUtility.deepEqualsIgnoreDupAndOrder(optionalOver.getPartitionExpressions(), ident.optionalLocalGroupBy.getPartitionExpressions())) {
return ident;
}
}
return null;
}
private static class AggregationMFIdentifier {
private final AggregationStateKey aggregationStateKey;
private final ExprAggregateLocalGroupByDesc optionalLocalGroupBy;
private final int slot;
private AggregationMFIdentifier(AggregationStateKey aggregationStateKey, ExprAggregateLocalGroupByDesc optionalLocalGroupBy, int slot) {
this.aggregationStateKey = aggregationStateKey;
this.optionalLocalGroupBy = optionalLocalGroupBy;
this.slot = slot;
}
public AggregationStateKey getAggregationStateKey() {
return aggregationStateKey;
}
public ExprAggregateLocalGroupByDesc getOptionalLocalGroupBy() {
return optionalLocalGroupBy;
}
public int getSlot() {
return slot;
}
}
}