LogicalBinaryAggregator.java
package redis.clients.jedis.executors.aggregators;
import redis.clients.jedis.exceptions.UnsupportedAggregationException;
import java.util.ArrayList;
/**
* Abstract base class for logical binary operations (AND, OR). Supports Boolean, Long,
* ArrayList<Boolean>, ArrayList<Long>.
*/
abstract class LogicalBinaryAggregator<T> implements Aggregator<T, T> {
private T result;
private final String operationName;
protected LogicalBinaryAggregator(String operationName) {
this.operationName = operationName;
}
@Override
public void add(T input) {
if (input == null) {
return; // ignore nulls
}
if (result == null) {
// First non-null input initializes the result
if (input instanceof Boolean || input instanceof Long || input instanceof ArrayList) {
result = input;
return;
} else {
throw new UnsupportedAggregationException(operationName
+ " requires Boolean, Long, ArrayList<Boolean>, or ArrayList<Long>, but got: "
+ input.getClass().getName());
}
}
// Handle Boolean
if (result instanceof Boolean && input instanceof Boolean) {
result = (T) Boolean.valueOf(applyBooleanOp((Boolean) result, (Boolean) input));
return;
}
// Handle Long
if (result instanceof Long && input instanceof Long) {
boolean existingBool = (Long) result != 0;
boolean newBool = (Long) input != 0;
result = (T) Long.valueOf(applyBooleanOp(existingBool, newBool) ? 1L : 0L);
return;
}
// Handle ArrayList
if (result instanceof ArrayList && input instanceof ArrayList) {
ArrayList<?> existingList = (ArrayList<?>) result;
ArrayList<?> newList = (ArrayList<?>) input;
if (existingList.size() != newList.size()) {
throw new UnsupportedAggregationException(
operationName + " requires ArrayLists of equal size, but got sizes: "
+ existingList.size() + " and " + newList.size());
}
if (!existingList.isEmpty()) {
Object firstExisting = existingList.get(0);
Object firstNew = newList.get(0);
// ArrayList<Boolean>
if (firstExisting instanceof Boolean && firstNew instanceof Boolean) {
ArrayList<Boolean> res = new ArrayList<>(existingList.size());
for (int i = 0; i < existingList.size(); i++) {
res.add(applyBooleanOp((Boolean) existingList.get(i), (Boolean) newList.get(i)));
}
result = (T) res;
return;
}
// ArrayList<Long> treated as boolean
if (firstExisting instanceof Long && firstNew instanceof Long) {
ArrayList<Long> res = new ArrayList<>(existingList.size());
for (int i = 0; i < existingList.size(); i++) {
boolean e = ((Long) existingList.get(i)) != 0;
boolean n = ((Long) newList.get(i)) != 0;
res.add(applyBooleanOp(e, n) ? 1L : 0L);
}
result = (T) res;
return;
}
} else {
// Empty lists ��� result remains empty list
result = (T) new ArrayList<>();
return;
}
}
throw new UnsupportedAggregationException(
operationName + " requires Boolean, Long, ArrayList<Boolean>, or ArrayList<Long>, but got: "
+ result.getClass().getName() + " and " + input.getClass().getName());
}
@Override
public T getResult() {
return result;
}
/**
* Template method for subclasses to implement the specific logical operation.
* @param a first boolean operand
* @param b second boolean operand
* @return result of the logical operation
*/
protected abstract boolean applyBooleanOp(boolean a, boolean b);
}