in cayenne/src/main/java/org/apache/cayenne/exp/parser/Evaluator.java [79:292]
static {
evaluators = new ConcurrentHashMap<>();
NULL_LHS_EVALUATOR = new Evaluator() {
@Override
Integer compare(Object lhs, Object rhs) {
return null;
}
@Override
boolean eq(Object lhs, Object rhs) {
return rhs == null;
}
};
DEFAULT_EVALUATOR = new NonNullLhsEvaluator(new Evaluator() {
@Override
boolean eq(Object lhs, Object rhs) {
return lhs.equals(rhs);
}
@Override
Integer compare(Object lhs, Object rhs) {
return null;
}
});
PERSISTENT_EVALUATOR = new NonNullLhsEvaluator(new Evaluator() {
@Override
Integer compare(Object lhs, Object rhs) {
return null;
}
@Override
boolean eq(Object lhs, Object rhs) {
Persistent lhsPersistent = (Persistent) lhs;
if (rhs instanceof Persistent) {
return lhsPersistent.getObjectId().equals(((Persistent) rhs).getObjectId());
}
if (rhs instanceof ObjectId) {
return lhsPersistent.getObjectId().equals(rhs);
}
if (rhs instanceof Map) {
return lhsPersistent.getObjectId().getIdSnapshot().equals(rhs);
}
if (lhsPersistent.getObjectId().getIdSnapshot().size() != 1) {
// the only options left below are for the single key IDs
return false;
}
if (rhs instanceof Number) {
// only care about whole numbers
if (rhs instanceof Integer) {
return Cayenne.longPKForObject(lhsPersistent) == ((Number) rhs).longValue();
}
if (rhs instanceof Long) {
return Cayenne.longPKForObject(lhsPersistent) == ((Number) rhs).longValue();
}
}
return Cayenne.pkForObject(lhsPersistent).equals(rhs);
}
});
BIG_DECIMAL_EVALUATOR = new NonNullLhsEvaluator(new Evaluator() {
@Override
Integer compare(Object lhs, Object rhs) {
return ((BigDecimal) lhs).compareTo(ConversionUtil.toBigDecimal(rhs));
}
@Override
boolean eq(Object lhs, Object rhs) {
// BigDecimals must be compared using compareTo (see CAY-280 and BigDecimal.equals JavaDoc)
Integer c = compare(lhs, rhs);
return c == 0;
}
});
NUMBER_EVALUATOR = new NonNullLhsEvaluator(new Evaluator() {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
Integer compare(Object lhs, Object rhs) {
return compareNumbers((Number)lhs, rhs);
}
@Override
boolean eq(Object lhs, Object rhs) {
return equalNumbers((Number)lhs, rhs);
}
private final List WHOLE_NUMBER_CLASSES = Arrays.asList(Byte.class, Short.class, Integer.class, AtomicInteger.class, Long.class, AtomicLong.class, BigInteger.class);
/**
* Returns the widest primitive wrapper class given the two operands, used in preparation for
* comparing two boxed numbers of different types, like java.lang.Short and java.lang.Integer.
*/
Class<?> widestNumberType(Number lhs, Number rhs) {
if (lhs.getClass().equals(rhs.getClass())) return lhs.getClass();
int lhsIndex = WHOLE_NUMBER_CLASSES.indexOf(lhs.getClass());
int rhsIndex = WHOLE_NUMBER_CLASSES.indexOf(rhs.getClass());
Class<?> widestClass;
if (lhsIndex != -1 && rhsIndex != -1) {
widestClass = (Class<?>) WHOLE_NUMBER_CLASSES.get(Math.max(lhsIndex, rhsIndex));
} else {
widestClass = Double.class;
}
return widestClass;
}
/**
* Enables equality tests for two boxed numbers of different types, like java.lang.Short and java.lang.Integer.
*/
boolean equalNumbers(Number lhs, Object _rhs) {
if (!Number.class.isAssignableFrom(_rhs.getClass())) {
return lhs.equals(_rhs);
}
Number rhs = (Number) _rhs;
Class<?> widestClass = widestNumberType(lhs, rhs);
if (Integer.class.equals(widestClass) || AtomicInteger.class.equals(widestClass)) {
return lhs.intValue() == rhs.intValue();
} else if (Long.class.equals(widestClass) || AtomicLong.class.equals(widestClass)) {
return lhs.longValue() == rhs.longValue();
} else if (Double.class.equals(widestClass)) {
return Math.abs(lhs.doubleValue() - rhs.doubleValue()) < EPSILON;
} else if (Short.class.equals(widestClass)) {
return lhs.shortValue() == rhs.shortValue();
} else if (BigInteger.class.equals(widestClass)) {
return lhs.toString().equals(rhs.toString());
} else {
return lhs.equals(rhs);
}
}
/**
* Enables comparison of two boxed numbers of different types, like java.lang.Short and java.lang.Integer.
*/
Integer compareNumbers(Number lhs, Object _rhs) {
if (!Number.class.isAssignableFrom(_rhs.getClass())) {
return null;
}
Number rhs = (Number) _rhs;
Class widestClass = widestNumberType(lhs, rhs);
if (Integer.class.equals(widestClass) || AtomicInteger.class.equals(widestClass)) {
return Integer.valueOf(lhs.intValue()).compareTo(rhs.intValue());
} else if (Long.class.equals(widestClass) || AtomicLong.class.equals(widestClass)) {
return Long.valueOf(lhs.longValue()).compareTo(rhs.longValue());
} else if (Double.class.equals(widestClass)) {
boolean areEqual = Math.abs(lhs.doubleValue() - rhs.doubleValue()) < EPSILON;
return areEqual ? 0 : Double.compare(lhs.doubleValue(), rhs.doubleValue());
} else if (Float.class.equals(widestClass)) {
boolean areEqual = Math.abs(lhs.floatValue() - rhs.floatValue()) < EPSILON;
return areEqual ? 0 : Float.compare(lhs.floatValue(), rhs.floatValue());
} else if (Short.class.equals(widestClass)) {
return Short.valueOf(lhs.shortValue()).compareTo(rhs.shortValue());
} else if (Byte.class.equals(widestClass)) {
return Byte.valueOf(lhs.byteValue()).compareTo(rhs.byteValue());
} else if (BigInteger.class.equals(widestClass)) {
BigInteger left = lhs instanceof BigInteger ? (BigInteger)lhs : new BigInteger(lhs.toString());
BigInteger right = rhs instanceof BigInteger ? (BigInteger)rhs : new BigInteger(rhs.toString());
return left.compareTo(right);
} else if (Comparable.class.isAssignableFrom(lhs.getClass())) {
return ((Comparable)lhs).compareTo(rhs);
} else {
return null;
}
}
});
COMPARABLE_EVALUATOR = new NonNullLhsEvaluator(new Evaluator() {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
Integer compare(Object lhs, Object rhs) {
return ((Comparable) lhs).compareTo(ConversionUtil.toComparable(rhs));
}
@Override
boolean eq(Object lhs, Object rhs) {
return lhs.equals(rhs);
}
});
}