I wrote the code and would like to change it to more readable and elegant:
@Repository
public class ProductRepositoryImpl implements ProductCustomRepository {
private static final int MORE_THEN_RESULT = 1;
@PersistenceContext
private EntityManager em;
public List<Product> findByFilter(Filter filter) {
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<Product> cq = cb.createQuery(Product.class);
final Root<Product> from = cq.from(Product.class);
try {
final List<Predicate> predicates = createPredicatesByFilter(cb, from, filter);
if (!CollectionUtils.isEmpty(predicates)) {
cq.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
}
} catch (RuntimeException e) {
return Collections.emptyList();
}
cq.select(from);
return em.createQuery(cq).getResultList();
}
private List<Predicate> createPredicatesByFilter(CriteriaBuilder cb, Root<Product> from, Filter filter) {
final List<Predicate> predicates = new ArrayList<>();
if (!StringUtils.isEmpty(filter.getName())) {
predicates.add(cb.like(cb.lower(from.<String>get("name")), filter.getName().toLowerCase() + "%"));
}
final BigDecimal priceBefore = filter.getPriceBefore();
final BigDecimal priceAfter = filter.getPriceAfter();
if (priceBefore != null && priceAfter != null) {
if (priceBefore.compareTo(priceAfter) != MORE_THEN_RESULT) {
predicates.add(cb.between(from.<BigDecimal>get("price"), priceBefore, priceAfter));
} else {
throw new RuntimeException();
}
} else if (priceBefore != null) {
predicates.add(cb.gt(from.<BigDecimal>get("price"), priceBefore));
} else if (priceAfter != null) {
predicates.add(cb.lt(from.<BigDecimal>get("price"), priceAfter));
}
if (!StringUtils.isEmpty(filter.getCategory())) {
predicates.add(cb.like(cb.lower(from.<Category>get("category").<String>get("name")), filter.getCategory().toLowerCase() + "%"));
}
return predicates;
}
}