/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.ui.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;
if (extSize != null) {
this.extSize = extSize.intValue();
}
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;
}
}