/*
***************************************************************************************
* 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.view.internal;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.core.context.util.AgentInstanceContext;
import com.espertech.esper.core.context.util.AgentInstanceViewFactoryChainContext;
import com.espertech.esper.core.service.StatementContext;
import com.espertech.esper.epl.expression.core.ExprNode;
import com.espertech.esper.view.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Factory for union-views.
*/
public class IntersectViewFactory implements ViewFactory, DataWindowViewFactory, DataWindowViewFactoryUniqueCandidate, ViewFactoryContainer {
protected EventType parentEventType;
protected List<ViewFactory> viewFactories;
protected int batchViewIndex;
protected boolean hasAsymetric;
protected ThreadLocal<IntersectBatchViewLocalState> batchViewLocalState;
protected ThreadLocal<IntersectDefaultViewLocalState> defaultViewLocalState;
protected ThreadLocal<IntersectAsymetricViewLocalState> asymetricViewLocalState;
/**
* Ctor.
*/
public IntersectViewFactory() {
}
/**
* Sets the parent event type.
*
* @param parentEventType type
*/
public void setParentEventType(EventType parentEventType) {
this.parentEventType = parentEventType;
}
/**
* Sets the view factories.
*
* @param viewFactories factories
*/
public void setViewFactories(final List<ViewFactory> viewFactories) {
this.viewFactories = viewFactories;
int batchCount = 0;
for (int i = 0; i < viewFactories.size(); i++) {
ViewFactory viewFactory = viewFactories.get(i);
hasAsymetric |= viewFactory instanceof AsymetricDataWindowViewFactory;
if (viewFactory instanceof DataWindowBatchingViewFactory) {
batchCount++;
batchViewIndex = i;
}
}
if (batchCount > 1) {
throw new ViewProcessingException("Cannot combined multiple batch data windows into an intersection");
}
if (batchCount == 1) {
batchViewLocalState = new ThreadLocal<IntersectBatchViewLocalState>() {
protected synchronized IntersectBatchViewLocalState initialValue() {
return new IntersectBatchViewLocalState(new EventBean[viewFactories.size()][], new EventBean[viewFactories.size()][]);
}
};
} else if (hasAsymetric) {
asymetricViewLocalState = new ThreadLocal<IntersectAsymetricViewLocalState>() {
protected synchronized IntersectAsymetricViewLocalState initialValue() {
return new IntersectAsymetricViewLocalState(new EventBean[viewFactories.size()][]);
}
};
} else {
defaultViewLocalState = new ThreadLocal<IntersectDefaultViewLocalState>() {
protected synchronized IntersectDefaultViewLocalState initialValue() {
return new IntersectDefaultViewLocalState(new EventBean[viewFactories.size()][]);
}
};
}
}
public void setViewParameters(ViewFactoryContext viewFactoryContext, List<ExprNode> viewParameters) throws ViewParameterException {
}
public void attach(EventType parentEventType, StatementContext statementContext, ViewFactory optionalParentFactory, List<ViewFactory> parentViewFactories) throws ViewParameterException {
}
public View makeView(AgentInstanceViewFactoryChainContext agentInstanceViewFactoryContext) {
List<View> views = new ArrayList<View>();
boolean hasBatch = false;
for (ViewFactory viewFactory : viewFactories) {
agentInstanceViewFactoryContext.setRemoveStream(true);
views.add(viewFactory.makeView(agentInstanceViewFactoryContext));
hasBatch |= viewFactory instanceof DataWindowBatchingViewFactory;
}
if (hasBatch) {
return new IntersectBatchView(agentInstanceViewFactoryContext, this, views);
} else if (hasAsymetric) {
return new IntersectAsymetricView(agentInstanceViewFactoryContext, this, views);
}
return new IntersectDefaultView(agentInstanceViewFactoryContext, this, views);
}
public EventType getEventType() {
return parentEventType;
}
public boolean canReuse(View view, AgentInstanceContext agentInstanceContext) {
return false;
}
public Set<String> getUniquenessCandidatePropertyNames() {
for (ViewFactory viewFactory : viewFactories) {
if (viewFactory instanceof DataWindowViewFactoryUniqueCandidate) {
DataWindowViewFactoryUniqueCandidate unique = (DataWindowViewFactoryUniqueCandidate) viewFactory;
Set<String> props = unique.getUniquenessCandidatePropertyNames();
if (props != null) {
return props;
}
}
}
return null;
}
public String getViewName() {
return getViewNameUnionIntersect(true, viewFactories);
}
public Collection<ViewFactory> getViewFactoriesContained() {
return viewFactories;
}
protected static String getViewNameUnionIntersect(boolean intersect, Collection<ViewFactory> factories) {
StringBuilder buf = new StringBuilder();
buf.append(intersect ? "Intersection" : "Union");
if (factories == null) {
return buf.toString();
}
buf.append(" of ");
String delimiter = "";
for (ViewFactory factory : factories) {
buf.append(delimiter);
buf.append(factory.getViewName());
delimiter = ",";
}
return buf.toString();
}
public EventType getParentEventType() {
return parentEventType;
}
public int getBatchViewIndex() {
return batchViewIndex;
}
public boolean isHasAsymetric() {
return hasAsymetric;
}
public IntersectBatchViewLocalState getBatchViewLocalStatePerThread() {
return batchViewLocalState.get();
}
public IntersectDefaultViewLocalState getDefaultViewLocalStatePerThread() {
return defaultViewLocalState.get();
}
public IntersectAsymetricViewLocalState getAsymetricViewLocalStatePerThread() {
return asymetricViewLocalState.get();
}
}