I have different specifications classes:
public class UserSpecification implements Specification<ApplicationUser> {
private SearchCriteria criteria;
public UserSpecification(SearchCriteria criteria) {
this.criteria = criteria;
}
@SuppressWarnings("unchecked")
@Override
public Predicate toPredicate(Root<ApplicationUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
...
}
}
public class HotelSpecification implements Specification<Hotel> {
private SearchCriteria criteria;
public HotelSpecification(SearchCriteria criteria) {
this.criteria = criteria;
}
@SuppressWarnings("unchecked")
@Override
public Predicate toPredicate(Root<Hotel> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
...
}
}
So I try to use a generic builder to compose specifications of the same type because the builder class is 99% duplicate which only differs in class type.
public class MySpecificationBuilder {
private final List<SearchCriteria> params;
public MySpecificationBuilder () {
params = new ArrayList<>();
}
public MySpecificationBuilder with(String key, String value) {
params.add(new SearchCriteria(key, value));
return this;
}
public Specification<?> build() {
if (params.size() == 0) {
return null;
}
List<Specification<?>> specs = new ArrayList<>();
for (SearchCriteria param : params) {
specs.add(new UserSpecification(param)); //how to make here generic
}
Specification<?> result = specs.get(0);
for (int i = 1; i < specs.size(); i++) {
result = Specification.where(result).and(specs.get(i)); //warning 1
}
return result;
}
}
I would like to know if it encourages/it's possible to use a generic specification builder. If so, how do I create a generic builder for different specifications?
