/**************************************************************************************
* 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.epl.named;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventPropertyDescriptor;
import com.espertech.esper.epl.expression.ExprEvaluator;
import com.espertech.esper.epl.expression.ExprEvaluatorContext;
import com.espertech.esper.epl.expression.ExprValidationException;
import com.espertech.esper.epl.spec.OnTriggerSetAssignment;
import com.espertech.esper.event.EventBeanCopyMethod;
import com.espertech.esper.event.EventPropertyWriter;
import com.espertech.esper.event.EventTypeSPI;
import com.espertech.esper.util.TypeWidener;
import com.espertech.esper.util.TypeWidenerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
public class NamedWindowUpdateHelper
{
private static final Log log = LogFactory.getLog(NamedWindowUpdateHelper.class);
private final ExprEvaluator[] expressions;
private final String[] propertyNames;
private final EventPropertyWriter[] writers;
private final EventBeanCopyMethod copyMethod;
private final boolean[] notNullableField;
private final TypeWidener[] wideners;
public NamedWindowUpdateHelper(ExprEvaluator[] expressions, String[] propertyNames, EventPropertyWriter[] writers, EventBeanCopyMethod copyMethod, boolean[] notNullableField, TypeWidener[] wideners) {
this.expressions = expressions;
this.propertyNames = propertyNames;
this.writers = writers;
this.copyMethod = copyMethod;
this.notNullableField = notNullableField;
this.wideners = wideners;
}
public static NamedWindowUpdateHelper make(String namedWindowName,
EventTypeSPI eventTypeSPI,
List<OnTriggerSetAssignment> assignments,
String namedWindowAlias)
throws ExprValidationException
{
TypeWidener wideners[] = new TypeWidener[assignments.size()];
List<String> properties = new ArrayList<String>();
int len = assignments.size();
ExprEvaluator[] expressions = new ExprEvaluator[len];
EventPropertyWriter[] writers = new EventPropertyWriter[len];
boolean[] notNullableField = new boolean[len];
for (int i = 0; i < assignments.size(); i++)
{
OnTriggerSetAssignment assignment = assignments.get(i);
String propertyName = assignment.getVariableName();
expressions[i] = assignment.getExpression().getExprEvaluator();
EventPropertyDescriptor writableProperty = eventTypeSPI.getWritableProperty(propertyName);
if (writableProperty == null)
{
int indexDot = propertyName.indexOf(".");
if ((namedWindowAlias != null) && (indexDot != -1)) {
String prefix = propertyName.substring(0, indexDot);
String name = propertyName.substring(indexDot + 1);
if (prefix.equals(namedWindowAlias)) {
writableProperty = eventTypeSPI.getWritableProperty(name);
propertyName = name;
}
}
if (writableProperty == null && indexDot != -1) {
String prefix = propertyName.substring(0, indexDot);
String name = propertyName.substring(indexDot + 1);
if (prefix.equals(namedWindowName)) {
writableProperty = eventTypeSPI.getWritableProperty(name);
propertyName = name;
}
}
if (writableProperty == null) {
throw new ExprValidationException("Property '" + propertyName + "' is not available for write access");
}
}
writers[i] = eventTypeSPI.getWriter(propertyName);
notNullableField[i] = writableProperty.getPropertyType().isPrimitive();
properties.add(propertyName);
wideners[i] = TypeWidenerFactory.getCheckPropertyAssignType(assignment.getExpression().toExpressionString(), assignment.getExpression().getExprEvaluator().getType(),
writableProperty.getPropertyType(), propertyName);
}
String[] propertyNames = properties.toArray(new String[properties.size()]);
// map expression index to property index
List<String> propertiesUniqueList = new ArrayList<String>(new HashSet<String>(properties));
String[] propertiesArray = propertiesUniqueList.toArray(new String[propertiesUniqueList.size()]);
EventBeanCopyMethod copyMethod = eventTypeSPI.getCopyMethod(propertiesArray);
if (copyMethod == null) {
throw new ExprValidationException("Event type does not support event bean copy");
}
return new NamedWindowUpdateHelper(expressions, propertyNames, writers, copyMethod, notNullableField, wideners);
}
public EventBean update(EventBean matchingEvent, EventBean[] eventsPerStream, ExprEvaluatorContext exprEvaluatorContext)
{
EventBean copy = copyMethod.copy(matchingEvent);
eventsPerStream[0] = copy;
eventsPerStream[2] = matchingEvent; // initial value
for (int i = 0; i < expressions.length; i++) {
Object result = expressions[i].evaluate(eventsPerStream, true, exprEvaluatorContext);
if (result == null && notNullableField[i]) {
log.warn("Null value returned by expression for assignment to property '" + propertyNames[i] + " is ignored as the property type is not nullable for expression");
continue;
}
if (wideners[i] != null) {
result = wideners[i].widen(result);
}
writers[i].write(result, copy);
}
return copy;
}
}