Skip to content

Instantly share code, notes, and snippets.

@dilnei
Forked from garcia-jj/Page.java
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dilnei/716a893a706196a9715f to your computer and use it in GitHub Desktop.
Save dilnei/716a893a706196a9715f to your computer and use it in GitHub Desktop.
Pagination is really cool to avoid fuking the server performance :)
package br.com.weblog.model.pg;
import static com.google.common.base.MoreObjects.firstNonNull;
import java.io.Serializable;
/**
* Classe para prover paginação de resultados.
*
* @author Otávio Scherer Garcia
*/
public final class Page implements Serializable {
private static final long serialVersionUID = 1762167069940450807L;
private static final int DEFAULT_LIMIT = 10;
private static final int DEFAULT_OFFSET = 1;
private final int page;
private final int limit;
private Page(Integer page, Integer limit) {
this.page = firstNonNull(page, DEFAULT_OFFSET);
this.limit = firstNonNull(limit, DEFAULT_LIMIT);
}
public static Page of(Integer value) {
return new Page(value, null);
}
public static Page of(Integer page, Integer limit) {
return new Page(page, limit);
}
public static Page notNull(Page page) {
return page == null ? of(DEFAULT_OFFSET, DEFAULT_LIMIT) : page;
}
public int getLimit() {
return limit;
}
public int getFirstResult() {
return (page * limit) - limit;
}
public int getPage() {
return page;
}
}
package br.com.weblog.model.pg;
import java.io.Serializable;
import java.util.List;
/**
* Interface filha de java.util.List que contém dados usados para paginação de resultados.
*
* @author Otávio Scherer Garcia
* @param <E> Tipo da classe interna armazenada na lista.
*/
public interface PaginatedList<E> extends List<E>, Serializable {
/**
* Retorna a quantidade total de registros encontrados.
*
* @return quantidade total de registros encontrados.
*/
int getTotalSize();
/**
* Retorna o indice da página corrente.
*
* @return indice da página corrente.
*/
int getCurrentPage();
/**
* Retorna a quantidade de páginas.
*
* @return quantidade de páginas.
*/
int getTotalPages();
/**
* Retorna o indice do primeiro registro.
*
* @return indice do primeiro registro.
*/
int getFirstResult();
}
package br.com.weblog.model.pg;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.google.common.collect.ForwardingList;
/**
* Implementação padrão para lista paginada. Internamente essa classe contém a lista somente com os resultados
* já filtrados para paginação. Há métodos auxiliares para conhecer os dados da paginação como getTotalSize(),
* getCurrentPage(), getTotalPages() e getFirstResult() que podem ser encontrados na interface
* {@link PaginatedList}.
*
* @author Otávio Scherer Garcia
* @autor Dilnei Cunha
* @param <E> Tipo da classe interna armazenada na lista.
*/
public final class PaginatedListWrapper<E> extends ForwardingList<E> implements PaginatedList<E> {
private static final long serialVersionUID = -7654322436718819832L;
private List<E> elements;
private int totalSize;
private int currentPage;
private int totalPages;
private int firstResult;
public PaginatedListWrapper() {
}
public PaginatedListWrapper(int totalSize, int currentPage, int totalPages, int firstResult, List<E> elements) {
this.totalSize = totalSize;
this.currentPage = currentPage;
this.totalPages = totalPages;
this.firstResult = firstResult;
this.elements = elements;
}
public String getLink(String uriPattern, int page) {
String uri = uriPattern.replace("{page}", String.valueOf(page));
return uri.endsWith("?") ? uri.substring(0, uri.length() - 1) : uri;
}
public static <E> PaginatedListWrapper<E> newList(Page page, int totalSize, List<E> elements) {
int totalPages = (int) Math.ceil((double) totalSize / page.getLimit());
return newList(totalSize, page.getPage(), totalPages, page.getFirstResult(), elements);
}
public static <E> PaginatedListWrapper<E> newList(int totalSize, int currentPage, int totalPages, int firstResult, List<E> elements) {
return new PaginatedListWrapper<E>(totalSize, currentPage, totalPages, firstResult, elements);
}
@Override
protected List<E> delegate() {
return elements;
}
public void elementsEmpty() {
this.elements = Collections.emptyList();
}
public void removeAllElements(Collection<?> c) {
this.elements.removeAll(c);
}
public void addAllElements(Collection<? extends E> c) {
elements.addAll(c);
}
public int getTotalPages() {
return totalPages;
}
public int getCurrentPage() {
return currentPage;
}
public int getTotalSize() {
return totalSize;
}
public int getFirstResult() {
return firstResult;
}
public List<E> getElements() {
return elements;
}
}
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"
xmlns:c="http://java.sun.com/jsp/jstl/core"
version="2.1">
<jsp:directive.tag body-content="empty" />
<jsp:directive.attribute name="results" type="icob.model.pg.PaginatedList" required="true" />
<jsp:directive.attribute name="uriPattern" type="java.lang.String" required="true" />
<c:set var="uriPattern" value="${uriPattern}?${pageContext.request.queryString}" />
<jsp:scriptlet><![CDATA[
int viewcount = 9;
int initcount = results.getCurrentPage() - viewcount + 1;
int finalcount = results.getCurrentPage() + viewcount;
if (initcount < 1) {
finalcount += initcount * (-1);
initcount = 1;
}
if (finalcount > results.getTotalPages()) {
initcount += results.getTotalPages() - finalcount - 1;
initcount = (initcount < 1) ? 1 : initcount;
finalcount = results.getTotalPages() + 1;
}
request.setAttribute("initcount", initcount);
request.setAttribute("finalcount", finalcount);
]]></jsp:scriptlet>
<ul class="pagination">
<c:choose>
<c:when test="${results.getCurrentPage() gt 1}">
<li><a href="${results.getLink(uriPattern, results.getCurrentPage() - 1)}">&#171;</a></li>
</c:when>
<c:otherwise>
<li class="disabled"><a>&#171;</a></li>
</c:otherwise>
</c:choose>
<c:if test="${empty results}">
<li class="disabled "><a>1</a></li>
</c:if>
<c:if test="${initcount gt 1}">
<li><a href="${results.getLink(uriPattern, 1)}">1</a></li>
<li class="disabled"><a>...</a></li>
</c:if>
<c:choose>
<c:when test="${empty results and results.getTotalPages() ge results.getCurrentPage()}">
<span class="page-numbers current">1</span>
</c:when>
<c:otherwise>
<c:forEach begin="${initcount}" end="${finalcount - 1}" var="y" varStatus="x">
<c:choose>
<c:when test="${y eq results.getCurrentPage()}">
<li class="active"><a>${y}</a></li>
</c:when>
<c:otherwise>
<li><a href="${results.getLink(uriPattern, y)}">${y}</a></li>
</c:otherwise>
</c:choose>
</c:forEach>
</c:otherwise>
</c:choose>
<c:if test="${finalcount lt results.getTotalPages()}">
<li class="disabled"><a>...</a></li>
<li><a href="${results.getLink(uriPattern, results.getTotalPages())}">${results.getTotalPages()}</a></li>
</c:if>
<c:choose>
<c:when test="${results.getTotalPages() gt results.getCurrentPage()}">
<li><a href="${results.getLink(uriPattern, results.getCurrentPage() + 1)}">&#187;</a></li>
</c:when>
<c:otherwise>
<li class="disabled"><a>&#187;</a></li>
</c:otherwise>
</c:choose>
</ul>
<p>
<fmt:message key="paging">
<fmt:param value="${results.getFirstResult() + 1}" />
<fmt:param value="${results.getFirstResult() + results.size()}" />
<fmt:param value="${results.getTotalSize()}" />
</fmt:message>
</p>
</jsp:root>
<tags:npaging uriPattern="/plan/page-{page}/" results="${planList}"/>
@dilnei
Copy link
Author

dilnei commented Jul 28, 2015

change import of com.google.common.base.Objects.firstNonNull to com.google.common.base.MoreObjects.firstNonNull, second documentation it is deprecated and it will be removed.

Deprecated. Use MoreObjects.firstNonNull(T, T) instead. 
This method is scheduled for removal in June 2016.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment