package streamcruncher.test.func.generic;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import org.testng.Assert;
import streamcruncher.api.DBName;
import streamcruncher.api.StreamCruncherException;
import streamcruncher.api.aggregator.AbstractAggregator;
import streamcruncher.api.aggregator.AbstractAggregatorHelper;
import streamcruncher.api.artifact.RowSpec;
import streamcruncher.api.artifact.RowSpec.Info;
import streamcruncher.test.func.BatchResult;
/*
* Author: Ashwin Jayaprakash Date: Oct 3, 2006 Time: 10:55:32 PM
*/
/**
* This Test lists all the Aggregate Functions that are available. It also shows
* how the create and plug in a custom Aggregate Function.
*/
public abstract class TimeWF2PartitionAggTest extends OrderGeneratorTest {
@Override
protected void beforeQueryParse() {
try {
cruncher.registerAggregator(new TestAggregatorHelper());
}
catch (StreamCruncherException e) {
throw new RuntimeException(e);
}
}
@Override
protected String[] getResultColumnNames() {
return new String[] { "country", "avg_qty", "num_skus", "geo_qty", "kurt_qty", "max_skus",
"median_qty", "min_skus", "skew_qty", "std_qty", "sum_qty", "sumsq_qty", "var_qty",
"test_fn_val" };
}
@Override
protected String[] getColumnTypes() {
/*
* "country", "state", "city", "item_sku", "item_qty", "order_time",
* "order_id"
*/
return new String[] { RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 15),
RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 15),
RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 15),
RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 15),
java.lang.Integer.class.getName(), java.sql.Timestamp.class.getName(),
java.lang.Long.class.getName() };
}
@Override
protected String[] getResultColumnTypes() {
return new String[] { RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 15),
java.lang.Double.class.getName(), java.lang.Integer.class.getName(),
java.lang.Double.class.getName(), java.lang.Double.class.getName(),
RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 15),
java.lang.Double.class.getName(),
RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 15),
java.lang.Double.class.getName(), java.lang.Double.class.getName(),
java.lang.Double.class.getName(), java.lang.Double.class.getName(),
java.lang.Double.class.getName(),
RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 15), };
}
@Override
protected String getRQL() {
String csv = getRQLColumnsCSV();
return "select "
+ csv
+ " from test (partition by country store last 5 seconds"
+ " with avg(item_qty) as avg_qty, count(item_sku) as num_skus"
+ ", geomean(item_qty) as geo_qty, kurtosis(item_qty) as kurt_qty, max(item_sku) as max_skus"
+ ", median(item_qty) as median_qty, min(item_sku) as min_skus, skewness(item_qty) as skew_qty"
+ ", stddev(item_qty) as std_qty, sum(item_qty) as sum_qty"
+ ", sumsq(item_qty) as sumsq_qty, variance(item_qty) as var_qty"
+ ", custom(test_fn, order_id, J) as test_fn_val)"
+ " as testStr where testStr.$row_status is new order by country;";
}
@Override
protected void verify(List<BatchResult> results) {
HashMap<String, Integer> countryVsCount = new HashMap<String, Integer>();
HashMap<String, Double> countryVsAvg = new HashMap<String, Double>();
System.out.println("--Results--");
for (BatchResult result : results) {
System.out.println("Batch created at: " + new Timestamp(result.getTimestamp())
+ ". Rows: " + result.getRows().size());
List<Object[]> rows = result.getRows();
System.out.println(" Batch results");
for (Object[] objects : rows) {
System.out.print(" ");
int i = 0;
String[] colNames = getResultColumnNames();
for (Object object : objects) {
if (i > 0) {
System.out.print("(" + colNames[i - 1] + ") ");
}
System.out.print(object + " ");
i++;
}
/*
* "country", "avg_qty", "num_skus", "geo_qty", "kurt_qty",
* "max_skus", "median_qty", "min_skus", "skew_qty", "std_qty",
* "sum_qty", "sumsq_qty", "var_qty", "test_fn_val".
*/
String country = (String) objects[0];
double avg = ((Number) objects[1]).doubleValue();
int count = ((Number) objects[2]).intValue();
double sum = ((Number) objects[10]).doubleValue();
Integer oldCount = countryVsCount.get(country);
if (oldCount != null && oldCount.intValue() == count) {
Assert.fail("For Country: " + country + ", new count: " + count
+ " is still the same as old: " + oldCount);
}
countryVsCount.put(country, count);
Double oldAvg = countryVsAvg.get(country);
if (oldAvg != null && oldAvg.doubleValue() == avg) {
Assert.fail("For Country: " + country + ", new avg: " + avg
+ " is still the same as old: " + oldAvg);
}
countryVsAvg.put(country, oldAvg);
double derivedSum = sum / (1.0 * count);
Assert.assertEquals(derivedSum, avg, "Average and Sum/Count are not the same.");
System.out.println();
}
int totalCount = 0;
for (Integer count : countryVsCount.values()) {
totalCount = totalCount + count;
}
if (totalCount > getMaxDataRows()) {
Assert.fail("Total count:" + totalCount + " cannot be greated than the max rows: "
+ getMaxDataRows());
}
}
}
// ----------
public static class TestAggregatorHelper extends AbstractAggregatorHelper {
public TestAggregatorHelper() {
super("test_fn", TestAggregator.class);
}
@Override
public String getAggregatedColumnDDLFragment(DBName dbName, String[] params,
LinkedHashMap<String, String> columnNamesAndTypes) throws Exception {
return RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 2);
}
}
/**
* Adds up the int-values of the Order-Id's in the Window and then converts
* the sum into a char.
*/
public static class TestAggregator extends AbstractAggregator {
private int columnPosition;
private int sumOfOrderIds;
private char suffix;
@Override
public void init(String[] params, LinkedHashMap<String, String> columnNamesAndTypes,
AggregationStage aggregationStage) {
super.init(params, columnNamesAndTypes, aggregationStage);
for (String column : columnNamesAndTypes.keySet()) {
if (params[0].equalsIgnoreCase(column)) {
break;
}
columnPosition++;
}
suffix = params[1].charAt(0);
}
@Override
public String aggregate(List<Object[]> removedValues, List<Object[]> addedValues) {
if (removedValues != null && getAggregationStage() != AggregationStage.ENTRANCE) {
for (Object[] objects : removedValues) {
Object object = objects[columnPosition];
// Consider only non-nulls.
if (object != null && object instanceof Long) {
Long l = (Long) object;
sumOfOrderIds = sumOfOrderIds - l.intValue();
}
}
}
if (addedValues != null) {
for (Object[] objects : addedValues) {
Object object = objects[columnPosition];
// Consider only non-nulls.
if (object != null && object instanceof Long) {
Long l = (Long) object;
sumOfOrderIds = sumOfOrderIds + l.intValue();
}
}
}
int i = (sumOfOrderIds % 26) + 65;
char c = (char) i;
return new String(new char[] { c, suffix });
}
}
}