package org.radargun.service; import java.util.ArrayList; import com.hazelcast.mapreduce.aggregation.Aggregation; import com.hazelcast.mapreduce.aggregation.Aggregations; import com.hazelcast.mapreduce.aggregation.PropertyExtractor; import com.hazelcast.mapreduce.aggregation.Supplier; import com.hazelcast.query.Predicate; import org.radargun.traits.Query; import static org.radargun.service.HazelcastQuery.getAccessor; public class HazelcastAggregationQuery implements Query { private final PropertyExtractor propertyExtractor; Aggregation aggregation; Supplier supplier; public HazelcastAggregationQuery(Class<?> clazz, Predicate predicate, SelectExpression aggregatedAttribute) { HazelcastQuery.Accessor accessor = getAccessor(clazz, aggregatedAttribute.attribute); propertyExtractor = new ReflexivePropertyExtractor(accessor); Supplier reflexiveSupplier = Supplier.all(propertyExtractor); if (predicate != null) { supplier = Supplier.fromPredicate(predicate, reflexiveSupplier); } else { supplier = reflexiveSupplier; } AggregationFunction function = aggregatedAttribute.function; String type = accessor.getReturnType().getSimpleName(); aggregation = null; if (function == AggregationFunction.NONE) throw new IllegalStateException("Aggregated query needs an aggregation!"); if (function == AggregationFunction.COUNT) aggregation = Aggregations.count(); if (function == AggregationFunction.SUM && (type.equals("Integer") || type.equals("int"))) aggregation = Aggregations.integerSum(); if (function == AggregationFunction.SUM && type.equalsIgnoreCase("double")) aggregation = Aggregations.doubleSum(); if (function == AggregationFunction.SUM && type.equalsIgnoreCase("long")) aggregation = Aggregations.longSum(); if (function == AggregationFunction.AVG && (type.equals("Integer") || type.equals("int"))) aggregation = Aggregations.integerAvg(); if (function == AggregationFunction.AVG && type.equalsIgnoreCase("double")) aggregation = Aggregations.doubleAvg(); if (function == AggregationFunction.AVG && type.equalsIgnoreCase("long")) aggregation = Aggregations.longAvg(); if (function == AggregationFunction.MAX && (type.equals("Integer") || type.equals("int"))) aggregation = Aggregations.integerMax(); if (function == AggregationFunction.MAX && type.equalsIgnoreCase("double")) aggregation = Aggregations.doubleMax(); if (function == AggregationFunction.MAX && type.equalsIgnoreCase("long")) aggregation = Aggregations.longMax(); if (function == AggregationFunction.MAX && type.equals("String")) aggregation = Aggregations.comparableMax(); if (function == AggregationFunction.MIN && (type.equals("Integer") || type.equals("int"))) aggregation = Aggregations.integerMin(); if (function == AggregationFunction.MIN && type.equalsIgnoreCase("double")) aggregation = Aggregations.doubleMin(); if (function == AggregationFunction.MIN && type.equalsIgnoreCase("long")) aggregation = Aggregations.longMin(); if (function == AggregationFunction.MIN && type.equals("String")) aggregation = Aggregations.comparableMin(); } @Override public Query.Result execute(Context context) { HazelcastQuery.Context impl = (HazelcastQuery.Context) context; ArrayList result = new ArrayList<>(); result.add(impl.map.aggregate(supplier, aggregation)); return new HazelcastQuery.Result(result, 0, null); } private static class ReflexivePropertyExtractor<T> implements PropertyExtractor<Object, T> { private HazelcastQuery.Accessor accessor; public ReflexivePropertyExtractor(HazelcastQuery.Accessor accessor) { this.accessor = accessor; } public T extract(Object value) { return (T) accessor.get(value); } } }