package org.infinispan.objectfilter.impl.aggregation; import org.infinispan.objectfilter.impl.ql.AggregationFunction; /** * An accumulator is a stateless object that operates on row data. * * @author anistor@redhat.com * @since 8.0 */ public abstract class FieldAccumulator { /** * Input column. */ protected final int inPos; /** * Output column. */ protected final int outPos; protected FieldAccumulator(int inPos, int outPos) { this.inPos = inPos; this.outPos = outPos; } public static void init(Object[] accRow, FieldAccumulator[] accumulators) { for (FieldAccumulator acc : accumulators) { acc.init(accRow); } } public static void update(Object[] srcRow, Object[] accRow, FieldAccumulator[] accumulators) { for (FieldAccumulator acc : accumulators) { acc.update(accRow, srcRow[acc.inPos]); } } public static void merge(Object[] srcRow, Object[] accRow, FieldAccumulator[] acc) { for (FieldAccumulator a : acc) { a.merge(accRow, srcRow[a.inPos]); } } public static void finish(Object[] accRow, FieldAccumulator[] accumulators) { for (FieldAccumulator acc : accumulators) { acc.finish(accRow); } } public void init(Object[] accRow) { } public abstract void update(Object[] accRow, Object value); protected void merge(Object[] accRow, Object value) { update(accRow, value); } protected void finish(Object[] accRow) { } public static FieldAccumulator makeAccumulator(AggregationFunction aggregationType, int inColumn, int outColumn, Class<?> propertyType) { switch (aggregationType) { case SUM: return new SumAccumulator(inColumn, outColumn, propertyType); case AVG: return new AvgAccumulator(inColumn, outColumn, propertyType); case MIN: return new MinAccumulator(inColumn, outColumn, propertyType); case MAX: return new MaxAccumulator(inColumn, outColumn, propertyType); case COUNT: return new CountAccumulator(inColumn, outColumn); default: throw new IllegalArgumentException("Aggregation " + aggregationType.name() + " is not supported"); } } public static Class<?> getOutputType(AggregationFunction aggregationType, Class<?> propertyType) { if (aggregationType == AggregationFunction.AVG) { return Double.class; } else if (aggregationType == AggregationFunction.COUNT) { return Long.class; } else if (aggregationType == AggregationFunction.SUM) { return SumAccumulator.getOutputType(propertyType); } return propertyType; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || o.getClass() != getClass()) return false; FieldAccumulator other = (FieldAccumulator) o; return inPos == other.inPos && outPos == other.outPos; } @Override public int hashCode() { return 31 * inPos + outPos; } }