package org.jooq.lambda;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
abstract class Sum<N> {
long count;
void add(Sum<N> sum) {
add0(sum.result());
count += sum.count;
}
void add(N value) {
add0(value);
count += 1;
}
void and(Sum<N> sum) {
and0(sum.result());
}
void and(N value) {
and0(value);
}
void or(Sum<N> sum) {
or0(sum.result());
}
void or(N value) {
or0(value);
}
abstract void add0(N value);
abstract void and0(N value);
abstract void or0(N value);
abstract N result();
abstract N avg();
@SuppressWarnings({ "unchecked", "rawtypes" })
static <N> Sum<N> create(N value) {
Sum<N> result;
if (value instanceof Byte)
result = (Sum) new OfByte();
else if (value instanceof Short)
result = (Sum) new OfShort();
else if (value instanceof Integer)
result = (Sum) new OfInt();
else if (value instanceof Long)
result = (Sum) new OfLong();
else if (value instanceof Float)
result = (Sum) new OfFloat();
else if (value instanceof Double)
result = (Sum) new OfDouble();
else if (value instanceof BigInteger)
result = (Sum) new OfBigInteger();
else if (value instanceof BigDecimal)
result = (Sum) new OfBigDecimal();
else
throw new IllegalArgumentException("Cannot calculate sums for value : " + value);
result.add(value);
return result;
}
static class OfByte extends Sum<Byte> {
byte result;
@Override
void add0(Byte value) {
result += value;
}
@Override
Byte result() {
return result;
}
@Override
void and0(Byte value) {
result &= value;
}
@Override
void or0(Byte value) {
result |= value;
}
@Override
Byte avg() {
return (byte) (result / count);
}
}
static class OfShort extends Sum<Short> {
short sum;
@Override
void add0(Short value) {
sum += value;
}
@Override
void and0(Short value) {
sum &= value;
}
@Override
void or0(Short value) {
sum |= value;
}
@Override
Short result() {
return sum;
}
@Override
Short avg() {
return (short) (sum / count);
}
}
static class OfInt extends Sum<Integer> {
int sum;
@Override
void add0(Integer value) {
sum += value;
}
@Override
void and0(Integer value) {
sum &= value;
}
@Override
void or0(Integer value) {
sum |= value;
}
@Override
Integer result() {
return sum;
}
@Override
Integer avg() {
return (int) (sum / count);
}
}
static class OfLong extends Sum<Long> {
long sum;
@Override
void add0(Long value) {
sum += value;
}
@Override
void and0(Long value) {
sum &= value;
}
@Override
void or0(Long value) {
sum |= value;
}
@Override
Long result() {
return sum;
}
@Override
Long avg() {
return sum / count;
}
}
static class OfFloat extends Sum<Float> {
float sum;
@Override
void add0(Float value) {
sum += value;
}
@Override
void and0(Float value) {
throw new UnsupportedOperationException();
}
@Override
void or0(Float value) {
throw new UnsupportedOperationException();
}
@Override
Float result() {
return sum;
}
@Override
Float avg() {
return sum / (float) count;
}
}
static class OfDouble extends Sum<Double> {
double sum;
@Override
void add0(Double value) {
sum += value;
}
@Override
void and0(Double value) {
throw new UnsupportedOperationException();
}
@Override
void or0(Double value) {
throw new UnsupportedOperationException();
}
@Override
Double result() {
return sum;
}
@Override
Double avg() {
return sum / (double) count;
}
}
static class OfBigInteger extends Sum<BigInteger> {
BigInteger sum = BigInteger.ZERO;
@Override
void add0(BigInteger value) {
sum = sum.add(value);
}
@Override
void and0(BigInteger value) {
throw new UnsupportedOperationException();
}
@Override
void or0(BigInteger value) {
throw new UnsupportedOperationException();
}
@Override
BigInteger result() {
return sum;
}
@Override
BigInteger avg() {
return sum.divide(BigInteger.valueOf(count));
}
}
static class OfBigDecimal extends Sum<BigDecimal> {
BigDecimal sum = BigDecimal.ZERO;
@Override
void add0(BigDecimal value) {
sum = sum.add(value);
}
@Override
void and0(BigDecimal value) {
throw new UnsupportedOperationException();
}
@Override
void or0(BigDecimal value) {
throw new UnsupportedOperationException();
}
@Override
BigDecimal result() {
return sum;
}
@Override
BigDecimal avg() {
return sum.divide(BigDecimal.valueOf(count), RoundingMode.HALF_EVEN);
}
}
}