/* *************************************************************************************** * 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.core; import com.espertech.esper.client.EventBean; import com.espertech.esper.collection.MultiKey; import com.espertech.esper.collection.UniformPair; import com.espertech.esper.epl.agg.service.AggregationGroupByRollupLevel; import java.util.*; public class ResultSetProcessorRowPerGroupRollupOutputAllHelperImpl implements ResultSetProcessorRowPerGroupRollupOutputAllHelper { private final ResultSetProcessorRowPerGroupRollup processor; private final Map<Object, EventBean[]>[] outputLimitGroupRepsPerLevel; private final Map<Object, EventBean>[] groupRepsOutputLastUnordRStream; private boolean first; public ResultSetProcessorRowPerGroupRollupOutputAllHelperImpl(ResultSetProcessorRowPerGroupRollup processor, int levelCount) { this.processor = processor; outputLimitGroupRepsPerLevel = (LinkedHashMap<Object, EventBean[]>[]) new LinkedHashMap[levelCount]; for (int i = 0; i < levelCount; i++) { outputLimitGroupRepsPerLevel[i] = new LinkedHashMap<Object, EventBean[]>(); } if (processor.prototype.isSelectRStream()) { groupRepsOutputLastUnordRStream = (LinkedHashMap<Object, EventBean>[]) new LinkedHashMap[levelCount]; for (int i = 0; i < levelCount; i++) { groupRepsOutputLastUnordRStream[i] = new LinkedHashMap<Object, EventBean>(); } } else { groupRepsOutputLastUnordRStream = null; } } public void processView(EventBean[] newData, EventBean[] oldData, boolean isGenerateSynthetic) { generateRemoveStreamJustOnce(isGenerateSynthetic, false); // apply to aggregates Object[] groupKeysPerLevel = new Object[processor.prototype.getGroupByRollupDesc().getLevels().length]; EventBean[] eventsPerStream; if (newData != null) { for (EventBean aNewData : newData) { eventsPerStream = new EventBean[]{aNewData}; Object groupKeyComplete = processor.generateGroupKey(eventsPerStream, true); for (AggregationGroupByRollupLevel level : processor.prototype.getGroupByRollupDesc().getLevels()) { Object groupKey = level.computeSubkey(groupKeyComplete); groupKeysPerLevel[level.getLevelNumber()] = groupKey; if (outputLimitGroupRepsPerLevel[level.getLevelNumber()].put(groupKey, eventsPerStream) == null) { if (processor.prototype.isSelectRStream()) { processor.generateOutputBatchedMapUnsorted(false, groupKey, level, eventsPerStream, true, isGenerateSynthetic, groupRepsOutputLastUnordRStream[level.getLevelNumber()]); } } } processor.aggregationService.applyEnter(eventsPerStream, groupKeysPerLevel, processor.agentInstanceContext); } } if (oldData != null) { for (EventBean anOldData : oldData) { eventsPerStream = new EventBean[]{anOldData}; Object groupKeyComplete = processor.generateGroupKey(eventsPerStream, false); for (AggregationGroupByRollupLevel level : processor.prototype.getGroupByRollupDesc().getLevels()) { Object groupKey = level.computeSubkey(groupKeyComplete); groupKeysPerLevel[level.getLevelNumber()] = groupKey; if (outputLimitGroupRepsPerLevel[level.getLevelNumber()].put(groupKey, eventsPerStream) == null) { if (processor.prototype.isSelectRStream()) { processor.generateOutputBatchedMapUnsorted(true, groupKey, level, eventsPerStream, false, isGenerateSynthetic, groupRepsOutputLastUnordRStream[level.getLevelNumber()]); } } } processor.aggregationService.applyLeave(eventsPerStream, groupKeysPerLevel, processor.agentInstanceContext); } } } public void processJoin(Set<MultiKey<EventBean>> newEvents, Set<MultiKey<EventBean>> oldEvents, boolean isGenerateSynthetic) { generateRemoveStreamJustOnce(isGenerateSynthetic, true); // apply to aggregates Object[] groupKeysPerLevel = new Object[processor.prototype.getGroupByRollupDesc().getLevels().length]; if (newEvents != null) { for (MultiKey<EventBean> newEvent : newEvents) { EventBean[] aNewData = newEvent.getArray(); Object groupKeyComplete = processor.generateGroupKey(aNewData, true); for (AggregationGroupByRollupLevel level : processor.prototype.getGroupByRollupDesc().getLevels()) { Object groupKey = level.computeSubkey(groupKeyComplete); groupKeysPerLevel[level.getLevelNumber()] = groupKey; if (outputLimitGroupRepsPerLevel[level.getLevelNumber()].put(groupKey, aNewData) == null) { if (processor.prototype.isSelectRStream()) { processor.generateOutputBatchedMapUnsorted(false, groupKey, level, aNewData, true, isGenerateSynthetic, groupRepsOutputLastUnordRStream[level.getLevelNumber()]); } } } processor.aggregationService.applyEnter(aNewData, groupKeysPerLevel, processor.agentInstanceContext); } } if (oldEvents != null) { for (MultiKey<EventBean> oldEvent : oldEvents) { EventBean[] aOldData = oldEvent.getArray(); Object groupKeyComplete = processor.generateGroupKey(aOldData, false); for (AggregationGroupByRollupLevel level : processor.prototype.getGroupByRollupDesc().getLevels()) { Object groupKey = level.computeSubkey(groupKeyComplete); groupKeysPerLevel[level.getLevelNumber()] = groupKey; if (outputLimitGroupRepsPerLevel[level.getLevelNumber()].put(groupKey, aOldData) == null) { if (processor.prototype.isSelectRStream()) { processor.generateOutputBatchedMapUnsorted(true, groupKey, level, aOldData, false, isGenerateSynthetic, groupRepsOutputLastUnordRStream[level.getLevelNumber()]); } } } processor.aggregationService.applyLeave(aOldData, groupKeysPerLevel, processor.agentInstanceContext); } } } public UniformPair<EventBean[]> outputView(boolean isSynthesize) { generateRemoveStreamJustOnce(isSynthesize, false); return output(isSynthesize, false); } public UniformPair<EventBean[]> outputJoin(boolean isSynthesize) { generateRemoveStreamJustOnce(isSynthesize, true); return output(isSynthesize, true); } public void destroy() { // no action required } private UniformPair<EventBean[]> output(boolean isSynthesize, boolean isJoin) { List<EventBean> newEvents = new ArrayList<EventBean>(4); for (AggregationGroupByRollupLevel level : processor.prototype.getGroupByRollupDesc().getLevels()) { Map<Object, EventBean[]> groupGenerators = outputLimitGroupRepsPerLevel[level.getLevelNumber()]; for (Map.Entry<Object, EventBean[]> entry : groupGenerators.entrySet()) { processor.generateOutputBatched(isJoin, entry.getKey(), level, entry.getValue(), true, isSynthesize, newEvents, null); } } EventBean[] newEventsArr = (newEvents.isEmpty()) ? null : newEvents.toArray(new EventBean[newEvents.size()]); EventBean[] oldEventsArr = null; if (processor.prototype.isSelectRStream()) { List<EventBean> oldEventList = new ArrayList<EventBean>(4); for (Map<Object, EventBean> entry : groupRepsOutputLastUnordRStream) { oldEventList.addAll(entry.values()); entry.clear(); } if (!oldEventList.isEmpty()) { oldEventsArr = oldEventList.toArray(new EventBean[oldEventList.size()]); } } first = true; if (newEventsArr == null && oldEventsArr == null) { return null; } return new UniformPair<EventBean[]>(newEventsArr, oldEventsArr); } private void generateRemoveStreamJustOnce(boolean isSynthesize, boolean join) { if (first && processor.prototype.isSelectRStream()) { for (AggregationGroupByRollupLevel level : processor.prototype.getGroupByRollupDesc().getLevels()) { for (Map.Entry<Object, EventBean[]> groupRep : outputLimitGroupRepsPerLevel[level.getLevelNumber()].entrySet()) { Object groupKeyPartial = processor.generateGroupKey(groupRep.getValue(), false); Object groupKey = level.computeSubkey(groupKeyPartial); processor.generateOutputBatchedMapUnsorted(join, groupKey, level, groupRep.getValue(), false, isSynthesize, groupRepsOutputLastUnordRStream[level.getLevelNumber()]); } } } first = false; } }