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

Attachment: 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











Reply via email to