/* * RHQ Management Platform * Copyright (C) 2005-2008 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.enterprise.gui.legacy.taglib; import java.text.MessageFormat; import java.util.Arrays; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.util.RequestUtils; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.enterprise.gui.legacy.Constants; /** * Generate pagination access for a provided PageList */ public class Pagination extends TagSupport { private static final Log log = LogFactory.getLog(Pagination.class); private String path; private JspWriter out; private PageList pageList; private String action; private boolean includeFirstLast = false; private boolean includePreviousNext = true; private String postfix = ""; private int currentPage; private int totalPages; private int pageSize; @Override public void release() { super.release(); out = null; path = null; pageList = null; this.action = null; } @Override public final int doStartTag() throws JspException { HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); JspWriter out = pageContext.getOut(); if (pageList.size() == pageList.getTotalSize()) { return SKIP_BODY; } path = request.getContextPath(); if (this.pageList.getPageControl() == null) { log.error("PageLists must have valid pageControls"); } this.currentPage = this.pageList.getPageControl().getPageNumber() + 1; if (this.pageSize == PageControl.SIZE_UNLIMITED) { this.totalPages = 1; } else { this.totalPages = (int) Math.ceil((double) this.pageList.getTotalSize() / this.pageList.getPageControl().getPageSize()); } this.pageSize = this.pageList.getPageControl().getPageSize(); try { out.write(createPagination()); } catch (Exception e) { throw new JspException("could not generate output ", e); } return SKIP_BODY; } protected String createPagination() throws Exception { StringBuffer output = new StringBuffer(); int sets = determineSets(); output.append("<table border=\"0\" class=\"ToolbarContent\" >"); output.append("<tr>"); if (sets > 1) { output.append("<td align=\"right\" nowrap><b>"); output.append(RequestUtils.message(pageContext, null, null, "ListToolbar.ListSetLabel", null)); output.append("</b></td>"); //generate select box output.append("<td>"); output.append(createSetListSelect(sets)); output.append("</select>"); output.append("</td>"); output.append("<td><img src="); output.append(path); output.append(" \"/images/spacer.gif\" height=\"1\" width=\"10\" border=\"0\"></td>"); } output.append("<td>"); output.append(createDots(sets)); output.append("</td>"); output.append("</tr>"); output.append("</table>"); return output.toString(); } /** * Returns a string containing the nagivation bar that allows the user to move between pages within the list. * * <p/>The urlFormatString should be a URL that looks like the following: * * <p/>http://.../somepage.page?pn={0} */ protected String createSetListSelect(int sets) { //ok now we should generate the select box StringBuffer msg = new StringBuffer(); //generate the set list message msg.append("<select name=\"").append(Constants.PAGENUM_PARAM).append(postfix).append( "\" size=\"1\" onchange=\"goToSelectLocation(this, '").append(Constants.PAGENUM_PARAM).append(postfix) .append("', '").append(getAction()).append("');\">"); //generate the the select box with each of the lists individually. for (int i = 0; i < sets; i++) { int set = (i * Constants.MAX_PAGES); msg.append("<option value=\"").append(set).append("\" "); if (currentPage >= set) { msg.append(" selected=\"selected\" "); } int display = i + 1; msg.append(">").append(display).append("</option>"); } return msg.toString(); } /** * Returns a string containing the nagivation bar that allows the user to move between pages within the list. * * <p/>The urlFormatString should be a URL that looks like the following: * * <p/>http://.../somepage.page?pn={0} */ protected String createDots(int sets) { setAction(removeExistingPaginationParams(getAction(), this.postfix)); // flag to determine if we should use a ? or a & int index = getAction().indexOf('?'); String separator = (index == -1) ? "?" : "&"; MessageFormat form = new MessageFormat(getAction() + separator + "pn" + postfix + "={0}"); int currentPage = this.pageList.getPageControl().getPageNumber(); int pageCount = determinePageCount(); int startPage = 0; int endPage = Constants.MAX_PAGES.intValue(); int currentSet = currentPage / Constants.MAX_PAGES.intValue(); if (sets >= 1) { startPage = currentSet * Constants.MAX_PAGES.intValue(); endPage = startPage + Constants.MAX_PAGES.intValue(); if (endPage > pageCount) { endPage = pageCount; } } if ((pageCount == 1) || (pageCount == 0)) { return " "; } if (currentPage < Constants.MAX_PAGES.intValue()) { if (pageCount < endPage) { endPage = pageCount; } } StringBuffer msg = new StringBuffer(); //passing sorting, ordering, and pageSize along with every request. StringBuffer pagMsg = new StringBuffer(); pagMsg.append("&").append(Constants.SORTCOL_PARAM + postfix).append("=").append( this.pageList.getPageControl().getPrimarySortColumn()).append("&").append( Constants.SORTORDER_PARAM + postfix).append("=").append( this.pageList.getPageControl().getPrimarySortOrder()).append("&") .append(Constants.PAGESIZE_PARAM + postfix).append("=").append(pageSize); if (currentPage == startPage) { msg.append("<td><img src=\"").append(path).append( "/images/tbb_pageleft_gray.gif\" width=\"13\" height=\"16\" border=\"0\"/></td>"); } else { Object[] objs = { new Integer(currentPage - 1) }; Object[] v1 = { new Integer(1) }; msg.append("<td><a href=\"").append(form.format(objs)).append(pagMsg.toString()).append("\">").append( "<img src=\"").append(path).append( "/images/tbb_pageleft.gif\" width=\"13\" height=\"16\" border=\"0\"/></a></td>"); } int displayNumber = startPage; for (int i = startPage; i < endPage; i++) { displayNumber += 1; if (i == currentPage) { msg.append("<td>").append(displayNumber).append("</td>"); } else { Object[] v = { new Integer(i) }; msg.append("<td><a href=\"").append(form.format(v)).append(pagMsg.toString()).append("\">").append( displayNumber).append("</a></td>"); } } if (currentPage == (endPage - 1)) { msg.append("<td><img src=\"").append(path).append( "/images/tbb_pageright_gray.gif\" width=\"13\" height=\"16\" border=\"0\"/></td>"); } else { Object[] objs = { new Integer(currentPage + 1) }; Object[] v1 = { new Integer(pageCount) }; msg.append("<td><a href=\"").append(form.format(objs)).append(pagMsg.toString()).append("\"><img src=\"") .append(path).append("/images/tbb_pageright.gif\" width=\"13\" height=\"16\" border=\"0\"/></a></td>"); } return msg.toString(); } /* * Removes any parameters from the query string which are going to be set again by this class. */ public static String removeExistingPaginationParams(String originalActionString, String postfix) { int index = originalActionString.indexOf('?'); if (index == -1) // there are no parameters so are work here is done { return originalActionString; } String mainActionString = originalActionString.substring(0, index + 1); String queryParametersString = originalActionString.substring(index + 1); log.debug("Original query parameters"); alphaPrintParams(queryParametersString); String[] queryParametersArray = queryParametersString.split("&"); // drop old parameters which we are about to appended to the query string StringBuilder newParameterString = new StringBuilder(); for (int i = 0; i < queryParametersArray.length; i++) { String currentParam = queryParametersArray[i]; if (!currentParam.startsWith(Constants.SORTCOL_PARAM + postfix) // sc && !currentParam.startsWith(Constants.SORTORDER_PARAM + postfix) // so && !currentParam.startsWith(Constants.PAGESIZE_PARAM + postfix) // ps && !currentParam.startsWith(Constants.PAGENUM_PARAM + postfix)) // pn { if (newParameterString.length() != 0) { newParameterString.append("&"); } newParameterString.append(currentParam); } } String newActionString = mainActionString + newParameterString.toString(); log.debug("New query parameters"); alphaPrintParams(newParameterString.toString()); return newActionString; } private static void alphaPrintParams(String value) { String[] parameters = value.split("&"); Arrays.sort(parameters); for (String param : parameters) { log.debug("\t" + param); } log.debug("\n"); } private int determineSets() { int pageCount = determinePageCount(); int sets; int div = pageCount / Constants.MAX_PAGES.intValue(); int mod = pageCount % Constants.MAX_PAGES.intValue(); sets = (mod == 0) ? div : (div + 1); return sets; } private int getPageCount() { return (int) Math.ceil(((double) this.pageList.getTotalSize()) / this.pageList.getPageControl().getPageSize()); } private int determinePageCount() { int pageCount = 0; int size; size = this.pageList.getTotalSize(); if (size == 0) { return 1; } int div = size / pageSize; int mod = size % pageSize; pageCount = (mod == 0) ? div : (div + 1); return pageCount; } @Override public int doEndTag() throws JspException { release(); return EVAL_PAGE; } public PageList getPageList() { return pageList; } public void setPageList(PageList pageList) { this.pageList = pageList; } public String getAction() { return this.action; } public void setAction(String action) { this.action = action; } public boolean isIncludeFirstLast() { return this.includeFirstLast; } public void setIncludeFirstLast(boolean includeFirstLast) { this.includeFirstLast = includeFirstLast; } public boolean isIncludePreviousNext() { return this.includePreviousNext; } public void setIncludePreviousNext(boolean includePreviousNext) { this.includePreviousNext = includePreviousNext; } public String getPostfix() { return postfix; } public void setPostfix(String postfix) { this.postfix = postfix; } }