I'm doing some filtering on database entries and I ended up with somewhat ugly code, which I don't like.
I have my MyFilterResolverFactory
class where I build and return my MyFilterResolver
chain.
public abstract class MyFilterResolver {
protected MyFilterResolver nextResolver = EMPTY;
protected List<Predicate> predicates;
public List<Predicate> resolve(MyFilter filter, CriteriaBuilder cb, Root<MyEntity> root) {
this.predicates = new ArrayList<Predicate>();
resolveFilter(filter, cb, root);
this.predicates.addAll(this.nextResolver.resolve(filter, cb, root));
return this.predicates;
}
protected abstract void resolveFilter(MyFilter filter, CriteriaBuilder cb, Root<MyEntity> root);
public void attachNextResolver(MyFilterResolver nextResolver) {
this.nextResolver = nextResolver;
}
public static MyFilterResolver EMPTY = new MyFilterResolver() {
@Override
public List<Predicate> resolve(MyFilter filter, CriteriaBuilder cb, Root<MyEntity> root) {
return new ArrayList<Predicate>();
}
@Override
protected void resolveFilter(MyFilter filter, CriteriaBuilder cb, Root<MyEntity> root) {
}
};
}
And an ugly, concrete implementation of it:
public class MyDateFilterResolver extends
MyFilterResolver {
@Override
protected void resolveFilter(MyFilter filter, CriteriaBuilder cb,
Root<MyEntity> root) {
if (filter != null) {
Date dateExact = filter.getDateExact();
Date dateAfter = filter.getDateAfter();
Date dateBefore = filter.getDateBefore();
if (dateExact != null) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(dateExact);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Date dayStart = calendar.getTime();
calendar = Calendar.getInstance();
calendar.setTime(dayStart);
calendar.add(Calendar.DATE, 1);
calendar.add(Calendar.MILLISECOND, -1);
Date dayEnd = calendar.getTime();
super.predicates.add(
cb.greaterThanOrEqualTo(
root.get("date").as(Date.class),
dayStart
)
);
super.predicates.add(
cb.lessThanOrEqualTo(
root.get("date").as(Date.class),
dayEnd
)
);
}
if (dateAfter != null) {
super.predicates.add(
cb.greaterThanOrEqualTo(
root.get("date").as(Date.class),
dateAfter
)
);
}
if (dateBefore != null) {
predicates.add(
cb.lessThanOrEqualTo(
root.get("date").as(Date.class),
dateBefore
)
);
}
}
}
}
MyFilter
class is a regular POJO with getters/setters only.
I'd like to get rid of these if (something != null)
checks, but I am not able to see how.
I don't see any reason to. A (poor) alternative would be to use one try/catch, but the if statements are more clear and better performing for the task in which they are used here.