com.espertech.esper.view.ViewServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of esper Show documentation
Show all versions of esper Show documentation
Complex event processing and event series analysis component
/**************************************************************************************
* Copyright (C) 2006-2015 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.view;
import com.espertech.esper.client.EventType;
import com.espertech.esper.collection.Pair;
import com.espertech.esper.core.context.util.AgentInstanceViewFactoryChainContext;
import com.espertech.esper.core.service.StatementContext;
import com.espertech.esper.epl.spec.StreamSpecOptions;
import com.espertech.esper.epl.spec.ViewSpec;
import com.espertech.esper.view.internal.IntersectViewFactory;
import com.espertech.esper.view.internal.UnionViewFactory;
import com.espertech.esper.view.std.GroupByViewFactory;
import com.espertech.esper.view.std.GroupByViewFactoryMarker;
import com.espertech.esper.view.std.MergeViewFactory;
import com.espertech.esper.view.std.MergeViewFactoryMarker;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.*;
/**
* Implementation of the view evaluation service business interface.
*/
public final class ViewServiceImpl implements ViewService
{
/**
* Ctor.
*/
public ViewServiceImpl()
{
}
public ViewFactoryChain createFactories(int streamNum,
EventType parentEventType,
ViewSpec[] viewSpecDefinitions,
StreamSpecOptions options,
StatementContext context,
boolean isSubquery,
int subqueryNumber)
throws ViewProcessingException
{
// Clone the view spec list to prevent parameter modification
List viewSpecList = new ArrayList(Arrays.asList(viewSpecDefinitions));
// Inspect views and add merge views if required
ViewServiceHelper.addMergeViews(viewSpecList);
// Instantiate factories, not making them aware of each other yet
List viewFactories = ViewServiceHelper.instantiateFactories(streamNum, viewSpecList, context, isSubquery, subqueryNumber);
ViewFactory parentViewFactory = null;
List attachedViewFactories = new ArrayList();
for (int i = 0; i < viewFactories.size(); i++)
{
ViewFactory factoryToAttach = viewFactories.get(i);
try
{
factoryToAttach.attach(parentEventType, context, parentViewFactory, attachedViewFactories);
attachedViewFactories.add(viewFactories.get(i));
parentEventType = factoryToAttach.getEventType();
}
catch (ViewParameterException ex)
{
String text = "Error attaching view to parent view";
if (i == 0)
{
text = "Error attaching view to event stream";
}
throw new ViewProcessingException(text + ": " + ex.getMessage(), ex);
}
}
// obtain count of data windows
int dataWindowCount = 0;
int firstNonDataWindowIndex = -1;
for (int i = 0; i < viewFactories.size(); i++)
{
ViewFactory factory = viewFactories.get(i);
if (factory instanceof DataWindowViewFactory)
{
dataWindowCount++;
continue;
}
if ((factory instanceof GroupByViewFactoryMarker) || (factory instanceof MergeViewFactory))
{
continue;
}
if (firstNonDataWindowIndex == -1)
{
firstNonDataWindowIndex = i;
}
}
boolean isAllowMultipleExpiry = context.getConfigSnapshot().getEngineDefaults().getViewResources().isAllowMultipleExpiryPolicies();
boolean isRetainIntersection = options.isRetainIntersection();
boolean isRetainUnion = options.isRetainUnion();
// Set the default to retain-intersection unless allow-multiple-expiry is turned on
if ((!isAllowMultipleExpiry) && (!isRetainUnion))
{
isRetainIntersection = true;
}
// handle multiple data windows with retain union.
// wrap view factories into the union view factory and handle a group-by, if present
if ((isRetainUnion || isRetainIntersection) && dataWindowCount > 1)
{
viewFactories = getRetainViewFactories(parentEventType, viewFactories, isRetainUnion, context);
}
return new ViewFactoryChain(parentEventType, viewFactories);
}
private List getRetainViewFactories(EventType parentEventType, List viewFactories, boolean isUnion, StatementContext context)
throws ViewProcessingException
{
Set groupByFactory = new HashSet();
Set mergeFactory = new HashSet();
List derivedValueViews = new ArrayList();
List dataWindowViews = new ArrayList();
for (int i = 0; i < viewFactories.size(); i++)
{
ViewFactory factory = viewFactories.get(i);
if (factory instanceof GroupByViewFactoryMarker)
{
groupByFactory.add(i);
}
else if (factory instanceof MergeViewFactoryMarker)
{
mergeFactory.add(i);
}
else if (factory instanceof DataWindowViewFactory)
{
dataWindowViews.add(factory);
}
else
{
derivedValueViews.add(factory);
}
}
if (groupByFactory.size() > 1)
{
throw new ViewProcessingException("Multiple groupwin views are not allowed in conjuntion with multiple data windows");
}
if ((!groupByFactory.isEmpty()) && (groupByFactory.iterator().next() != 0))
{
throw new ViewProcessingException("The groupwin view must occur in the first position in conjuntion with multiple data windows");
}
if ((!groupByFactory.isEmpty()) && (mergeFactory.iterator().next() != (viewFactories.size() - 1)))
{
throw new ViewProcessingException("The merge view cannot be used in conjuntion with multiple data windows");
}
GroupByViewFactoryMarker groupByViewFactory = null;
MergeViewFactoryMarker mergeViewFactory = null;
if (!groupByFactory.isEmpty())
{
groupByViewFactory = (GroupByViewFactoryMarker) viewFactories.remove(0);
mergeViewFactory = (MergeViewFactoryMarker) viewFactories.remove(viewFactories.size() - 1);
}
ViewFactory retainPolicy;
if (isUnion)
{
UnionViewFactory viewFactory = (UnionViewFactory) context.getViewResolutionService().create("internal", "union");
viewFactory.setParentEventType(parentEventType);
viewFactory.setViewFactories(dataWindowViews);
retainPolicy = viewFactory;
}
else
{
IntersectViewFactory viewFactory = (IntersectViewFactory) context.getViewResolutionService().create("internal", "intersect");
viewFactory.setParentEventType(parentEventType);
viewFactory.setViewFactories(dataWindowViews);
retainPolicy = viewFactory;
}
List nonRetainViewFactories = new ArrayList();
nonRetainViewFactories.add(retainPolicy);
if (groupByViewFactory != null)
{
nonRetainViewFactories.add(0, (ViewFactory) groupByViewFactory);
nonRetainViewFactories.addAll(derivedValueViews);
nonRetainViewFactories.add((ViewFactory) mergeViewFactory);
}
else
{
nonRetainViewFactories.addAll(derivedValueViews);
}
return nonRetainViewFactories;
}
public ViewServiceCreateResult createViews(Viewable eventStreamViewable,
List viewFactories,
AgentInstanceViewFactoryChainContext viewFactoryChainContext,
boolean hasPreviousNode)
{
// Attempt to find existing views under the stream that match specs.
// The viewSpecList may have been changed by this method.
Pair> resultPair;
if (hasPreviousNode) {
resultPair = new Pair>(eventStreamViewable, Collections.emptyList());
}
else {
resultPair = ViewServiceHelper.matchExistingViews(eventStreamViewable, viewFactories);
}
Viewable parentViewable = resultPair.getFirst();
if (viewFactories.isEmpty())
{
if (log.isDebugEnabled())
{
log.debug(".createView No new views created, dumping stream ... " + eventStreamViewable);
ViewSupport.dumpChildViews("EventStream ", eventStreamViewable);
}
return new ViewServiceCreateResult(parentViewable, parentViewable, Collections.emptyList()); // we know its a view here since the factory list is empty
}
// Instantiate remaining chain of views from the remaining factories which didn't match to existing views.
List views = ViewServiceHelper.instantiateChain(parentViewable, viewFactories, viewFactoryChainContext);
// Initialize any views that need initializing after the chain is complete
for (View view : views)
{
if (view instanceof InitializableView)
{
InitializableView initView = (InitializableView) view;
initView.initialize();
}
}
if (log.isDebugEnabled())
{
log.debug(".createView New views created for stream, all views ... " + eventStreamViewable);
ViewSupport.dumpChildViews("EventStream ", eventStreamViewable);
}
return new ViewServiceCreateResult(views.get(views.size() - 1), views.get(0), views);
}
public void remove(EventStream eventStream, Viewable viewToRemove)
{
// If the viewToRemove to remove has child viewToRemove, don't disconnect - the child viewToRemove(s) need this
if (viewToRemove.hasViews())
{
return;
}
if (log.isDebugEnabled())
{
log.debug(".remove Views before the remove of view " + viewToRemove + ", for event stream " + eventStream);
ViewSupport.dumpChildViews("EventStream ", eventStream);
}
// Remove views in chain leaving only non-empty parent views to the child view to be removed
ViewServiceHelper.removeChainLeafView(eventStream, viewToRemove);
if (log.isDebugEnabled())
{
log.debug(".remove Views after the remove, for event stream " + eventStream);
ViewSupport.dumpChildViews("EventStream ", eventStream);
}
}
private static final Log log = LogFactory.getLog(ViewServiceImpl.class);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy