/*
* *************************************************************************************
* 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.regression.client;
import com.espertech.esper.client.*;
import com.espertech.esper.client.hook.AggregationFunctionFactory;
import com.espertech.esper.client.scopetest.EPAssertionUtil;
import com.espertech.esper.client.scopetest.SupportUpdateListener;
import com.espertech.esper.client.soda.*;
import com.espertech.esper.epl.agg.aggregator.AggregationMethod;
import com.espertech.esper.epl.agg.service.AggregationValidationContext;
import com.espertech.esper.support.bean.SupportBean;
import com.espertech.esper.support.bean.SupportBean_A;
import com.espertech.esper.support.client.SupportConfigFactory;
import com.espertech.esper.support.epl.SupportPluginAggregationMethodOne;
import com.espertech.esper.support.epl.SupportPluginAggregationMethodThree;
import com.espertech.esper.support.epl.SupportPluginAggregationMethodTwo;
import com.espertech.esper.util.SerializableObjectCopier;
import junit.framework.TestCase;
public class TestAggregationFunctionPlugIn extends TestCase
{
private EPServiceProvider epService;
public void setUp()
{
Configuration configuration = SupportConfigFactory.getConfiguration();
configuration.addPlugInAggregationFunction("concatstring", MyConcatAggregationFunction.class.getName());
configuration.addPlugInAggregationFunctionFactory("concatstringTwo", MyConcatTwoAggFunctionFactory.class.getName());
configuration.getEngineDefaults().getThreading().setEngineFairlock(true);
epService = EPServiceProviderManager.getProvider("TestAggregationFunctionPlugIn", configuration);
epService.initialize();
}
public void tearDown()
{
epService.initialize();
}
public void testGrouped() throws Exception
{
String textOne = "select irstream CONCATSTRING(theString) as val from " + SupportBean.class.getName() + ".win:length(10) group by intPrimitive";
tryGrouped(textOne, null);
String textTwo = "select irstream concatstring(theString) as val from " + SupportBean.class.getName() + ".win:length(10) group by intPrimitive";
tryGrouped(textTwo, null);
String textThree = "select irstream concatstring(theString) as val from " + SupportBean.class.getName() + ".win:length(10) group by intPrimitive";
EPStatementObjectModel model = epService.getEPAdministrator().compileEPL(textThree);
SerializableObjectCopier.copy(model);
assertEquals(textThree, model.toEPL());
tryGrouped(null, model);
String textFour = "select irstream concatstring(theString) as val from " + SupportBean.class.getName() + ".win:length(10) group by intPrimitive";
EPStatementObjectModel modelTwo = new EPStatementObjectModel();
modelTwo.setSelectClause(SelectClause.create().streamSelector(StreamSelector.RSTREAM_ISTREAM_BOTH)
.add(Expressions.plugInAggregation("concatstring", Expressions.property("theString")), "val"));
modelTwo.setFromClause(FromClause.create(FilterStream.create(SupportBean.class.getName()).addView("win", "length", Expressions.constant(10))));
modelTwo.setGroupByClause(GroupByClause.create("intPrimitive"));
assertEquals(textFour, modelTwo.toEPL());
SerializableObjectCopier.copy(modelTwo);
tryGrouped(null, modelTwo);
String textFive = "select irstream concatstringTwo(theString) as val from " + SupportBean.class.getName() + ".win:length(10) group by intPrimitive";
tryGrouped(textFive, null);
}
private void tryGrouped(String text, EPStatementObjectModel model)
{
EPStatement statement;
if (model != null)
{
statement = epService.getEPAdministrator().create(model);
}
else
{
statement = epService.getEPAdministrator().createEPL(text);
}
SupportUpdateListener listener = new SupportUpdateListener();
statement.addListener(listener);
epService.getEPRuntime().sendEvent(new SupportBean("a", 1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a"}, new Object[] {""});
epService.getEPRuntime().sendEvent(new SupportBean("b", 2));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"b"}, new Object[] {""});
epService.getEPRuntime().sendEvent(new SupportBean("c", 1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a c"}, new Object[] {"a"});
epService.getEPRuntime().sendEvent(new SupportBean("d", 2));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"b d"}, new Object[] {"b"});
epService.getEPRuntime().sendEvent(new SupportBean("e", 1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a c e"}, new Object[] {"a c"});
epService.getEPRuntime().sendEvent(new SupportBean("f", 2));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"b d f"}, new Object[] {"b d"});
listener.reset();
}
public void testWindow()
{
String text = "select irstream concatstring(theString) as val from " + SupportBean.class.getName() + ".win:length(2)";
EPStatement statement = epService.getEPAdministrator().createEPL(text);
SupportUpdateListener listener = new SupportUpdateListener();
statement.addListener(listener);
epService.getEPRuntime().sendEvent(new SupportBean("a", -1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a"}, new Object[] {""});
epService.getEPRuntime().sendEvent(new SupportBean("b", -1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a b"}, new Object[] {"a"});
epService.getEPRuntime().sendEvent(new SupportBean("c", -1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"b c"}, new Object[] {"a b"});
epService.getEPRuntime().sendEvent(new SupportBean("d", -1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"c d"}, new Object[] {"b c"});
epService.getEPAdministrator().destroyAllStatements();
}
public void testDistinctAndStarParam()
{
epService.getEPAdministrator().getConfiguration().addEventType(SupportBean.class);
// test *-parameter
String textTwo = "select concatstring(*) as val from SupportBean";
EPStatement statementTwo = epService.getEPAdministrator().createEPL(textTwo);
SupportUpdateListener listenerTwo = new SupportUpdateListener();
statementTwo.addListener(listenerTwo);
epService.getEPRuntime().sendEvent(new SupportBean("d", -1));
EPAssertionUtil.assertProps(listenerTwo.assertOneGetNewAndReset(), "val".split(","), new Object[] {"SupportBean(d, -1)"});
epService.getEPRuntime().sendEvent(new SupportBean("e", 2));
EPAssertionUtil.assertProps(listenerTwo.assertOneGetNewAndReset(), "val".split(","), new Object[] {"SupportBean(d, -1) SupportBean(e, 2)"});
try {
epService.getEPAdministrator().createEPL("select concatstring(*) as val from SupportBean.std:lastevent(), SupportBean unidirectional");
}
catch (EPStatementException ex) {
assertEquals("Error starting statement: Invalid use of wildcard (*) for stream selection in a join or an empty from-clause, please use the stream-alias syntax to select a specific stream instead [select concatstring(*) as val from SupportBean.std:lastevent(), SupportBean unidirectional]", ex.getMessage());
}
// test distinct
String text = "select irstream concatstring(distinct theString) as val from SupportBean";
EPStatement statement = epService.getEPAdministrator().createEPL(text);
SupportUpdateListener listener = new SupportUpdateListener();
statement.addListener(listener);
epService.getEPRuntime().sendEvent(new SupportBean("a", -1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a"}, new Object[] {""});
epService.getEPRuntime().sendEvent(new SupportBean("b", -1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a b"}, new Object[] {"a"});
epService.getEPRuntime().sendEvent(new SupportBean("b", -1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a b"}, new Object[] {"a b"});
epService.getEPRuntime().sendEvent(new SupportBean("c", -1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a b c"}, new Object[] {"a b"});
epService.getEPRuntime().sendEvent(new SupportBean("a", -1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a b c"}, new Object[] {"a b c"});
}
public void testArrayParamsAndDotMethod()
{
epService.getEPAdministrator().getConfiguration().addPlugInAggregationFunction("countback", SupportPluginAggregationMethodOne.class.getName());
String text = "select irstream countback({1,2,intPrimitive}) as val from " + SupportBean.class.getName();
EPStatement statement = epService.getEPAdministrator().createEPL(text);
SupportUpdateListener listener = new SupportUpdateListener();
statement.addListener(listener);
epService.getEPRuntime().sendEvent(new SupportBean());
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {-1}, new Object[] {0});
// test dot-method
epService.getEPAdministrator().getConfiguration().addEventType(SupportBean_A.class);
epService.getEPAdministrator().getConfiguration().addPlugInAggregationFunctionFactory("myagg", MyAggFuncFactory.class.getName());
String[] fields = "val0,val1".split(",");
epService.getEPAdministrator().createEPL("select (myagg(id)).getTheString() as val0, (myagg(id)).getIntPrimitive() as val1 from SupportBean_A").addListener(listener);
epService.getEPRuntime().sendEvent(new SupportBean_A("A1"));
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[] {"XX", 1});
assertEquals(1, MyAggFuncFactory.getInstanceCount());
epService.getEPRuntime().sendEvent(new SupportBean_A("A2"));
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[] {"XX", 2});
}
public void testMultipleParams()
{
epService.getEPAdministrator().getConfiguration().addPlugInAggregationFunction("countboundary", SupportPluginAggregationMethodThree.class.getName());
String text = "select irstream countboundary(1, 10, intPrimitive) as val from " + SupportBean.class.getName();
EPStatement statement = epService.getEPAdministrator().createEPL(text);
SupportUpdateListener listener = new SupportUpdateListener();
statement.addListener(listener);
runAssertion(listener);
statement.destroy();
EPStatementObjectModel model = epService.getEPAdministrator().compileEPL(text);
assertEquals(text, model.toEPL());
statement = epService.getEPAdministrator().create(model);
statement.addListener(listener);
runAssertion(listener);
}
private void runAssertion(SupportUpdateListener listener) {
AggregationValidationContext validContext = SupportPluginAggregationMethodThree.getContexts().get(0);
EPAssertionUtil.assertEqualsExactOrder(new Class[]{Integer.class, Integer.class, int.class}, validContext.getParameterTypes());
EPAssertionUtil.assertEqualsExactOrder(new Object[]{1, 10, null}, validContext.getConstantValues());
EPAssertionUtil.assertEqualsExactOrder(new boolean[]{true, true, false}, validContext.getIsConstantValue());
epService.getEPRuntime().sendEvent(new SupportBean("E1", 5));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {1}, new Object[] {0});
epService.getEPRuntime().sendEvent(new SupportBean("E1", 0));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {1}, new Object[] {1});
epService.getEPRuntime().sendEvent(new SupportBean("E1", 11));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {1}, new Object[] {1});
epService.getEPRuntime().sendEvent(new SupportBean("E1", 1));
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {2}, new Object[] {1});
}
public void testNoSubnodesRuntimeAdd()
{
epService.getEPAdministrator().getConfiguration().addPlugInAggregationFunction("countback", SupportPluginAggregationMethodOne.class.getName());
String text = "select irstream countback() as val from " + SupportBean.class.getName();
EPStatement statement = epService.getEPAdministrator().createEPL(text);
SupportUpdateListener listener = new SupportUpdateListener();
statement.addListener(listener);
epService.getEPRuntime().sendEvent(new SupportBean());
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {-1}, new Object[] {0});
epService.getEPRuntime().sendEvent(new SupportBean());
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {-2}, new Object[] {-1});
}
public void testMappedPropertyLookAlike()
{
String text = "select irstream concatstring('a') as val from " + SupportBean.class.getName();
EPStatement statement = epService.getEPAdministrator().createEPL(text);
SupportUpdateListener listener = new SupportUpdateListener();
statement.addListener(listener);
assertEquals(String.class, statement.getEventType().getPropertyType("val"));
epService.getEPRuntime().sendEvent(new SupportBean());
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a"}, new Object[] {""});
epService.getEPRuntime().sendEvent(new SupportBean());
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a a"}, new Object[] {"a"});
epService.getEPRuntime().sendEvent(new SupportBean());
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {"a a a"}, new Object[] {"a a"});
}
public void testFailedValidation()
{
Configuration configuration = SupportConfigFactory.getConfiguration();
configuration.addPlugInAggregationFunction("concat", SupportPluginAggregationMethodTwo.class.getName());
epService = EPServiceProviderManager.getDefaultProvider(configuration);
epService.initialize();
try
{
String text = "select * from " + SupportBean.class.getName() + " group by concat(1)";
epService.getEPAdministrator().createEPL(text);
}
catch (EPStatementException ex)
{
assertEquals("Error starting statement: Plug-in aggregation function 'concat' failed validation: Invalid parameter type 'java.lang.Integer', expecting string [select * from com.espertech.esper.support.bean.SupportBean group by concat(1)]", ex.getMessage());
}
try
{
String text = "select * from " + SupportBean.class.getName() + " group by concat(1, 1)";
epService.getEPAdministrator().createEPL(text);
}
catch (EPStatementException ex)
{
assertEquals("Error starting statement: Plug-in aggregation function 'concat' failed validation: Invalid parameter type 'java.lang.Integer', expecting string [select * from com.espertech.esper.support.bean.SupportBean group by concat(1, 1)]", ex.getMessage());
}
}
public void testInvalidUse()
{
Configuration configuration = SupportConfigFactory.getConfiguration();
configuration.addPlugInAggregationFunction("xxx", String.class.getName());
configuration.addPlugInAggregationFunction("yyy", "com.NoSuchClass");
epService = EPServiceProviderManager.getDefaultProvider(configuration);
epService.initialize();
try
{
String text = "select * from " + SupportBean.class.getName() + " group by xxx(1)";
epService.getEPAdministrator().createEPL(text);
}
catch (EPStatementException ex)
{
assertEquals("Error in expression: Error resolving aggregation: Aggregation class by name 'java.lang.String' does not subclass AggregationSupport [select * from com.espertech.esper.support.bean.SupportBean group by xxx(1)]", ex.getMessage());
}
try
{
String text = "select * from " + SupportBean.class.getName() + " group by yyy(1)";
epService.getEPAdministrator().createEPL(text);
}
catch (EPStatementException ex)
{
assertEquals("Error in expression: Error resolving aggregation: Could not load aggregation class by name 'com.NoSuchClass' [select * from com.espertech.esper.support.bean.SupportBean group by yyy(1)]", ex.getMessage());
}
}
public void testInvalidConfigure()
{
tryInvalidConfigure("a b", "MyClass");
tryInvalidConfigure("abc", "My Class");
// configure twice
try
{
epService.getEPAdministrator().getConfiguration().addPlugInAggregationFunction("concatstring", MyConcatAggregationFunction.class.getName());
fail();
}
catch (ConfigurationException ex)
{
// expected
}
}
private void tryInvalidConfigure(String funcName, String className)
{
try
{
epService.getEPAdministrator().getConfiguration().addPlugInAggregationFunction(funcName, className);
fail();
}
catch (ConfigurationException ex)
{
// expected
}
}
public void testInvalid()
{
tryInvalid("select xxx(theString) from " + SupportBean.class.getName(),
"Error starting statement: Unknown single-row function, aggregation function or mapped or indexed property named 'xxx' could not be resolved [select xxx(theString) from com.espertech.esper.support.bean.SupportBean]");
}
private void tryInvalid(String stmtText, String expectedMsg)
{
try
{
epService.getEPAdministrator().createEPL(stmtText);
fail();
}
catch (EPStatementException ex)
{
assertEquals(expectedMsg, ex.getMessage());
}
}
public static class MyAggFuncFactory implements AggregationFunctionFactory {
private static int instanceCount;
public static int getInstanceCount() {
return instanceCount;
}
public void setFunctionName(String functionName) {
}
public void validate(AggregationValidationContext validationContext) {
}
public AggregationMethod newAggregator() {
instanceCount++;
return new MyAggFuncMethod();
}
public Class getValueType() {
return SupportBean.class;
}
}
public static class MyAggFuncMethod implements AggregationMethod {
private int count;
public void enter(Object value) {
count++;
}
public void leave(Object value) {
count--;
}
public Object getValue() {
return new SupportBean("XX", count);
}
public Class getValueType() {
return SupportBean.class;
}
public void clear() {
count = 0;
}
}
}