/*
* RHQ Management Platform
* Copyright (C) 2009-2010 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.core.gui.table.bean;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.jetbrains.annotations.NotNull;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.UnlimitedPageControl;
import org.rhq.core.gui.table.model.PagedListDataModel;
/**
* @author Ian Springer
*/
public abstract class AbstractPagedDataUIBean<T> {
private static final int[] PAGE_SIZES = new int[] {15, 30, 45};
private static final SelectItem[] PAGE_SIZE_SELECT_ITEMS = new SelectItem[PAGE_SIZES.length];
static {
for (int i = 0; i < PAGE_SIZES.length; i++) {
PAGE_SIZE_SELECT_ITEMS[i] = new SelectItem(PAGE_SIZES[i], Integer.valueOf(PAGE_SIZES[i]).toString());
}
}
private static final int MINIMUM_PAGE_SIZE = PAGE_SIZES[0];
private static final int DEFAULT_PAGE_SIZE = PAGE_SIZES[0];
/** The number of specific pages to display on the data scroller - limit to 7 pages until we find a general fix for
* RHQ-1813. */
private static final int DATA_SCROLLER_MAX_PAGES = 7;
private PageControl pageControl;
private PagedListDataModel<T> dataModel;
public SelectItem[] getPageSizeSelectItems() {
return PAGE_SIZE_SELECT_ITEMS;
}
public int getPageSizeCount() {
return PAGE_SIZES.length;
}
public int getMinimumPageSize() {
return MINIMUM_PAGE_SIZE;
}
public int getDefaultPageSize() {
return DEFAULT_PAGE_SIZE;
}
public int getDataScrollerMaxPages() {
return DATA_SCROLLER_MAX_PAGES;
}
public int getDataScrollerPage() {
// rich:dataScroller expects its 'page' attribute to be 1-indexed, not 0-indexed.
return getPageControl().getPageNumber() + 1;
}
public void setDataScrollerPage(int i) {
// rich:dataScroller expects its 'page' attribute to be 1-indexed, not 0-indexed.
getPageControl().setPageNumber(i - 1);
}
@NotNull
public PageControl getPageControl() {
if (this.pageControl == null) {
this.pageControl = loadPageControl(FacesContext.getCurrentInstance());
if (this.pageControl == null) {
this.pageControl = getDefaultPageControl();
if (this.pageControl == null) {
throw new IllegalStateException("getDefaultPageControl() returned null - this is not allowed.");
}
}
}
/*
* if an invalid value was already persisted to the database, this needs to be fixed;
* this can occur when the value was valid at some point in the past, but new overrides
* changes the valid list of page sizes; generally, the user can correct this themselves
* at the user interface by selecting a different pageSize (which would cause the new
* value to be persisted), unless there is only one allowable value in which case it's
* not possible for the user to correct the issue themselves; to handle both of these
* cases, let's just pessimistically determine whether we need to "fix" the PageControl
* and, if so, repersist the adjusted values
*/
if (!(this.pageControl instanceof UnlimitedPageControl)) {
String pageSize = String.valueOf(pageControl.getPageSize());
boolean hasValidSize = false;
for (SelectItem validPageSize : getPageSizeSelectItems()) {
if (validPageSize.getValue().toString().equals(pageSize)) {
hasValidSize = true;
break;
}
}
if (!hasValidSize) {
this.pageControl.setPageSize(getMinimumPageSize());
storePageControl(FacesContext.getCurrentInstance(), this.pageControl);
}
}
return this.pageControl;
}
public void setPageControl(PageControl pageControl) {
// TODO: Implement equals() on PageControl, so we can skip reloading the page if the paging and sorting
// settings have not changed at all.
this.pageControl = pageControl;
storePageControl(FacesContext.getCurrentInstance(), this.pageControl);
// Reset the data model, so it will load a new page using the new PageControl.
this.dataModel.reset();
}
public void resetPageControl() {
setPageControl(null);
}
/**
* Subclasses can override this to change the default page size or to provide default ordering fields.
*
* @return the default page control (i.e. the page control to use when
* {@link #loadPageControl(javax.faces.context.FacesContext)} returns null); must never return null
*/
protected PageControl getDefaultPageControl() {
return new PageControl(0, MINIMUM_PAGE_SIZE);
}
/**
* TODO
* @param context
* @return
*/
protected PageControl loadPageControl(FacesContext context) {
// TODO: Provide a default impl that stores a Map<String, PageContro> in APPLICATION scope. The key would be
// viewRoot+dataTableClientId.
return null;
}
/**
* Subclasses can override this to persist page controls somewhere. They would typically be keyed off the
* current user and the current data table, so the GUI will remember a user's preferences for various tables.
*
* @param context
* @param pageControl
*/
protected void storePageControl(FacesContext context, PageControl pageControl) {
return;
}
public PagedListDataModel<T> getDataModel() {
if (this.dataModel == null) {
this.dataModel = createDataModel();
}
return this.dataModel;
}
public void setDataModel(PagedListDataModel<T> dataModel) {
this.dataModel = dataModel;
}
public abstract PagedListDataModel<T> createDataModel();
}