[BAEL-9557] - Migrated the spring-rest-query-language to Java 8 idioms

This commit is contained in:
amit2103 2018-10-27 21:10:33 +05:30
parent e31557b2dc
commit 14db73cf02
8 changed files with 142 additions and 82 deletions

View File

@ -1,10 +1,13 @@
package org.baeldung.persistence.dao;
import com.querydsl.core.types.dsl.BooleanExpression;
import org.baeldung.web.util.SearchCriteria;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.baeldung.web.util.SearchCriteria;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
public final class MyUserPredicatesBuilder {
private final List<SearchCriteria> params;
@ -22,21 +25,34 @@ public final class MyUserPredicatesBuilder {
if (params.size() == 0) {
return null;
}
final List<BooleanExpression> predicates = new ArrayList<>();
MyUserPredicate predicate;
for (final SearchCriteria param : params) {
predicate = new MyUserPredicate(param);
final BooleanExpression exp = predicate.getPredicate();
if (exp != null) {
predicates.add(exp);
}
}
BooleanExpression result = predicates.get(0);
for (int i = 1; i < predicates.size(); i++) {
result = result.and(predicates.get(i));
final List<BooleanExpression> predicates = params.stream().map(param -> {
MyUserPredicate predicate = new MyUserPredicate(param);
return predicate.getPredicate();
}).filter(predicate -> predicate != null).collect(Collectors.toCollection(ArrayList::new));
BooleanExpression result = Expressions.asBoolean(true).isTrue();
for (BooleanExpression predicate : predicates) {
result = result.and(predicate);
}
return result;
}
static class BooleanExpressionWrapper {
private BooleanExpression result;
public BooleanExpressionWrapper(final BooleanExpression result) {
super();
this.result = result;
}
public BooleanExpression getResult() {
return result;
}
public void setResult(BooleanExpression result) {
this.result = result;
}
}
}

View File

@ -1,8 +1,6 @@
package org.baeldung.persistence.dao;
import org.baeldung.persistence.model.User;
import org.baeldung.web.util.SearchCriteria;
import org.springframework.stereotype.Repository;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@ -10,7 +8,10 @@ import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.List;
import org.baeldung.persistence.model.User;
import org.baeldung.web.util.SearchCriteria;
import org.springframework.stereotype.Repository;
@Repository
public class UserDAO implements IUserDAO {
@ -25,20 +26,9 @@ public class UserDAO implements IUserDAO {
final Root r = query.from(User.class);
Predicate predicate = builder.conjunction();
for (final SearchCriteria param : params) {
if (param.getOperation().equalsIgnoreCase(">")) {
predicate = builder.and(predicate, builder.greaterThanOrEqualTo(r.get(param.getKey()), param.getValue().toString()));
} else if (param.getOperation().equalsIgnoreCase("<")) {
predicate = builder.and(predicate, builder.lessThanOrEqualTo(r.get(param.getKey()), param.getValue().toString()));
} else if (param.getOperation().equalsIgnoreCase(":")) {
if (r.get(param.getKey()).getJavaType() == String.class) {
predicate = builder.and(predicate, builder.like(r.get(param.getKey()), "%" + param.getValue() + "%"));
} else {
predicate = builder.and(predicate, builder.equal(r.get(param.getKey()), param.getValue()));
}
}
}
UserSearchQueryCriteriaConsumer searchConsumer = new UserSearchQueryCriteriaConsumer(predicate, builder, r);
params.stream().forEach(searchConsumer);
predicate = searchConsumer.getPredicate();
query.where(predicate);
return entityManager.createQuery(query).getResultList();

View File

@ -0,0 +1,43 @@
package org.baeldung.persistence.dao;
import java.util.function.Consumer;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.baeldung.web.util.SearchCriteria;
public class UserSearchQueryCriteriaConsumer implements Consumer<SearchCriteria>{
private Predicate predicate;
private CriteriaBuilder builder;
private Root r;
public UserSearchQueryCriteriaConsumer(Predicate predicate, CriteriaBuilder builder, Root r) {
super();
this.predicate = predicate;
this.builder = builder;
this.r= r;
}
@Override
public void accept(SearchCriteria param) {
if (param.getOperation().equalsIgnoreCase(">")) {
predicate = builder.and(predicate, builder.greaterThanOrEqualTo(r.get(param.getKey()), param.getValue().toString()));
} else if (param.getOperation().equalsIgnoreCase("<")) {
predicate = builder.and(predicate, builder.lessThanOrEqualTo(r.get(param.getKey()), param.getValue().toString()));
} else if (param.getOperation().equalsIgnoreCase(":")) {
if (r.get(param.getKey()).getJavaType() == String.class) {
predicate = builder.and(predicate, builder.like(r.get(param.getKey()), "%" + param.getValue() + "%"));
} else {
predicate = builder.and(predicate, builder.equal(r.get(param.getKey()), param.getValue()));
}
}
}
public Predicate getPredicate() {
return predicate;
}
}

View File

@ -1,14 +1,15 @@
package org.baeldung.persistence.dao;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.baeldung.persistence.model.User;
import org.baeldung.web.util.SearchOperation;
import org.baeldung.web.util.SpecSearchCriteria;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.domain.Specifications;
import java.util.ArrayList;
import java.util.List;
public final class UserSpecificationsBuilder {
private final List<SpecSearchCriteria> params;
@ -48,15 +49,19 @@ public final class UserSpecificationsBuilder {
if (params.size() == 0)
return null;
Specification<User> result = new UserSpecification(params.get(0));
final List<Specification<User>> specs = params.stream()
.map(UserSpecification::new)
.collect(Collectors.toCollection(ArrayList::new));
Specification<User> result = specs.get(0);
for (int i = 1; i < params.size(); i++) {
result = params.get(i)
.isOrPredicate()
? Specifications.where(result)
.or(new UserSpecification(params.get(i)))
.or(specs.get(i))
: Specifications.where(result)
.and(new UserSpecification(params.get(i)));
.and(specs.get(i));
}

View File

@ -1,13 +1,15 @@
package org.baeldung.persistence.dao.rsql;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.data.jpa.domain.Specifications;
import cz.jirutka.rsql.parser.ast.ComparisonNode;
import cz.jirutka.rsql.parser.ast.LogicalNode;
import cz.jirutka.rsql.parser.ast.LogicalOperator;
import cz.jirutka.rsql.parser.ast.Node;
import org.springframework.data.jpa.domain.Specifications;
import java.util.ArrayList;
import java.util.List;
public class GenericRsqlSpecBuilder<T> {
@ -22,29 +24,24 @@ public class GenericRsqlSpecBuilder<T> {
}
public Specifications<T> createSpecification(final LogicalNode logicalNode) {
final List<Specifications<T>> specs = new ArrayList<Specifications<T>>();
Specifications<T> temp;
for (final Node node : logicalNode.getChildren()) {
temp = createSpecification(node);
if (temp != null) {
specs.add(temp);
List<Specifications<T>> specs = logicalNode.getChildren()
.stream()
.map(node -> createSpecification(node))
.filter(specifications -> specifications != null)
.collect(Collectors.toCollection(ArrayList::new));
Specifications<T> initialSpec = specs.stream().findFirst().get();
Specifications<T> result = specs.stream().skip(1).reduce(initialSpec, (firstSpec, secondSpec) -> {
if (logicalNode.getOperator() == LogicalOperator.AND) {
return Specifications.where(firstSpec).and(secondSpec);
} else if (logicalNode.getOperator() == LogicalOperator.OR) {
return Specifications.where(firstSpec).or(secondSpec);
}
}
Specifications<T> result = specs.get(0);
if (logicalNode.getOperator() == LogicalOperator.AND) {
for (int i = 1; i < specs.size(); i++) {
result = Specifications.where(result).and(specs.get(i));
}
}
else if (logicalNode.getOperator() == LogicalOperator.OR) {
for (int i = 1; i < specs.size(); i++) {
result = Specifications.where(result).or(specs.get(i));
}
}
return firstSpec;
});
return result;
}

View File

@ -1,14 +1,17 @@
package org.baeldung.persistence.dao.rsql;
import cz.jirutka.rsql.parser.ast.ComparisonOperator;
import org.springframework.data.jpa.domain.Specification;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.jpa.domain.Specification;
import cz.jirutka.rsql.parser.ast.ComparisonOperator;
public class GenericRsqlSpecification<T> implements Specification<T> {
@ -71,18 +74,22 @@ public class GenericRsqlSpecification<T> implements Specification<T> {
// === private
private List<Object> castArguments(final Root<T> root) {
final List<Object> args = new ArrayList<Object>();
final Class<? extends Object> type = root.get(property).getJavaType();
for (final String argument : arguments) {
final List<Object> args = arguments.stream().map(arg -> {
Object obj;
if (type.equals(Integer.class)) {
args.add(Integer.parseInt(argument));
obj = Integer.parseInt(arg);
} else if (type.equals(Long.class)) {
args.add(Long.parseLong(argument));
obj = Long.parseLong(arg);
} else {
args.add(argument);
obj = arg;
}
}
return obj;
}).collect(Collectors.toCollection(ArrayList::new));
return args;
}

View File

@ -2,6 +2,7 @@ package org.baeldung.web.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -63,7 +64,7 @@ public class UserController {
@ResponseBody
public List<User> findAll(@RequestParam(value = "search", required = false) String search) {
List<SearchCriteria> params = new ArrayList<SearchCriteria>();
if (search != null) {
if (Optional.ofNullable(search).isPresent()) {
Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),");
Matcher matcher = pattern.matcher(search + ",");
while (matcher.find()) {
@ -126,7 +127,7 @@ public class UserController {
@ResponseBody
public Iterable<MyUser> findAllByQuerydsl(@RequestParam(value = "search") String search) {
MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder();
if (search != null) {
if (Optional.ofNullable(search).isPresent()) {
Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),");
Matcher matcher = pattern.matcher(search + ",");
while (matcher.find()) {

View File

@ -1,5 +1,6 @@
package org.baeldung.web.util;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
@ -45,7 +46,7 @@ public class CriteriaParser {
Deque<Object> output = new LinkedList<>();
Deque<String> stack = new LinkedList<>();
for (String token : searchParam.split("\\s+")) {
Arrays.stream(searchParam.split("\\s+")).forEach(token -> {
if (ops.containsKey(token)) {
while (!stack.isEmpty() && isHigerPrecedenceOperator(token, stack.peek()))
output.push(stack.pop()
@ -65,7 +66,7 @@ public class CriteriaParser {
output.push(new SpecSearchCriteria(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4), matcher.group(5)));
}
}
}
});
while (!stack.isEmpty())
output.push(stack.pop());