/* * Copyright 2015 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.thoughtworks.go.server.util; import java.util.ArrayList; import java.util.List; import java.util.LinkedHashMap; import java.util.Map; public class Pagination { private Integer pageSize; private Integer offset; private Integer total; private static final int DEFAULT_PER_PAGE = 10; private static final int MAXIMUM_LIMIT = 300; public static final Pagination ONE_ITEM = pageStartingAt(0, 1, 1); private static final int NUMBER_OF_NEIGHBOURS = 2; private Pagination(Integer offset, Integer total, Integer pageSize) { setPageSize(pageSize); setOffset(offset); setTotal(total); } private void setPageSize(Integer pageSize) { if (pageSize != null && pageSize > MAXIMUM_LIMIT) { throw new RuntimeException("The max number of perPage is [" + MAXIMUM_LIMIT + "]."); } this.pageSize = (pageSize == null || pageSize == 0) ? DEFAULT_PER_PAGE : pageSize; } private void setOffset(Integer offset) { this.offset = (offset == null) ? 0 : offset; } private void setTotal(Integer total) { this.total = (total == null) ? 0 : total; } public Integer getPageSize() { return pageSize; } public Integer getOffset() { return offset; } public Integer getTotal() { return total; } public Map toJsonMap() { Map<String, Object> json = new LinkedHashMap<>(); json.put("count", total); json.put("start", offset); json.put("perPage", pageSize); return json; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Pagination that = (Pagination) o; if (pageSize != null ? !pageSize.equals(that.pageSize) : that.pageSize != null) { return false; } if (offset != null ? !offset.equals(that.offset) : that.offset != null) { return false; } if (total != null ? !total.equals(that.total) : that.total != null) { return false; } return true; } @Override public int hashCode() { int result = pageSize != null ? pageSize.hashCode() : 0; result = 31 * result + (offset != null ? offset.hashCode() : 0); result = 31 * result + (total != null ? total.hashCode() : 0); return result; } public int getCurrentPage() { return offset / pageSize + 1; } public int getTotalPages() { return total / pageSize; } public int getPreviousPage() { return getCurrentPage() - 1; } public int getPreviousOffset() { return (getPreviousPage() - 1) * pageSize; } public int getNextPage() { return getCurrentPage() + 1; } public int getNextOffset() { return (getNextPage() - 1) * pageSize; } public boolean hasNextPage() { return offset + pageSize <= total; } public boolean hasPreviousPage() { return offset - pageSize >= 0; } @Override public String toString() { return "Pagination{" + "pageSize=" + pageSize + ", offset=" + offset + ", total=" + total + '}'; } public static Pagination pageFor(int currentItem, int totalCount, int pageSize) { return pageStartingAt((currentItem / pageSize) * pageSize, totalCount, pageSize); } public static Pagination pageStartingAt(Integer offset, Integer total, Integer pageSize) { return new Pagination(offset, total, pageSize); } public static Pagination pageByNumber(int pageNumber, int total, int pageSize) { return pageStartingAt((pageNumber - 1) * pageSize, total, pageSize); } public int getFirstPage() { return 1; } public int getLastPage() { return (total - 1) / pageSize + 1; } public List<PageNumber> getPages() { ArrayList<PageNumber> pages = new ArrayList<>(); if (getCurrentPage() > getFirstPage()) { pages.add(new PageNumber(getCurrentPage() - 1, "prev")); } if (getLastPage() < showAllPagesThreshold()) { for (int i = 1; i <= getLastPage(); i++) { addPage(pages, i); } } else { if (getCurrentPage() <= endLength()) { for(int i = 1; i <= getCurrentPage() + NUMBER_OF_NEIGHBOURS; i++) { addPage(pages, i); } pages.add(PageNumber.DOTS); addPage(pages, getLastPage()); } else if(getCurrentPage() > getLastPage() - endLength()) { addPage(pages, getFirstPage()); pages.add(PageNumber.DOTS); for(int i = getCurrentPage() - NUMBER_OF_NEIGHBOURS; i <= getLastPage(); i++) { addPage(pages, i); } } else { addPage(pages, getFirstPage()); pages.add(PageNumber.DOTS); for (int i = getCurrentPage() - NUMBER_OF_NEIGHBOURS; i <= getCurrentPage() + NUMBER_OF_NEIGHBOURS; i++) { addPage(pages, i); } pages.add(PageNumber.DOTS); addPage(pages, getLastPage()); } } if (getLastPage() > getCurrentPage()) { pages.add(new PageNumber(getCurrentPage() + 1, "next")); } return pages; } private void addPage(ArrayList<PageNumber> pages, int i) { pages.add(new PageNumber(i, i == getCurrentPage())); } private int showAllPagesThreshold() { return endLength() + 5; } private int endLength() { return NUMBER_OF_NEIGHBOURS * 2; } public static PageNumber page(int i) { return new PageNumber(i); } public static PageNumber page(int i, String label) { return new PageNumber(i, label); } public static PageNumber currentPage(int i) { return new PageNumber(i, true); } public static class PageNumber { public static final PageNumber DOTS = new PageNumber(-1, "...") { @Override public String toString() { return "..."; } @Override public boolean isDots() { return true; } }; private int page; private String label; private boolean current; public PageNumber(int page) { this(page, String.valueOf(page)); } public PageNumber(int page, String label) { this.page = page; this.label = label; } public PageNumber(int page, boolean current) { this(page); this.current = current; } public boolean isDots() { return false; } public String getLabel() { return label; } public int getNumber() { return page; } public boolean isCurrent() { return current; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } PageNumber that = (PageNumber) o; if (current != that.current) { return false; } if (page != that.page) { return false; } if (label != null ? !label.equals(that.label) : that.label != null) { return false; } return true; } @Override public int hashCode() { int result = page; result = 31 * result + (label != null ? label.hashCode() : 0); result = 31 * result + (current ? 1 : 0); return result; } @Override public String toString() { return "" + page + "(" + label + ')' + (current ? "current" : ""); } } }