public class GenericSpecification<T> implements Specification<T> {
private static final long serialVersionUID = 1900581010229669687L;
private List<SearchCriteria> list;
public GenericSpecification() {
this.list = new ArrayList<>();
}
public void add(SearchCriteria criteria) {
if (criteria.getValue() != null && !criteria.getValue().toString().equals("")) list.add(criteria);
}
private Join<?, ?> recursiveRootBuilder(Join<?, ?> joinColumn, String[] keys, int index) {
if (index == keys.length - 2) return joinColumn;
return recursiveRootBuilder(joinColumn.join(keys[index], JoinType.LEFT), keys, index + 1);
}
private Path<String> getStringPath(Root<T> root, String key) {
if (key.contains(".")) {
String[] fetchKey = key.split("\\.");
String lastKey = fetchKey[fetchKey.length - 1];
return recursiveRootBuilder(root.join(fetchKey[0], JoinType.LEFT), fetchKey, 0).get(lastKey);
}
return root.get(key);
}
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
//create a new predicate list
List<Predicate> predicates = new ArrayList<>();
//add add criteria to predicates
for (SearchCriteria criteria : list) {
Path<String> path = null;
if (criteria.getOperation() != SearchOperation.FETCH) path = getStringPath(root, criteria.getKey());
if (path == null) {
log.warn("No path variable found");
} else
switch (criteria.getOperation()) {
case GREATER_THAN:
predicates.add(builder.greaterThan(
path, criteria.getValue().toString()));
break;
case LESS_THAN:
predicates.add(builder.lessThan(
path, criteria.getValue().toString()));
break;
case GREATER_THAN_EQUAL:
predicates.add(builder.greaterThanOrEqualTo(
path, criteria.getValue().toString()));
break;
case LESS_THAN_EQUAL:
predicates.add(builder.lessThanOrEqualTo(
path, criteria.getValue().toString()));
break;
case NOT_EQUAL:
predicates.add(builder.notEqual(
path, criteria.getValue()));
break;
case EQUAL:
predicates.add(builder.equal(
path, criteria.getValue()));
break;
case MATCH:
predicates.add(builder.like(
builder.lower(path),
"%" + criteria.getValue().toString().toLowerCase() + "%"));
break;
case MATCH_END:
predicates.add(builder.like(
builder.lower(path),
criteria.getValue().toString().toLowerCase() + "%"));
break;
case IN:
List<?> values = (List<?>) criteria.getValue();
if (values.size() > 0) predicates.add(path.in(values));
break;
case FETCH:
break;
default:
throw new RuntimeException("Operation not supported yet");
}
}
return builder.and(predicates.toArray(new Predicate[0]));
}
}
public interface NavigationService {
Page<?> getReportData(Object filterDTO, Pageable pageable);
}
@AllArgsConstructor
public class RecordNavigationManager {
NavigationService m_navigationService;
public ResponseEntity<?> getNavigationResponse(Object searchCriteria, HttpServletRequest request) throws JsonProcessingException {
Page<?> reportData = getNavigationPage(searchCriteria, request);
return new ResponseEntity<>(reportData, HttpStatus.OK);
}
public Page<?> getNavigationPage(Object searchCriteria, HttpServletRequest request) throws JsonProcessingException {
int size = getValueFromRequest(request, "size");
int page = getValueFromRequest(request, "page");
List<Sort.Order> orders = getSortOrders(request);
Pageable pageable = PageRequest.of(page, size, Sort.by(orders));
return m_navigationService.getReportData(searchCriteria, pageable);
}
private List<Sort.Order> getSortOrders(HttpServletRequest request) throws JsonProcessingException {
String[] sort = {"id", "desc"};
String sorts = request.getParameter("sort");
if (sorts != null) {
// String decodeURIComponent = EncodingUtil.decodeURIComponent(sorts);
// sort = new ObjectMapper().readValue(decodeURIComponent,String[].class);
sort = sorts.split(",");
}
List<Sort.Order> orders = new ArrayList<>();
if (sort[0].contains(",")) {
for (String sortOrder : sort) {
String[] _sort = sortOrder.split(",");
orders.add(new Sort.Order(getSortDirection(_sort[1]), _sort[0]));
}
} else {
orders.add(new Sort.Order(getSortDirection(sort[1]), sort[0]));
}
return orders;
}
private int getValueFromRequest(HttpServletRequest request, String param) {
String paramValue = request.getParameter(param);
if (paramValue == null) {
switch (param) {
case "size":
return 10;
case "page":
return 0;
}
}
return Integer.parseInt(paramValue);
}
private Sort.Direction getSortDirection(String direction) {
if (direction.equals("asc")) {
return Sort.Direction.ASC;
} else if (direction.equals("desc")) {
return Sort.Direction.DESC;
}
return Sort.Direction.ASC;
}
}