Hi, I'm still new to JSF and my first task has been to work on a reports type page using tomahawks dataTable, commandSortHeader and dataScroller.
So far, I've managed to get something whereby the dataTable's data is being paginated and sorted. Given the wiki document WorkingWithLargeTables, and also the column sort requirement lead me to the attached script(s) which is based on the pagedSortTable demo. Basically I ended up creating a PagedListDataModel class that extends the javax.faces.DataModel. It follows closely to the existing javax.faces.ListDataModel class but with the ability for the given List to have an independent dataset size. And also some extra methods associated to the sort column and ascending attribute(s). It seems to work fairly well for what I need it to do at this time, however the actionListener stuff in the setRowIndex method has not been explicity tested. I also noticed a difference between Sun's implementation and MyFaces in regard to the setWrappedData method, where Sun would first set the current index value to -1 directly before then passing actual desired index value (zero) as a param to the setRowIndex method (in setWrappedData). However MyFaces does not do this. Unless I'm mistaken, please correct me, at the moment, I do think that Sun's method is correct, because if by some means (e.g. an actionEvent) on the first row (index=0) this row event handler itself wants to update the the UIData's associated (List) data (via another call to setWrappedData), then with the MyFaces implementation no actionListener/Event will then occure because zero == zero, whereas Sun's index = -1 trick ensures that even the first row can invoke the actionListener/Events... As said I havent had the need to consider a dataTable's actionListeners, so my interpretation/reading of the code might be mistaken. The PagedListDataModel seems to be quite neat in that in ties together the three Tomahawk components nicely. However someone might be able to make a suggestion about the technique used in the commandSortHeader actionListener method where the dataModel's data is explicitly reset (via setWrappedData), this was because it seemed needed to ensure that the UIData data was then rebuilt/re-queried (in my case from the database) so that the data got refreshed immediately. I would probably have to do something similiar regardless because of the additional query params required in the db query (filters etc) , I couldn't firgure out a better or more applicable technique ? -- Greg
pagedSortTable.jsp
Description: Binary data
package javax.faces.model;
import java.util.List;
import javax.faces.model.DataModel;
import javax.faces.model.DataModelListener;
import javax.faces.model.DataModelEvent;
public abstract class PagedListDataModel extends DataModel {
// --------------------------------------------------------------------------
private List list;
private int index = -1;
private int size = 0;
private int rowsPerPage = 10;
private int startRow = 0;
private String column;
private boolean ascending = true;
// --------------------------------------------------------------------------
protected PagedListDataModel() {
this(0, null);
}
// --------------------------------------------------------------------------
protected PagedListDataModel(int rowCount, List list) {
super();
setWrappedData(rowCount, list);
}
// --------------------------------------------------------------------------
public int getRowIndex() {
return index;
}
// --------------------------------------------------------------------------
public void setRowIndex(int rowIndex) {
if (rowIndex < -1) {
throw new IllegalArgumentException();
}
int previousIndex = index;
index = rowIndex;
if (previousIndex == index) {
return;
}
if (list == null) {
return;
}
DataModelListener[] listeners = getDataModelListeners();
if (listeners == null) {
return;
}
Object rowData = null;
if (isRowAvailable()) {
if (index >= (startRow + list.size()) || index < startRow) {
createModelData();
}
rowData = getRowData();
}
for (int i = 0; i < listeners.length; ++i) {
if (listeners[i] != null) {
listeners[i].rowSelected(new DataModelEvent(this, index, rowData));
}
}
}
// --------------------------------------------------------------------------
public synchronized DataModel getModel() {
if (list == null) {
createModelData();
}
return this;
}
// --------------------------------------------------------------------------
public Object getWrappedData() {
return list;
}
// --------------------------------------------------------------------------
public void setWrappedData(Object data) {
startRow = 0;
if (data == null) {
list = null;
setRowIndex(-1);
} else {
list = (List) data;
index = -1;
setRowIndex(0);
}
}
// --------------------------------------------------------------------------
protected void setWrappedData(int rowCount, Object data) {
startRow = index == -1 ? 0 : index;
setRowCount(rowCount);
if (data == null) {
list = null;
setRowIndex(-1);
} else {
list = (List) data;
index = -1;
setRowIndex(startRow);
}
}
// --------------------------------------------------------------------------
public boolean isRowAvailable() {
return index >= 0 && index < size;
}
// --------------------------------------------------------------------------
public void setRowCount(int rowCount) {
size = rowCount;
}
// --------------------------------------------------------------------------
public int getRowCount() {
return list == null ? -1 : size;
}
// --------------------------------------------------------------------------
public Object getRowData() {
if (list == null) {
return null;
}
if (!isRowAvailable()) {
throw new IllegalArgumentException();
}
return list.get(index - startRow);
}
// --------------------------------------------------------------------------
protected abstract void createModelData();
// --------------------------------------------------------------------------
public String getSort() {
return column;
}
// --------------------------------------------------------------------------
public void setSort(String sort) {
column = sort;
}
// --------------------------------------------------------------------------
public boolean isSortAscending() {
return ascending;
}
// --------------------------------------------------------------------------
public void setSortAscending(boolean sortAscending) {
ascending = sortAscending;
}
// --------------------------------------------------------------------------
public int getRows() {
return rowsPerPage;
}
// --------------------------------------------------------------------------
public void setRows(int rows) {
rowsPerPage = rows;
}
// --------------------------------------------------------------------------
public int getPage() {
if (index < 1) {
return 1;
}
return index / rowsPerPage + 1;
}
// --------------------------------------------------------------------------
}//end class
/* * Copyright 2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.myfaces.examples.listexample; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.faces.component.UIData; import javax.faces.event.ActionEvent; import javax.faces.model.DataModel; import javax.faces.model.PagedListDataModel; public class PagedSortableCarList { // -------------------------------------------------------------------------- private PagedListDataModel dataModel; private UIData data = null; // -------------------------------------------------------------------------- public PagedSortableCarList() { dataModel = new LocalPagedListDataModel(); dataModel.setSort("type"); dataModel.setSortAscending(true); dataModel.setRows(10); } // -------------------------------------------------------------------------- public UIData getData() { return data; } // -------------------------------------------------------------------------- public void setData(UIData data) { this.data = data; } // -------------------------------------------------------------------------- public DataModel getDataModel() { return dataModel; } // -------------------------------------------------------------------------- private class LocalPagedListDataModel extends PagedListDataModel { // ------------------------------------------------------------------------ public LocalPagedListDataModel() { super(); } // -------------------------------------------------------------------------- protected void createModelData() { List<SimpleCar> cars = new ArrayList<SimpleCar>(); int datasetSize = 900; for (int i = 0; i < getRows(); ++i) { int index = i + (getPage() * getRows()) - getRows(); if (!isSortAscending()) { index = datasetSize - index; } SimpleCar car = new SimpleCar( index, "Car Type " + index, (index % 2 == 0) ? "blue" : "green" ); cars.add(car); } sort(cars, getSort(), isSortAscending()); setWrappedData(datasetSize, cars); } // ------------------------------------------------------------------------ } // -------------------------------------------------------------------------- public void processSortEvent(ActionEvent event) { dataModel.setWrappedData(null); dataModel.setRowIndex(data.getFirst()); } // ------------------------------------------------------------------------ private void sort(Object list, final String column, final boolean ascending) { Comparator comparator = new Comparator() { public int compare(Object o1, Object o2) { SimpleCar c1 = (SimpleCar) o1; SimpleCar c2 = (SimpleCar) o2; if (column == null) { return 0; } if (column.equals("type")) { return ascending ? c1.getType().compareTo(c2.getType()) : c2.getType().compareTo(c1.getType()); } if (column.equals("color")) { return ascending ? c1.getColor().compareTo(c2.getColor()) : c2.getColor().compareTo(c1.getColor()); } return 0; } }; Collections.sort((List<SimpleCar>)list, (Comparator<SimpleCar>)comparator); } // -------------------------------------------------------------------------- }//end class
