package jpasearch.repository.util; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import jpasearch.repository.query.selector.Range; /** * Helper to create a predicate out of {@link Range}s. */ @SuppressWarnings("unchecked") @Named @Singleton public class ByRangeUtil { @Inject private JpaUtil jpaUtil; public <E> Predicate byRange(Root<E> root, CriteriaBuilder builder, Range<E, ?> range) { if (range.isSet()) { return buildRangePredicate(range, root, builder); } else { return null; } } private <D extends Comparable<? super D>, E> Predicate buildRangePredicate(Range<E, D> range, Root<E> root, CriteriaBuilder builder) { Predicate rangePredicate = null; Path<D> path = jpaUtil.getPath(root, range.getPath()); if (range.isBetween()) { if (range.isIncludeLowerBound() && range.isIncludeHigherBound()) { // assuming between include bounds rangePredicate = builder.between(path, range.getLowerBound(), range.getHigherBound()); } else if (range.isIncludeHigherBound()) { rangePredicate = builder.and(builder.greaterThan(path, range.getLowerBound()), builder.lessThanOrEqualTo(path, range.getHigherBound())); } else if (range.isIncludeLowerBound()) { rangePredicate = builder.and(builder.greaterThanOrEqualTo(path, range.getLowerBound()), builder.lessThan(path, range.getHigherBound())); } else { rangePredicate = builder.and(builder.greaterThan(path, range.getLowerBound()), builder.lessThan(path, range.getHigherBound())); } } else if (range.isLowerBoundSet()) { if (range.isIncludeLowerBound()) { rangePredicate = builder.greaterThanOrEqualTo(path, range.getLowerBound()); } else { rangePredicate = builder.greaterThan(path, range.getLowerBound()); } } else if (range.isHigherBoundSet()) { if (range.isIncludeHigherBound()) { rangePredicate = builder.lessThanOrEqualTo(path, range.getHigherBound()); } else { rangePredicate = builder.lessThan(path, range.getHigherBound()); } } if (rangePredicate != null) { if (TRUE != range.getIncludeNull()) { return rangePredicate; } else { return builder.or(rangePredicate, builder.isNull(path)); } } else { // no from/to is set, but include null or not could be: if (TRUE == range.getIncludeNull()) { return builder.isNull(path); } else if (FALSE == range.getIncludeNull()) { return builder.isNotNull(path); } } return null; } }