/*
***************************************************************************************
* 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.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.metrics.instrumentation.InstrumentationHelper;
import com.espertech.esper.supportregression.bean.SupportBean;
import com.espertech.esper.supportregression.bean.SupportBean_A;
import com.espertech.esper.supportregression.client.SupportConfigFactory;
import com.espertech.esper.supportregression.epl.*;
import com.espertech.esper.supportregression.util.SupportMessageAssertUtil;
import com.espertech.esper.supportregression.util.SupportModelHelper;
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.addPlugInAggregationFunctionFactory("concatstring", MyConcatAggregationFunctionFactory.class.getName());
configuration.addPlugInAggregationFunctionFactory("concatstringTwo", MyConcatTwoAggFunctionFactory.class.getName());
configuration.getEngineDefaults().getThreading().setEngineFairlock(true);
epService = EPServiceProviderManager.getProvider("TestAggregationFunctionPlugIn", configuration);
epService.initialize();
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.startTest(epService, this.getClass(), getName());}
}
public void tearDown()
{
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.endTest();}
epService.initialize();
}
public void testGrouped() throws Exception
{
String textOne = "select irstream CONCATSTRING(theString) as val from " + SupportBean.class.getName() + "#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() + "#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() + "#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(null, "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() + "#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() + "#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#lastevent, SupportBean unidirectional");
}
catch (EPStatementException ex) {
SupportMessageAssertUtil.assertMessage(ex, "Error starting statement: Failed to validate select-clause expression 'concatstring(*)': The 'concatstring' aggregation function requires that in joins or subqueries the stream-wildcard (stream-alias.*) syntax is used instead");
}
// 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().addPlugInAggregationFunctionFactory("countback", SupportPluginAggregationMethodOneFactory.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().addPlugInAggregationFunctionFactory("countboundary", SupportPluginAggregationMethodThreeFactory.class.getName());
runAssertionMultipleParams(false);
runAssertionMultipleParams(true);
}
private void runAssertionMultipleParams(boolean soda) {
String text = "select irstream countboundary(1,10,intPrimitive,*) as val from " + SupportBean.class.getName();
EPStatement statement = SupportModelHelper.createByCompileOrParse(epService, soda, text);
SupportUpdateListener listener = new SupportUpdateListener();
statement.addListener(listener);
AggregationValidationContext validContext = SupportPluginAggregationMethodThreeFactory.getContexts().get(0);
EPAssertionUtil.assertEqualsExactOrder(new Class[]{Integer.class, Integer.class, int.class, SupportBean.class}, validContext.getParameterTypes());
EPAssertionUtil.assertEqualsExactOrder(new Object[]{1, 10, null, null}, validContext.getConstantValues());
EPAssertionUtil.assertEqualsExactOrder(new boolean[]{true, true, false, false}, validContext.getIsConstantValue());
SupportBean e1 = new SupportBean("E1", 5);
epService.getEPRuntime().sendEvent(e1);
EPAssertionUtil.assertPropsPerRow(listener.assertInvokedAndReset(), "val", new Object[] {1}, new Object[] {0});
EPAssertionUtil.assertEqualsExactOrder(new Object[] {1, 10, 5, e1}, SupportPluginAggregationMethodThree.getLastEnterParameters());
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});
epService.getEPAdministrator().destroyAllStatements();
}
public void testNoSubnodesRuntimeAdd()
{
epService.getEPAdministrator().getConfiguration().addPlugInAggregationFunctionFactory("countback", SupportPluginAggregationMethodOneFactory.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.addPlugInAggregationFunctionFactory("concat", SupportPluginAggregationMethodTwoFactory.class.getName());
epService = EPServiceProviderManager.getDefaultProvider(configuration);
epService.initialize();
try
{
String text = "select concat(1) from " + SupportBean.class.getName();
epService.getEPAdministrator().createEPL(text);
}
catch (EPStatementException ex)
{
SupportMessageAssertUtil.assertMessage(ex, "Error starting statement: Failed to validate select-clause expression 'concat(1)': Plug-in aggregation function 'concat' failed validation: Invalid parameter type 'java.lang.Integer', expecting string [");
}
}
public void testInvalidUse()
{
Configuration configuration = SupportConfigFactory.getConfiguration();
configuration.addPlugInAggregationFunctionFactory("xxx", String.class.getName());
configuration.addPlugInAggregationFunctionFactory("yyy", "com.NoSuchClass");
epService = EPServiceProviderManager.getDefaultProvider(configuration);
epService.initialize();
SupportMessageAssertUtil.tryInvalid(epService, "select * from " + SupportBean.class.getName() + " group by xxx(1)",
"Error in expression: Error resolving aggregation: Aggregation class by name 'java.lang.String' does not implement AggregationFunctionFactory");
SupportMessageAssertUtil.tryInvalid(epService, "select * from " + SupportBean.class.getName() + " group by yyy(1)",
"Error in expression: Error resolving aggregation: Could not load aggregation factory class by name 'com.NoSuchClass'");
}
public void testInvalidConfigure()
{
tryInvalidConfigure("a b", "MyClass");
tryInvalidConfigure("abc", "My Class");
// configure twice
try
{
epService.getEPAdministrator().getConfiguration().addPlugInAggregationFunctionFactory("concatstring", MyConcatAggregationFunction.class.getName());
fail();
}
catch (ConfigurationException ex)
{
// expected
}
}
private void tryInvalidConfigure(String funcName, String className)
{
try
{
epService.getEPAdministrator().getConfiguration().addPlugInAggregationFunctionFactory(funcName, className);
fail();
}
catch (ConfigurationException ex)
{
// expected
}
}
public void testInvalid()
{
SupportMessageAssertUtil.tryInvalid(epService, "select xxx(theString) from " + SupportBean.class.getName(),
"Error starting statement: Failed to validate select-clause expression 'xxx(theString)': Unknown single-row function, aggregation function or mapped or indexed property named 'xxx' could not be resolved");
}
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 void clear() {
count = 0;
}
}
}