/*
***************************************************************************************
* 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.core.context.factory;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.core.context.activator.ViewableActivationResult;
import com.espertech.esper.core.context.activator.ViewableActivator;
import com.espertech.esper.core.context.util.AgentInstanceContext;
import com.espertech.esper.core.context.util.AgentInstanceViewFactoryChainContext;
import com.espertech.esper.core.context.util.StatementAgentInstanceUtil;
import com.espertech.esper.core.service.EPServicesContext;
import com.espertech.esper.core.service.StatementContext;
import com.espertech.esper.core.start.EPStatementStartMethodCreateWindow;
import com.espertech.esper.core.start.EPStatementStartMethodHelperAssignExpr;
import com.espertech.esper.epl.core.ResultSetProcessor;
import com.espertech.esper.epl.core.ResultSetProcessorFactoryDesc;
import com.espertech.esper.epl.expression.core.ExprEvaluator;
import com.espertech.esper.epl.named.NamedWindowProcessor;
import com.espertech.esper.epl.named.NamedWindowProcessorInstance;
import com.espertech.esper.epl.named.NamedWindowTailViewInstance;
import com.espertech.esper.epl.spec.StatementSpecCompiled;
import com.espertech.esper.epl.view.OutputProcessViewFactory;
import com.espertech.esper.epl.virtualdw.VirtualDWView;
import com.espertech.esper.util.StopCallback;
import com.espertech.esper.view.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.NamingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class StatementAgentInstanceFactoryCreateWindow extends StatementAgentInstanceFactoryBase {
private static final Logger log = LoggerFactory.getLogger(EPStatementStartMethodCreateWindow.class);
protected final StatementContext statementContext;
protected final StatementSpecCompiled statementSpec;
protected final EPServicesContext services;
protected final ViewableActivator activator;
protected final ViewFactoryChain unmaterializedViewChain;
protected final ResultSetProcessorFactoryDesc resultSetProcessorPrototype;
protected final OutputProcessViewFactory outputProcessViewFactory;
protected final boolean isRecoveringStatement;
public StatementAgentInstanceFactoryCreateWindow(StatementContext statementContext, StatementSpecCompiled statementSpec, EPServicesContext services, ViewableActivator activator, ViewFactoryChain unmaterializedViewChain, ResultSetProcessorFactoryDesc resultSetProcessorPrototype, OutputProcessViewFactory outputProcessViewFactory, boolean recoveringStatement) {
super(statementContext.getAnnotations());
this.statementContext = statementContext;
this.statementSpec = statementSpec;
this.services = services;
this.activator = activator;
this.unmaterializedViewChain = unmaterializedViewChain;
this.resultSetProcessorPrototype = resultSetProcessorPrototype;
this.outputProcessViewFactory = outputProcessViewFactory;
isRecoveringStatement = recoveringStatement;
}
public StatementAgentInstanceFactoryCreateWindowResult newContextInternal(final AgentInstanceContext agentInstanceContext, boolean isRecoveringResilient) {
final List<StopCallback> stopCallbacks = new ArrayList<StopCallback>();
String windowName = statementSpec.getCreateWindowDesc().getWindowName();
Viewable finalView;
Viewable eventStreamParentViewable;
StatementAgentInstancePostLoad postLoad;
Viewable topView;
NamedWindowProcessorInstance processorInstance;
ViewableActivationResult viewableActivationResult;
try {
// Register interest
viewableActivationResult = activator.activate(agentInstanceContext, false, isRecoveringResilient);
stopCallbacks.add(viewableActivationResult.getStopCallback());
eventStreamParentViewable = viewableActivationResult.getViewable();
// Obtain processor for this named window
NamedWindowProcessor processor = services.getNamedWindowMgmtService().getProcessor(windowName);
if (processor == null) {
throw new RuntimeException("Failed to obtain named window processor for named window '" + windowName + "'");
}
// Allocate processor instance
processorInstance = processor.addInstance(agentInstanceContext);
View rootView = processorInstance.getRootViewInstance();
eventStreamParentViewable.addView(rootView);
// Materialize views
AgentInstanceViewFactoryChainContext viewFactoryChainContext = new AgentInstanceViewFactoryChainContext(agentInstanceContext, true, null, null);
ViewServiceCreateResult createResult = services.getViewService().createViews(rootView, unmaterializedViewChain.getViewFactoryChain(), viewFactoryChainContext, false);
topView = createResult.getTopViewable();
finalView = createResult.getFinalViewable();
// add views to stop callback if applicable
StatementAgentInstanceFactorySelect.addViewStopCallback(stopCallbacks, createResult.getNewViews());
// If this is a virtual data window implementation, bind it to the context for easy lookup
StopCallback envStopCallback = null;
if (finalView instanceof VirtualDWView) {
final String objectName = "/virtualdw/" + windowName;
final VirtualDWView virtualDWView = (VirtualDWView) finalView;
try {
services.getEngineEnvContext().bind(objectName, virtualDWView.getVirtualDataWindow());
} catch (NamingException e) {
throw new ViewProcessingException("Invalid name for adding to context:" + e.getMessage(), e);
}
envStopCallback = new StopCallback() {
public void stop() {
try {
virtualDWView.destroy();
services.getEngineEnvContext().unbind(objectName);
} catch (NamingException e) {
}
}
};
}
final StopCallback environmentStopCallback = envStopCallback;
// Only if we are context-allocated: destroy the instance
final String contextName = processor.getContextName();
final int agentInstanceId = agentInstanceContext.getAgentInstanceId();
StopCallback allInOneStopMethod = new StopCallback() {
public void stop() {
String windowName = statementSpec.getCreateWindowDesc().getWindowName();
NamedWindowProcessor processor = services.getNamedWindowMgmtService().getProcessor(windowName);
if (processor == null) {
log.warn("Named window processor by name '" + windowName + "' has not been found");
} else {
NamedWindowProcessorInstance instance = processor.getProcessorInstanceAllowUnpartitioned(agentInstanceId);
if (instance != null) {
if (contextName != null) {
instance.destroy();
} else {
instance.stop();
}
}
}
if (environmentStopCallback != null) {
environmentStopCallback.stop();
}
}
};
stopCallbacks.add(allInOneStopMethod);
// Attach tail view
NamedWindowTailViewInstance tailView = processorInstance.getTailViewInstance();
finalView.addView(tailView);
finalView = tailView;
// obtain result set processor
ResultSetProcessor resultSetProcessor = EPStatementStartMethodHelperAssignExpr.getAssignResultSetProcessor(agentInstanceContext, resultSetProcessorPrototype, false, null, false);
// Attach output view
View outputView = outputProcessViewFactory.makeView(resultSetProcessor, agentInstanceContext);
finalView.addView(outputView);
finalView = outputView;
// obtain post load
postLoad = processorInstance.getPostLoad();
// Handle insert case
if (statementSpec.getCreateWindowDesc().isInsert() && !isRecoveringStatement && !isRecoveringResilient) {
String insertFromWindow = statementSpec.getCreateWindowDesc().getInsertFromWindow();
NamedWindowProcessor namedWindowProcessor = services.getNamedWindowMgmtService().getProcessor(insertFromWindow);
NamedWindowProcessorInstance sourceWindowInstances = namedWindowProcessor.getProcessorInstance(agentInstanceContext);
List<EventBean> events = new ArrayList<EventBean>();
if (statementSpec.getCreateWindowDesc().getInsertFilter() != null) {
EventBean[] eventsPerStream = new EventBean[1];
ExprEvaluator filter = statementSpec.getCreateWindowDesc().getInsertFilter().getExprEvaluator();
for (Iterator<EventBean> it = sourceWindowInstances.getTailViewInstance().iterator(); it.hasNext(); ) {
EventBean candidate = it.next();
eventsPerStream[0] = candidate;
Boolean result = (Boolean) filter.evaluate(eventsPerStream, true, agentInstanceContext);
if ((result == null) || (!result)) {
continue;
}
events.add(candidate);
}
} else {
for (Iterator<EventBean> it = sourceWindowInstances.getTailViewInstance().iterator(); it.hasNext(); ) {
events.add(it.next());
}
}
if (events.size() > 0) {
EventType rootViewType = rootView.getEventType();
EventBean[] convertedEvents = services.getEventAdapterService().typeCast(events, rootViewType);
rootView.update(convertedEvents, null);
}
}
} catch (RuntimeException ex) {
StopCallback stopCallback = StatementAgentInstanceUtil.getStopCallback(stopCallbacks, agentInstanceContext);
StatementAgentInstanceUtil.stopSafe(stopCallback, statementContext);
throw ex;
}
StatementAgentInstanceFactoryCreateWindowResult createWindowResult = new StatementAgentInstanceFactoryCreateWindowResult(finalView, null, agentInstanceContext, eventStreamParentViewable, postLoad, topView, processorInstance, viewableActivationResult);
if (statementContext.getStatementExtensionServicesContext() != null) {
statementContext.getStatementExtensionServicesContext().contributeStopCallback(createWindowResult, stopCallbacks);
}
log.debug(".start Statement start completed");
StopCallback stopCallback = StatementAgentInstanceUtil.getStopCallback(stopCallbacks, agentInstanceContext);
createWindowResult.setStopCallback(stopCallback);
return createWindowResult;
}
public void assignExpressions(StatementAgentInstanceFactoryResult result) {
}
public void unassignExpressions() {
}
}