/************************************************************************************** * Copyright (C) 2008 EsperTech, Inc. All rights reserved. * * http://esper.codehaus.org * * 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.core.start; import com.espertech.esper.epl.core.ViewResourceDelegateUnverified; import com.espertech.esper.epl.core.ViewResourceDelegateVerified; import com.espertech.esper.epl.core.ViewResourceDelegateVerifiedStream; import com.espertech.esper.epl.expression.ExprPreviousNode; import com.espertech.esper.epl.expression.ExprPriorNode; import com.espertech.esper.epl.expression.ExprValidationException; import com.espertech.esper.util.CollectionUtil; import com.espertech.esper.view.DataWindowViewWithPrevious; import com.espertech.esper.view.ViewFactory; import com.espertech.esper.view.ViewFactoryChain; import com.espertech.esper.view.internal.PriorEventViewFactory; import com.espertech.esper.view.std.GroupByViewFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.*; public class EPStatementStartMethodHelperViewResources { private static final Log log = LogFactory.getLog(EPStatementStartMethodHelperViewResources.class); public static ViewResourceDelegateVerified verifyPreviousAndPriorRequirements(ViewFactoryChain[] unmaterializedViewChain, ViewResourceDelegateUnverified delegate) throws ExprValidationException { boolean hasPriorNodes = !delegate.getPriorRequests().isEmpty(); boolean hasPreviousNodes = !delegate.getPreviousRequests().isEmpty(); int numStreams = unmaterializedViewChain.length; ViewResourceDelegateVerifiedStream[] perStream = new ViewResourceDelegateVerifiedStream[numStreams]; // verify "previous" List<ExprPreviousNode>[] previousPerStream = new List[numStreams]; for (ExprPreviousNode previousNode : delegate.getPreviousRequests()) { int stream = previousNode.getStreamNumber(); List<ViewFactory> factories = unmaterializedViewChain[stream].getViewFactoryChain(); boolean pass = inspectViewFactoriesForPrevious(factories); if (!pass) { throw new ExprValidationException("Previous function requires a single data window view onto the stream"); } boolean found = false; for (ViewFactory factory : factories) { if (factory instanceof DataWindowViewWithPrevious) { found = true; break; } } if (!found) { throw new ExprValidationException("Required data window not found for the 'prev' function, specify a data window for which previous events are retained"); } if (previousPerStream[stream] == null) { previousPerStream[stream] = new ArrayList<ExprPreviousNode>(); } previousPerStream[stream].add(previousNode); } // verify "prior" SortedMap<Integer, List<ExprPriorNode>>[] priorPerStream = new SortedMap[numStreams]; for (ExprPriorNode priorNode : delegate.getPriorRequests()) { int stream = priorNode.getStreamNumber(); if (priorPerStream[stream] == null) { priorPerStream[stream] = new TreeMap<Integer, List<ExprPriorNode>>(); } TreeMap<Integer, List<ExprPriorNode>> treemap = (TreeMap<Integer, List<ExprPriorNode>>) priorPerStream[stream]; List<ExprPriorNode> callbackList = treemap.get(priorNode.getConstantIndexNumber()); if (callbackList == null) { callbackList = new LinkedList<ExprPriorNode>(); treemap.put(priorNode.getConstantIndexNumber(), callbackList); } callbackList.add(priorNode); } // build per-stream info for (int i = 0; i < numStreams; i++) { if (previousPerStream[i] == null) { previousPerStream[i] = Collections.emptyList(); } if (priorPerStream[i] == null) { priorPerStream[i] = CollectionUtil.EMPTY_SORTED_MAP; } perStream[i] = new ViewResourceDelegateVerifiedStream(previousPerStream[i], priorPerStream[i]); } return new ViewResourceDelegateVerified(hasPriorNodes, hasPreviousNodes, perStream); } private static boolean inspectViewFactoriesForPrevious(List<ViewFactory> viewFactories) { // We allow the capability only if // - 1 view // - 2 views and the first view is a group-by (for window-per-group access) if (viewFactories.size() == 1) { return true; } if (viewFactories.size() == 2) { if (viewFactories.get(0) instanceof GroupByViewFactory) { return true; } if (viewFactories.get(1) instanceof PriorEventViewFactory) { return true; } return false; } return true; } }