Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.kasinf.framework.rest.support.SearchRequest Maven / Gradle / Ivy
package com.kasinf.framework.rest.support;
import cn.hutool.core.date.DateUtil;
import com.kasinf.framework.rest.config.SearchableConfiguration;
import com.kasinf.framework.rest.exception.InvalidSearchPropertyException;
import com.kasinf.framework.rest.exception.InvalidSearchValueException;
import com.kasinf.framework.rest.exception.SearchException;
import com.kasinf.framework.rest.support.filter.*;
import com.kasinf.framework.rest.util.SearchableConvertUtils;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.util.Assert;
import java.util.*;
/**
* @author lkhsh
* 查询接口实现,包括条件、分页、排序
*/
@Data
@NoArgsConstructor
@ToString(of = {"searchFilterMap", "page", "sort"})
public final class SearchRequest implements Searchable {
private final Map searchFilterMap = new HashMap<>();
/**
* 使用这个的目的是保证拼sql的顺序是按照添加时的顺序
*/
private final List searchFilters = new ArrayList<>();
private Pageable page;
private Sort sort;
private boolean converted;
private SearchableConfiguration config;
private Class projection;
@Override
public boolean hasProjection() {
return projection != null;
}
@Override
public Searchable setProjection(Class projection){
this.projection = projection;
return this;
}
public SearchRequest(final Map searchParams) {
this(searchParams, null, null);
}
public SearchRequest(final Map searchParams, final Pageable page) {
this(searchParams, page, null);
}
public SearchRequest(final Map searchParams, final Sort sort) {
this(searchParams, null, sort);
}
/**
* 根据查询参数拼Search
* 查询参数格式:property_op=value 或 customerProperty=value
* customerProperty查找规则是:1、先查找domain的属性,2、如果找不到查找domain上的SearchPropertyMappings映射规则
* 属性、操作符之间用_分割,op可省略/或custom,省略后值默认为custom,即程序中自定义
* 如果op=custom,property也可以自定义(即可以与domain的不一样)
*
* @param searchParams 查询参数组
* @param page 分页
* @param sort 排序
*/
public SearchRequest(final Map searchParams, final Pageable page, final Sort sort) throws SearchException {
toSearchFilters(searchParams);
merge(sort, page);
}
/**
* 组装查询条件
*
* @param searchParams 查询条件
*/
private void toSearchFilters(final Map searchParams) throws SearchException {
if (searchParams == null || searchParams.size() == 0) {
return;
}
for (Map.Entry entry : searchParams.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
addSearchFilter(SearchFilterHelper.newCondition(key, value));
}
}
@Override
public void changeDataCondition() {
changeDataCondition(this.searchFilters);
}
private void changeDataCondition(List searchFilters) {
for (int i = 0; i < searchFilters.size(); i++) {
SearchFilter searchFilter = searchFilters.get(i);
if (searchFilter instanceof Condition) {
Condition condition = (Condition) searchFilter;
if (condition.isDateFilter()) {
Date today = DateUtil.beginOfDay(new Date()).toJdkDate();
Date begin = null;
Date end = null;
switch (condition.getOperator()) {
case yesterday:
// 操作符为昨天,取昨天0点-昨天23:59:59的区间
begin = DateUtil.offsetDay(today, -1).toJdkDate();
end = DateUtil.offsetSecond(today, -1).toJdkDate();
break;
case thisWeek:
//操作符为本周,获取本周一0点至上周日23:59:59
begin = DateUtil.beginOfWeek(today).toJdkDate();
end = DateUtil.endOfWeek(today).toJdkDate();
break;
case lastWeek:
//操作符为上周,获取上周一0点至上周日23:59:59
Date monday = DateUtil.beginOfWeek(today);
begin = DateUtil.offsetWeek(monday, -1).toJdkDate();
end = DateUtil.offsetSecond(monday, -1).toJdkDate();
break;
case thisMonth:
// 操作符为本月,获取本月1号0点至本月最后一天23:59:59
begin = DateUtil.beginOfMonth(today).toJdkDate();
end = DateUtil.endOfMonth(today).toJdkDate();
break;
case thisYear:
begin = DateUtil.beginOfYear(today).toJdkDate();
end = DateUtil.endOfYear(today).toJdkDate();
break;
case specific:
// 指定日期,生成当天0点至当天23:59:59的区间
Object value = condition.getValue();
if (value instanceof String) {
begin = DateUtil.parse((String) condition.getValue()).toJdkDate();
} else if (value instanceof Date) {
begin = DateUtil.beginOfDay((Date) value).toJdkDate();
}
Assert.notNull(begin, "指定的日期必须为 String 或 Date 类型");
end = DateUtil.endOfDay(begin).toJdkDate();
break;
}
condition.setOperator(SearchOperator.ge);
condition.setValue(begin);
condition.createKey();
// 为当前条件拼接一个and条件
SearchFilter newCondition = SearchFilterHelper.newCondition(condition.getSearchProperty(), SearchOperator.le, end);
searchFilter = SearchFilterHelper.and(condition, newCondition);
searchFilters.set(i, searchFilter);
}
return;
}
if (searchFilter instanceof OrCondition) {
changeDataCondition(((OrCondition) searchFilter).getOrFilters());
return;
}
if (searchFilter instanceof AndCondition) {
changeDataCondition(((AndCondition) searchFilter).getAndFilters());
}
}
}
@Override
public Searchable addSearchParam(String key, Object value) throws SearchException {
addSearchFilter(SearchFilterHelper.newCondition(key, value));
return this;
}
@Override
public Searchable addSearchParams(Map searchParams) throws SearchException {
toSearchFilters(searchParams);
return this;
}
@Override
public Searchable addSearchFilter(String searchProperty, SearchOperator operator, Object value) throws SearchException {
SearchFilter searchFilter = SearchFilterHelper.newCondition(searchProperty, operator, value);
return addSearchFilter(searchFilter);
}
@Override
public Searchable addSearchFilter(String searchProperty, SearchOperator operator) throws SearchException {
SearchFilter searchFilter = SearchFilterHelper.newCondition(searchProperty, operator, null);
return addSearchFilter(searchFilter);
}
@Override
public Searchable addSearchFilter(SearchFilter searchFilter) {
if (searchFilter == null) {
return this;
}
if (searchFilter instanceof Condition) {
Condition condition = (Condition) searchFilter;
String key = condition.getKey();
searchFilterMap.put(key, condition);
}
int index = searchFilters.indexOf(searchFilter);
if (index != -1) {
searchFilters.set(index, searchFilter);
} else {
searchFilters.add(searchFilter);
}
return this;
}
@Override
public Searchable addSearchFilters(Collection extends SearchFilter> searchFilters) {
if (searchFilters != null && !searchFilters.isEmpty()) {
searchFilters.forEach(this::addSearchFilter);
}
return this;
}
@Override
public Searchable or(final SearchFilter first, final SearchFilter... others) {
addSearchFilter(SearchFilterHelper.or(first, others));
return this;
}
@Override
public Searchable and(final SearchFilter first, final SearchFilter... others) {
addSearchFilter(SearchFilterHelper.and(first, others));
return this;
}
@Override
public Searchable removeSearchFilter(final String key) {
if (key == null) {
return this;
}
SearchFilter searchFilter = searchFilterMap.get(key);
if (searchFilter == null) {
searchFilter = searchFilterMap.remove(getCustomKey(key));
}
if (searchFilter == null) {
return this;
}
searchFilters.remove(searchFilter);
return this;
}
/**
* 获取自定义key
*
* @param key:
*/
private String getCustomKey(String key) {
return key + Condition.separator + SearchOperator.custom;
}
@Override
public Searchable removeSearchFilter(final String searchProperty, final SearchOperator operator) {
this.removeSearchFilter(searchProperty + Condition.separator + operator);
return this;
}
@Override
public Searchable convert(Class entityClass) throws InvalidSearchValueException, InvalidSearchPropertyException {
SearchableConvertUtils.convertSearchValueToEntityValue(this, entityClass);
markConverted();
return this;
}
@Override
public List getSearchFilters() {
return searchFilters;
}
@Override
public Searchable markConverted() {
this.converted = true;
return this;
}
@Override
public Searchable setPage(final Pageable page) {
merge(sort, page);
return this;
}
@Override
public Searchable setPage(int pageNumber, int pageSize) {
merge(sort, PageRequest.of(pageNumber, pageSize));
return this;
}
@Override
public Searchable addSort(Sort sort) {
merge(sort, page);
return this;
}
@Override
public Searchable addSort(Sort.Direction direction, String property) {
merge(Sort.by(direction, property), page);
return this;
}
@Override
public boolean hasSearchFilter() {
return searchFilters.size() > 0;
}
@Override
public boolean hashSort() {
return this.sort != null && this.sort.iterator().hasNext();
}
@Override
public void removeSort() {
this.sort = null;
if (this.page != null) {
this.page = PageRequest.of(page.getPageNumber(), page.getPageSize());
}
}
@Override
public boolean hasPageable() {
return this.page != null && this.page.getPageSize() > 0;
}
@Override
public void removePageable() {
this.page = null;
}
@Override
public boolean containsSearchKey(String key) {
boolean contains = searchFilterMap.containsKey(key) || searchFilterMap.containsKey(getCustomKey(key));
if (contains) {
return true;
}
//否则检查其中的or 和 and
return containsSearchKey(searchFilters, key);
}
/**
* 是否存在查询条件
*
* @param searchFilters:
* @param key:
*/
private boolean containsSearchKey(List searchFilters, String key) {
boolean contains = false;
for (SearchFilter searchFilter : searchFilters) {
if (searchFilter instanceof OrCondition) {
OrCondition orCondition = (OrCondition) searchFilter;
contains = containsSearchKey(orCondition.getOrFilters(), key);
}
if (searchFilter instanceof AndCondition) {
AndCondition andCondition = (AndCondition) searchFilter;
contains = containsSearchKey(andCondition.getAndFilters(), key);
}
if (searchFilter instanceof Condition) {
Condition condition = (Condition) searchFilter;
contains = condition.getKey().equals(key) || condition.getSearchProperty().equals(key);
}
}
return contains;
}
@Override
public Object getValue(String key) {
SearchFilter searchFilter = searchFilterMap.get(key);
if (searchFilter == null) {
searchFilter = searchFilterMap.get(getCustomKey(key));
}
if (searchFilter == null) {
return null;
}
if (searchFilter instanceof Condition) {
Condition condition = (Condition) searchFilter;
return condition.getValue();
}
return null;
}
/**
* 合并
*
* @param sort 排序
* @param page 分页
*/
private void merge(Sort sort, Pageable page) {
if (sort == null) {
sort = this.sort;
}
if (page == null) {
page = this.page;
}
// 合并排序
if (sort == null) {
this.sort = page != null ? page.getSort() : null;
} else {
this.sort = (page != null ? sort.and(page.getSort()) : sort);
}
// 把排序合并到page中
if (page != null) {
this.page = PageRequest.of(page.getPageNumber(), page.getPageSize(), this.sort);
} else {
this.page = null;
}
}
}