class PaginationEvaluator {

    public PageResult<T> takePage(Page page, List<T> items) {
        if (page.getPageSize() < 0) {
            throw PaginationException.badPageSize(page.getPageSize());
        }

        if (page.getPageSize() == 0) {
            return takeEmptyPage(page, items);
        }

        List<T> itemsCopy = new ArrayList<>(items);
        itemsCopy.sort(dataComparator);

        if (StringExt.isEmpty(page.getCursor())) {
            return takePageWithoutCursor(page, itemsCopy);
        }

        Pair<String, Long> decodedCursor = decode(page.getCursor());
        return takePageWithCursor(page, itemsCopy, decodedCursor.getLeft(), decodedCursor.getRight());
    }

    public  PaginationEvaluator(Function<T, String> idExtractor, Function<T, Long> timestampExtractor);

}