/*
***************************************************************************************
* 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.dataflow.ops;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.dataflow.annotations.DataFlowContext;
import com.espertech.esper.dataflow.annotations.DataFlowOpParameter;
import com.espertech.esper.dataflow.annotations.DataFlowOperator;
import com.espertech.esper.dataflow.interfaces.*;
import com.espertech.esper.dataflow.util.GraphTypeDesc;
import com.espertech.esper.epl.expression.core.*;
import com.espertech.esper.event.EventBeanSPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
@DataFlowOperator
public class Filter implements DataFlowOpLifecycle {
private static final Logger log = LoggerFactory.getLogger(Filter.class);
@DataFlowOpParameter
private ExprNode filter;
private ExprEvaluator evaluator;
private EventBeanSPI theEvent;
private EventBean[] eventsPerStream = new EventBean[1];
private boolean singleOutputPort;
@DataFlowContext
private EPDataFlowEmitter graphContext;
public DataFlowOpInitializeResult initialize(DataFlowOpInitializateContext prepareContext) throws Exception {
if (prepareContext.getInputPorts().size() != 1) {
throw new ExprValidationException("Filter requires single input port");
}
if (filter == null) {
throw new ExprValidationException("Required parameter 'filter' providing the filter expression is not provided");
}
if (prepareContext.getOutputPorts().isEmpty() || prepareContext.getOutputPorts().size() > 2) {
throw new IllegalArgumentException("Filter operator requires one or two output stream(s) but produces " + prepareContext.getOutputPorts().size() + " streams");
}
EventType eventType = prepareContext.getInputPorts().get(0).getTypeDesc().getEventType();
singleOutputPort = prepareContext.getOutputPorts().size() == 1;
ExprNode validated = ExprNodeUtility.validateSimpleGetSubtree(ExprNodeOrigin.DATAFLOWFILTER, filter, prepareContext.getStatementContext(), eventType, false);
evaluator = validated.getExprEvaluator();
theEvent = prepareContext.getServicesContext().getEventAdapterService().getShellForType(eventType);
eventsPerStream[0] = theEvent;
GraphTypeDesc[] typesPerPort = new GraphTypeDesc[prepareContext.getOutputPorts().size()];
for (int i = 0; i < typesPerPort.length; i++) {
typesPerPort[i] = new GraphTypeDesc(false, true, eventType);
}
return new DataFlowOpInitializeResult(typesPerPort);
}
public void onInput(Object row) {
if (log.isDebugEnabled()) {
log.debug("Received row for filtering: " + Arrays.toString((Object[]) row));
}
if (!(row instanceof EventBeanSPI)) {
theEvent.setUnderlying(row);
} else {
theEvent = (EventBeanSPI) row;
}
Boolean pass = (Boolean) evaluator.evaluate(eventsPerStream, true, null);
if (pass != null && pass) {
if (log.isDebugEnabled()) {
log.debug("Submitting row " + Arrays.toString((Object[]) row));
}
if (singleOutputPort) {
graphContext.submit(row);
} else {
graphContext.submitPort(0, row);
}
} else {
if (!singleOutputPort) {
graphContext.submitPort(1, row);
}
}
}
public void open(DataFlowOpOpenContext openContext) {
// no action
}
public void close(DataFlowOpCloseContext openContext) {
// no action
}
}