/*
* 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.display;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
/**
* This is a little utility class that the SmartListTag uses to chop up a List of objects into small bite size pieces
* that are more suitable for display.
*/
class SmartListHelper extends Object {
private List masterList;
private int pageSize;
private int pageCount;
private int currentPage;
private int extSize = -1;
private Properties prop = null;
/**
* Creates a SmarListHelper instance that will help you chop up a list into bite size pieces that are suitable for
* display.
*/
protected SmartListHelper(List list, int pageSize, Properties prop, Integer extSize) {
super();
if (list == null) {
throw new IllegalArgumentException("Bad list argument passed into " + "SmartListHelper() constructor");
} else if (pageSize < 1) {
throw new IllegalArgumentException("Bad pageSize argument passed into " + "SmartListHelper() constructor");
}
this.prop = prop;
this.pageSize = pageSize;
this.masterList = list;
try {
this.extSize = extSize.intValue();
} catch (NullPointerException e) {
//do nothing means value not set.
}
this.pageCount = this.computedPageCount();
this.currentPage = 1;
}
/**
* Returns the computed number of pages it would take to show all the elements in the list given the pageSize we are
* working with.
*/
protected int computedPageCount() {
int result = 0;
if ((this.masterList != null) && (this.pageSize > 0)) {
int size;
size = this.masterList.size();
int div = size / this.pageSize;
int mod = size % this.pageSize;
result = (mod == 0) ? div : (div + 1);
}
return result;
}
/**
* Returns the index into the master list of the first object that should appear on the current page that the user
* is viewing.
*/
protected int getFirstIndexForCurrentPage() {
return this.getFirstIndexForPage(this.currentPage);
}
/**
* Returns the index into the master list of the last object that should appear on the current page that the user is
* viewing.
*/
protected int getLastIndexForCurrentPage() {
return this.getLastIndexForPage(this.currentPage);
}
/**
* Returns the index into the master list of the first object that should appear on the given page.
*/
protected int getFirstIndexForPage(int page) {
return ((page - 1) * this.pageSize);
}
/**
* Returns the index into the master list of the last object that should appear on the given page.
*/
protected int getLastIndexForPage(int page) {
int firstIndex = this.getFirstIndexForPage(page);
int pageIndex = this.pageSize - 1;
int lastIndex = this.masterList.size() - 1;
return Math.min(firstIndex + pageIndex, lastIndex);
}
/**
* Returns a subsection of the list that contains just the elements that are supposed to be shown on the current
* page the user is viewing.
*/
protected List getListForCurrentPage() {
return this.getListForPage(this.currentPage);
}
/**
* Returns a subsection of the list that contains just the elements that are supposed to be shown on the given page.
*/
protected List getListForPage(int page) {
List list = new ArrayList(this.pageSize + 1);
int firstIndex = this.getFirstIndexForPage(page);
int lastIndex = this.getLastIndexForPage(page);
for (int i = firstIndex; i <= lastIndex; i++) {
list.add(this.masterList.get(i));
}
return list;
}
/**
* Set's the page number that the user is viewing.
*
* @throws IllegalArgumentException if the page provided is invalid.
*/
protected void setCurrentPage(int page) {
if ((page < 1) || (page > this.pageCount)) {
Object[] objs = { new Integer(page), new Integer(pageCount) };
throw new IllegalArgumentException(MessageFormat.format(prop.getProperty("error.msg.invalid_page"), objs));
}
this.currentPage = page;
}
/**
* Return the little summary message that lets the user know how many objects are in the list they are viewing, and
* where in the list they are currently positioned. The message looks like: nnn <item(s)> found, displaying nnn to
* nnn. <item(s)> is replaced by either itemName or itemNames depending on if it should be signular or plurel.
*/
protected String getSearchResultsSummary() {
if (this.masterList.size() == 0) {
Object[] objs = { prop.getProperty("paging.banner.items_name") };
return MessageFormat.format(prop.getProperty("paging.banner.no_items_found"), objs);
} else if (this.masterList.size() == 1) {
Object[] objs = { prop.getProperty("paging.banner.item_name") };
return MessageFormat.format(prop.getProperty("paging.banner.one_item_found"), objs);
} else if (this.getFirstIndexForCurrentPage() == this.getLastIndexForCurrentPage()) {
Object[] objs = { new Integer(this.masterList.size()), prop.getProperty("paging.banner.items_name"),
prop.getProperty("paging.banner.items_name") };
return MessageFormat.format(prop.getProperty("paging.banner.all_items_found"), objs);
} else {
Object[] objs = { new Integer(this.masterList.size()), prop.getProperty("paging.banner.items_name"),
new Integer(this.getFirstIndexForCurrentPage() + 1), new Integer(this.getLastIndexForCurrentPage() + 1) };
return MessageFormat.format(prop.getProperty("paging.banner.some_items_found"), objs);
}
}
/**
* Returns a string containing the nagivation bar that allows the user to move between pages within the list. The
* urlFormatString should be a URL that looks like the following: http://.../somepage.page?page={0}
*/
protected String getPageNavigationBar(String urlFormatString, HttpServletRequest request, boolean pageAtServer) {
MessageFormat form = new MessageFormat(urlFormatString);
int maxPages = 8;
try {
maxPages = Integer.parseInt(prop.getProperty("paging.banner.group_size"));
} catch (NumberFormatException e) {
// Don't care, we will just default to 8.
}
int currentPage = this.currentPage;
int pageCount = this.pageCount;
int startPage = 1;
int endPage = maxPages;
if ((pageCount == 1) || (pageCount == 0)) {
return "<b>1</b>";
}
if (currentPage < maxPages) {
startPage = 1;
endPage = maxPages;
if (pageCount < endPage) {
endPage = pageCount;
}
} else {
startPage = currentPage;
while ((startPage + maxPages) > (pageCount + 1)) {
startPage--;
}
endPage = startPage + (maxPages - 1);
}
boolean includeFirstLast = prop.getProperty("paging.banner.include_first_last").equals("true");
boolean includePreviousNext = prop.getProperty("paging.banner.include_previous_next").equals("true");
String msg = "";
if (currentPage == 1) {
if (includeFirstLast) {
msg += "[" + prop.getProperty("paging.banner.first_label");
}
if (includePreviousNext) {
msg += "[" + prop.getProperty("paging.banner.prev_label") + "] ";
}
} else {
Object[] objs = { new Integer(currentPage - 1) };
Object[] v1 = { new Integer(1) };
if (includeFirstLast) {
msg += "[<a href=\"" + form.format(v1) + "\">" + prop.getProperty("paging.banner.first_label")
+ "</a>/<a href=\"" + form.format(objs) + "\">";
}
if (includePreviousNext) {
msg += "[<a href=\"" + form.format(objs) + "\">" + prop.getProperty("paging.banner.prev_label")
+ "</a>] ";
}
}
for (int i = startPage; i <= endPage; i++) {
if (i == currentPage) {
msg += "<b>" + i + "</b>";
} else {
Object[] v = { new Integer(i) };
//get order and sort from request
String sort = request.getParameter("sort");
String order = request.getParameter("order");
String pageSize = request.getParameter("pageSize");
String pagMsg;
//passing sorting, ordering, and pageSize along with every requests.
if (order == null) {
pagMsg = "&order=asc";
} else {
pagMsg = "&order=" + order;
}
if (sort == null) {
pagMsg = pagMsg + "&sort=1";
} else {
pagMsg = pagMsg + "&sort=" + sort;
}
if (pageSize == null) {
pagMsg = pagMsg + "&pageSize=" + prop.getProperty("paging.banner.default.page_size");
} else {
pagMsg = pagMsg + "&pageSize=" + pageSize;
}
msg += "<a href=\"" + form.format(v) + pagMsg + "\">" + i + "</a>";
}
if (i != endPage) {
msg += ", ";
} else {
msg += " ";
}
}
if (currentPage == pageCount) {
if (includeFirstLast) {
msg += "[" + prop.getProperty("paging.banner.next_label");
}
if (includePreviousNext) {
msg += "[" + prop.getProperty("paging.banner.next_label") + "] ";
}
} else {
Object[] objs = { new Integer(currentPage + 1) };
Object[] v1 = { new Integer(pageCount) };
if (includeFirstLast) {
msg += "[<a href=\"" + form.format(objs) + "\">";
}
if (includePreviousNext) {
msg += "[<a href=\"" + form.format(objs) + "\">" + prop.getProperty("paging.banner.next_label")
+ "</a>] ";
}
}
return msg;
}
}