package de.interseroh.report.pagination; import java.util.Collections; import java.util.LinkedList; import java.util.List; /** * @author Ingo Düppe (Crowdcode) */ public class Pagination { private long maxNumberOfLinks = 5; private long currentPage; private boolean withFastForward; private long numberOfPages; private List<PageLink> pageLinks; public Pagination(final long currentPage, final long numberOfPages, final long maxNumberOfLinks, final boolean withFastForward) throws IndexOutOfBoundsException { if (currentPage < 1 || currentPage > numberOfPages) throw new IndexOutOfBoundsException(String.format( "CurrentPage is out of range. It must be between 1 and %s. It is %s.", numberOfPages, currentPage)); if (maxNumberOfLinks < 2) throw new IllegalArgumentException("MaxNumberOfLinks must be greater than 1"); this.maxNumberOfLinks = maxNumberOfLinks; this.currentPage = currentPage; this.numberOfPages = numberOfPages; this.withFastForward = withFastForward; initPageLinks(); } public Pagination(final long currentPage, final long numberOfPages) { this(currentPage, numberOfPages, 5, true); } private void initPageLinks() { pageLinks = new LinkedList<>(); if (isFirstPageLinkNeeded()) { pageLinks.add(new PageLink(1, isFirstPage(), PageLinkType.FIRST)); } if (isFastForwardedPossible()) { pageLinks.add(new PageLink(fastBackwardPage(), false, PageLinkType.FASTBACKWARD)); } if (numberOfPages > 1) { for (long pageNumber = numberOfBeginLink(); pageNumber <= numberOfEndLink(); pageNumber++) { pageLinks.add(new PageLink(pageNumber, isCurrentPage(pageNumber), PageLinkType.PAGE)); } } if (isFastForwardedPossible()) { pageLinks.add(new PageLink(fastForwardPage(), false, PageLinkType.FASTFORWARD)); } if (isLastPageLinkNeeded()) { pageLinks.add(new PageLink(numberOfPages, isLastPage(), PageLinkType.LAST)); } } private long numberOfBeginLink() { long offset = getMaxNumbersOfLinks() / 2; long diff = numberOfPages - offset - currentPage; diff = diff < 0 ? -diff : 0; long linksBegin = currentPage - offset - diff; return (linksBegin < 1) ? 1 : linksBegin; } private long numberOfEndLink() { long offset = getMaxNumbersOfLinks() / 2; long diff = ((currentPage - offset) < 1 )? -(currentPage - offset)+1 : 0; long linksEnd = currentPage + offset + diff; return (linksEnd > numberOfPages) ? numberOfPages : linksEnd; } public boolean isFirstPageLinkNeeded() { return maxNumberOfLinks < numberOfPages; } public boolean isLastPageLinkNeeded() { return maxNumberOfLinks < numberOfPages; } private long getMaxNumbersOfLinks() { return Math.min(numberOfPages, maxNumberOfLinks); } public boolean isLastPage() { return currentPage == numberOfPages; } public boolean isFirstPage() { return currentPage == 1L; } public boolean isCurrentPage(long pageNumber) { return pageNumber == currentPage; } public long getCurrentPageNumber() { return currentPage; } public long getNumberOfPages() { return numberOfPages; } public List<PageLink> getPageLinks() { return Collections.unmodifiableList(pageLinks); } public boolean isFastForwardedPossible() { return maxNumberOfLinks + 10 < numberOfPages && withFastForward; } public long fastBackwardPage() { long fastBackwardPage = numberOfBeginLink() - 5; return (fastBackwardPage < 1) ? 1 : fastBackwardPage; } public long fastForwardPage() { long fastForwardPage = numberOfEndLink() + 5; return (fastForwardPage < numberOfPages) ? fastForwardPage : numberOfPages; } @Override public String toString() { return "Pagination{" + "maxNumberOfLinks=" + maxNumberOfLinks + ", currentPage=" + currentPage + ", numberOfPages=" + numberOfPages + ", pageLinks=" + pageLinks + '}'; } }