org.springframework.data.jpa.repository.support.PredicateFactory Maven / Gradle / Ivy
package org.springframework.data.jpa.repository.support;
import static org.springframework.data.jpa.support.DataTablesUtils.ESCAPED_NULL;
import static org.springframework.data.jpa.support.DataTablesUtils.ESCAPED_OR_SEPARATOR;
import static org.springframework.data.jpa.support.DataTablesUtils.NULL;
import static org.springframework.data.jpa.support.DataTablesUtils.OR_SEPARATOR;
import static org.springframework.data.jpa.support.DataTablesUtils.isBoolean;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.persistence.Search;
import org.springframework.data.jpa.support.Column;
import org.springframework.data.jpa.support.DataTablesInput;
import org.springframework.util.StringUtils;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Ops;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.PathBuilder;
import com.querydsl.core.types.dsl.StringExpression;
class PredicateFactory {
private final static char ESCAPE_CHAR = '~';
public static Predicate createPredicate(PathBuilder entity, DataTablesInput input, Search search) {
BooleanBuilder predicate = new BooleanBuilder();
List searchs = search == null ? Collections.emptyList() : Arrays.asList(search.value());
for (Column column : input.getColumns()) {
String filterValue = column.getSearch().getValue();
boolean isColumnSearchable = searchs.contains(column.getData()) && column.getSearchable() && StringUtils.hasText(filterValue);
if (!isColumnSearchable) {
continue;
}
if (filterValue.contains(OR_SEPARATOR)) {
boolean nullable = false;
List values = new ArrayList();
for (String value : filterValue.split(ESCAPED_OR_SEPARATOR)) {
if (NULL.equals(value)) {
nullable = true;
}
else {
values.add(ESCAPED_NULL.equals(value) ? NULL : value);
}
}
if (values.size() > 0 && isBoolean(values.get(0))) {
List booleanValues = new ArrayList();
for (int i = 0; i < values.size(); i++) {
booleanValues.add(Boolean.valueOf(values.get(i)));
}
Predicate in = entity.getBoolean(column.getData()).in(booleanValues);
if (nullable) {
predicate = predicate.and(entity.getBoolean(column.getData()).isNull().or(in));
}
else {
predicate = predicate.and(in);
}
}
else {
if (values.isEmpty()) {
if (nullable) {
predicate = predicate.and(entity.get(column.getData()).isNull());
}
continue;
}
Predicate in = getStringExpression(entity, column.getData()).in(values);
if (nullable) {
predicate = predicate.and(entity.get(column.getData()).isNull().or(in));
}
else {
predicate = predicate.and(in);
}
}
continue;
}
if (isBoolean(filterValue)) {
predicate = predicate.and(entity.getBoolean(column.getData()).eq(Boolean.valueOf(filterValue)));
continue;
}
StringExpression stringExpression = getStringExpression(entity, column.getData());
if (NULL.equals(filterValue)) {
predicate = predicate.and(stringExpression.isNull());
continue;
}
String likeFilterValue = getLikeFilterValue(ESCAPED_NULL.equals(filterValue) ? NULL : filterValue);
predicate = predicate.and(stringExpression.lower().like(likeFilterValue, ESCAPE_CHAR));
}
String globalFilterValue = input.getSearch().getValue();
if (StringUtils.hasText(globalFilterValue)) {
BooleanBuilder matchOneColumnPredicate = new BooleanBuilder();
for (Column column : input.getColumns()) {
if (searchs.contains(column.getData()) && column.getSearchable()) {
matchOneColumnPredicate = matchOneColumnPredicate.or(getStringExpression(entity, column.getData()).lower().like(getLikeFilterValue(globalFilterValue), ESCAPE_CHAR));
}
}
predicate = predicate.and(matchOneColumnPredicate);
}
return predicate;
}
private static StringExpression getStringExpression(PathBuilder entity, String columnData) {
// path.getAnnotatedElement().getAnnotations();
// builder.getMetadata().isRoot();
// entity.get(columnData).getType()etMetadata().getPathType()getRootPath()Element();
return Expressions.stringOperation(Ops.STRING_CAST, entity.get(columnData));
}
private static String getLikeFilterValue(String filterValue) {
return "%" + filterValue.toLowerCase().replaceAll("~", "~~").replaceAll("%", "~%").replaceAll("_", "~_") + "%";
}
}