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;
}
}