}
private static Expression toPredicate(Domain domain, QualifiedNameReference reference, Type type)
{
if (domain.getRanges().isNone()) {
return domain.isNullAllowed() ? new IsNullPredicate(reference) : FALSE_LITERAL;
}
if (domain.getRanges().isAll()) {
return domain.isNullAllowed() ? TRUE_LITERAL : new NotExpression(new IsNullPredicate(reference));
}
// Add disjuncts for ranges
List<Expression> disjuncts = new ArrayList<>();
List<Expression> singleValues = new ArrayList<>();
for (Range range : domain.getRanges()) {
checkState(!range.isAll()); // Already checked
if (range.isSingleValue()) {
singleValues.add(toExpression(range.getLow().getValue(), type));
}
else if (isBetween(range)) {
// Specialize the range with BETWEEN expression if possible b/c it is currently more efficient
disjuncts.add(new BetweenPredicate(reference, toExpression(range.getLow().getValue(), type), toExpression(range.getHigh().getValue(), type)));
}
else {
List<Expression> rangeConjuncts = new ArrayList<>();
if (!range.getLow().isLowerUnbounded()) {
switch (range.getLow().getBound()) {
case ABOVE:
rangeConjuncts.add(new ComparisonExpression(GREATER_THAN, reference, toExpression(range.getLow().getValue(), type)));
break;
case EXACTLY:
rangeConjuncts.add(new ComparisonExpression(GREATER_THAN_OR_EQUAL, reference, toExpression(range.getLow().getValue(),
type)));
break;
case BELOW:
throw new IllegalStateException("Low Marker should never use BELOW bound: " + range);
default:
throw new AssertionError("Unhandled bound: " + range.getLow().getBound());
}
}
if (!range.getHigh().isUpperUnbounded()) {
switch (range.getHigh().getBound()) {
case ABOVE:
throw new IllegalStateException("High Marker should never use ABOVE bound: " + range);
case EXACTLY:
rangeConjuncts.add(new ComparisonExpression(LESS_THAN_OR_EQUAL, reference, toExpression(range.getHigh().getValue(), type)));
break;
case BELOW:
rangeConjuncts.add(new ComparisonExpression(LESS_THAN, reference, toExpression(range.getHigh().getValue(), type)));
break;
default:
throw new AssertionError("Unhandled bound: " + range.getHigh().getBound());
}
}
// If rangeConjuncts is null, then the range was ALL, which should already have been checked for
checkState(!rangeConjuncts.isEmpty());
disjuncts.add(combineConjuncts(rangeConjuncts));
}
}
// Add back all of the possible single values either as an equality or an IN predicate
if (singleValues.size() == 1) {
disjuncts.add(new ComparisonExpression(EQUAL, reference, getOnlyElement(singleValues)));
}
else if (singleValues.size() > 1) {
disjuncts.add(new InPredicate(reference, new InListExpression(singleValues)));
}
// Add nullability disjuncts
checkState(!disjuncts.isEmpty());
if (domain.isNullAllowed()) {
disjuncts.add(new IsNullPredicate(reference));
}
return combineDisjunctsWithDefault(disjuncts, TRUE_LITERAL);
}