/*
* Copyright 2011 SURFnet bv, The Netherlands
*
* 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 teams.domain;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.MoreObjects;
/**
* Utility class for paging
*/
public class Pager {
private long totalCount;
private int offset;
private int pageSize;
private static final int MAX_VISIBLE = 5;
private static final int PAGES_BEFORE = 2; // Math.ceil(MAX_VISIBLE/2)
public Pager(long totalCount, int offset, int pageSize) {
this.totalCount = totalCount;
this.offset = offset;
this.pageSize = pageSize;
}
public long getTotalCount() {
return totalCount;
}
/**
* @return {@link teams.domain.Page} in paging that is the first possible page
* or {@literal null} if no such navigation item is needed (first page is current)
*/
public Page getFirstPage() {
if (totalCount == 0 || offset < pageSize) {
return null;
}
return new Page(1, 0, false);
}
/**
* @return {@link teams.domain.Page} in paging that goes to the previous page
* or {@literal null} if no such item is needed (first page is current)
*/
public Page getPreviousPage() {
if (totalCount == 0 || offset < pageSize) {
return null;
}
int pageNumber = (offset / pageSize);
return new Page(pageNumber, offset - pageSize, false);
}
/**
* @return {@link teams.domain.Page} in paging that goes to the next page
* or {@literal null} if no such item is needed (last page is current)
*/
public Page getNextPage() {
if (offset + pageSize >= totalFilledUp()) {
return null;
}
int pageNumber = (offset / pageSize) + 2;
return new Page(pageNumber, offset + pageSize, false);
}
/**
* @return {@link teams.domain.Page} in paging that goes to the last possible page
* or {@literal null} if no such item is needed (last page is current)
*/
public Page getLastPage() {
if (offset + pageSize >= totalFilledUp()) {
return null;
}
int pageNumber = (totalFilledUp() / pageSize);
return new Page(pageNumber, (pageNumber - 1) * pageSize, false);
}
/**
* Start algorithm, example: pagesize 10, visible pages 5, total pages 15
* <ul>
* <li>Current page is 4 (first 5): start at 1: 1 - 2 - 3 - <b>4</b> - 5</li>
* <li>Current page is 12 (last 5): start at 11: 11 - <b>12</b> - 13 - 14 - 15 </li>
* <li>Current page is 8 (middle): start at 6: 6 - 7 - <b>8</b> - 9 - 10</li>
* </ul>
* If there is at most 1 page, an empty list is returned.
*
* @return List of {@link teams.domain.Page}'s that should be visible (sliding pager),
* can be empty
*/
public List<Page> getVisiblePages() {
List<Page> visiblePages = new ArrayList<Page>();
if (totalCount < pageSize) {
return visiblePages;
}
int start;
if (offset < (MAX_VISIBLE * pageSize)) {
// 'first 5'
start = 0;
} else if (offset + (MAX_VISIBLE * pageSize) > totalFilledUp()) {
// 'last 5'
start = totalFilledUp() - ((MAX_VISIBLE) * pageSize);
} else {
// 'in the middle'
start = offset - (PAGES_BEFORE * pageSize);
}
for (int i = 0; i < MAX_VISIBLE; i++) {
if (start + pageSize > totalFilledUp()) {
// in case we have only 1 till 4 pages
break;
}
final Page page = new Page((start / pageSize + 1), start, start == offset);
visiblePages.add(page);
start += pageSize;
}
return visiblePages;
}
/**
* Rounds up the totalCount to the next page.
* <p/>Example with pagesize 10:
* <ul>
* <li>0 rounded to 0</li>
* <li>1 rounded to 10</li>
* <li>9 rounded to 10</li>
* <li>10 rounded to 10</li>
* <li>11 rounded to 20</li>
* </ul>
*
* @return totalCount to the next page.
*/
int totalFilledUp() {
return (int) ((Math.ceil((double) totalCount / (double) pageSize)) * pageSize);
}
/**
* @return offset the startpoint within the totalresult for this request
*/
public int getOffset() {
return offset;
}
/**
* @return (maximum) pagesize for the current resultset
*/
public int getPageSize() {
return pageSize;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + offset;
result = prime * result + pageSize;
result = prime * result + (int) (totalCount ^ (totalCount >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pager other = (Pager) obj;
if (offset != other.offset)
return false;
if (pageSize != other.pageSize)
return false;
if (totalCount != other.totalCount)
return false;
return true;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(Pager.class)
.add("totalCount", totalCount)
.add("offset", offset)
.add("pageSize", pageSize).toString();
}
}