package ru.hflabs.rcd.web;
import ru.hflabs.rcd.model.criteria.FilterCriteria;
import ru.hflabs.rcd.model.criteria.FilterResult;
import ru.hflabs.rcd.service.IPagingService;
import ru.hflabs.rcd.web.model.PageResponseBean;
/**
* Класс <class>PagingUtils</class> реализует вспомогательные методы для формирования страниц объектов
*
* @see ru.hflabs.rcd.service.IFilterService
*/
public abstract class PagingUtils {
protected PagingUtils() {
}
/**
* Рассчитывает общее количество страниц
*
* @param pageSize размер страницы
* @param itemsCount общее количество объектов
* @return Возвращает рассчитанное общее количество страниц
*/
private static int calculateTotalPageCount(int pageSize, int itemsCount) {
if (pageSize != FilterCriteria.COUNT_ALL) {
int tail = (itemsCount % pageSize == 0) ? 0 : 1;
return itemsCount / pageSize + tail;
} else {
return 1;
}
}
/**
* Рассчитывает смещение относительно начала объектов
*
* @param pageSize размер страницы
* @param page текущая страница
* @return Возвращает рассчитанное смешение
*/
private static int calculateOffset(int pageSize, int page) {
return (pageSize != FilterCriteria.COUNT_ALL) ?
Math.max(page - 1, 0) * pageSize :
0;
}
/**
* Рассчитывает количество объектов на странице
*
* @param pageSize предпочитаемый размер
* @param defaultSize размер по умолчанию
* @return Возвращает рассчитанный размер
*/
private static int calculatePageSize(Integer pageSize, int defaultSize) {
return (pageSize != null && (pageSize > 0 || pageSize == FilterCriteria.COUNT_ALL)) ?
pageSize :
defaultSize;
}
/**
* Выполняет поиск страницы объектов
*
* @param pageSize количество объектов на странице
* @param defaultPageSize количество объектов на странице по умолчанию
* @param currentPage запрашиваемая страница
* @param service сервис получения результатов
* @return Возвращает результат фильтрации
*/
public static <T> PageResponseBean<T> findPageByCriteria(Integer pageSize, int defaultPageSize, int currentPage, IPagingService<T> service) {
final int targetPage = Math.max(1, currentPage);
final int targetPageSize = calculatePageSize(pageSize, defaultPageSize);
// Формируем смещение относительно начала объектов
final int offset = calculateOffset(targetPageSize, targetPage);
// Получаем коллекцию результатов
FilterResult<T> filterResult = service.findPage(targetPageSize, offset);
// Если объекты не найдены и целевая страница не является первой,
// то перерасчитываем критерии поиска для получения последней страницы
if (filterResult.isEmpty() && targetPage != 1) {
return findPageByCriteria(pageSize, defaultPageSize, calculateTotalPageCount(targetPageSize, filterResult.getCountByFilter()), service);
}
// Формируем и возвращаем результат
return new PageResponseBean<>(
Math.max(targetPageSize, filterResult.size()),
targetPage,
calculateTotalPageCount(targetPageSize, filterResult.getCountByFilter()),
filterResult.getCountByFilter(),
filterResult.getResult()
);
}
}