[
https://issues.apache.org/jira/browse/TOMAHAWK-952?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12485543
]
Mike Kienenberger commented on TOMAHAWK-952:
--------------------------------------------
As a first step in this process, I've separated SortableDataModel into
SortableDataModel (current behavior, final, subclass of BaseSortableDataModel)
and BaseSortableDataModel (extendable, works with Comparators).
> Provide cleaner, consistent sorting for dataTable and selectItems
> -----------------------------------------------------------------
>
> Key: TOMAHAWK-952
> URL: https://issues.apache.org/jira/browse/TOMAHAWK-952
> Project: MyFaces Tomahawk
> Issue Type: New Feature
> Components: Extended Datatable, Extended SelectItems, New Component
> Affects Versions: 1.1.6-SNAPSHOT
> Reporter: Mike Kienenberger
> Assigned To: Mike Kienenberger
> Priority: Minor
>
> My requirements in most cases are to specify a sort order in the page code,
> not to allow end-users to manipulate the sort
> order. From what I can tell, there's no easy way to do this. I documented
> the most effective method I could find on the wiki under a "static sorting"
> subheading, but even that method leaves unnecessary links in the column
> headers.
> At the same time, I looked into what it would take to make sorting cleaner
> and more user-friendly.
> I came up with a subclass of extended dataTable and a replacement
> SortableModel that did what I wanted for the most part:
> <my:sortableDataTable
> preserveDataModel="true"
> value="#{bean.carList}"
> var="car"
> >
> <f:facet name="comparator">
> <my:propertyComparator
> property="style.color"
> descending="true" />
> </f:facet>
> </my:sortableDataTable>
> This is based in part on reusing my components for sorting selectItem lists.
> For some reason, couldn't make this work without using preserveDataModel.
> [Strangely enough, doing the same thing with the current t:dataTable sort
> attributes didn't require preserveDataModel.]
> In any case, a comparator component can be any UIComponent that implements a
> ComparatorSource interface (ie, public Comparator getComparator()), which
> provides a great deal of flexibility.
> The propertyComparator implementation basically does the same thing as the
> internal guts of the current SortableModel, but is pluggable. I used
> beanutils in my comparator rather than EL to process the property expression,
> which also eliminates the "rowObjectGet" hack. An "EL comparator" could be
> implemented if the EL processing features were needed.
> I think it would be worthwhile to replace the current SortableModel with a
> more generic pluggable one. A good start would be to pull all of the
> property-resolving/comparison out of it, and stick it into a comparator like
> I did. setSortCriteria(List criteria) appears to be misnomer since only the
> first item in the list is used -- using a comparator would also solve that
> issue as you can create MultipleComparator that takes a list of other
> comparators and goes through them in order.
> Following is what DataTable looks like to make this work. Note that this
> doesn't handle the current sorting options.
> protected DataModel createDataModel()
> {
> DataModel dataModel = super.createDataModel();
> UIComponent comparatorUIComponent = getComparator();
> Comparator comparator = null;
> if (null != comparatorUIComponent)
> {
> if (comparatorUIComponent instanceof ComparatorSource)
> {
> comparator =
> ((ComparatorSource)comparatorUIComponent).getComparator();
> }
> else
> {
> // TODO: need log error instead
> throw new RuntimeException("comparatorUIComponent
> should
> implement ComparatorSource");
> }
> }
> boolean isSortable = null != comparator;
> if (isSortable)
> {
> if (!(dataModel instanceof BaseSortableModel))
> {
> dataModel = new BaseSortableModel(dataModel);
> }
> ((BaseSortableModel)dataModel).setComparator(comparator);
> }
> return dataModel;
> }
> After stripping out the comparator stuff from SortableModel, these are the
> major changes:
> public void setComparator(Comparator _comparator) {
> this._comparator = _comparator;
> _sort();
> }
> private void _sort()
> {
> if (null == _comparator)
> {
> // restore unsorted order:
> _baseIndicesList = _sortedIndicesList = null;
> return;
> }
> //TODO: support -1 for rowCount:
> int sz = getRowCount();
> if ((_baseIndicesList == null) || (_baseIndicesList.size() != sz))
> {
> // we do not want to mutate the original data.
> // however, instead of copying the data and sorting the copy,
> // we will create a list of indices into the original data, and
> // sort the indices. This way, when certain rows are made current
> // in this Collection, we can make them current in the underlying
> // DataModel as well.
> _baseIndicesList = new IntList(sz);
> }
> final int rowIndex = _model.getRowIndex();
> _model.setRowIndex(0);
> // Make sure the model has that row 0! (It could be empty.)
> if (_model.isRowAvailable())
> {
> Collections.sort(_baseIndicesList, new
> RowDataComparator(_comparator, _model));
> _sortedIndicesList = null;
> }
> _model.setRowIndex(rowIndex);
> }
> protected class RowDataComparator implements Comparator
> {
> private Comparator dataComparator = null;
> private DataModel dataModel = null;
> public RowDataComparator(Comparator comparator, DataModel
> model)
> {
> this.dataComparator = comparator;
> this.dataModel = model;
> }
> public int compare(Object arg1, Object arg2) {
> Integer r1 = (Integer)arg1;
> Integer r2 = (Integer)arg2;
> dataModel.setRowIndex(r1.intValue());
> Object rowData1 = _model.getRowData();
> dataModel.setRowIndex(r2.intValue());
> Object rowData2 = _model.getRowData();
> return dataComparator.compare(rowData1, rowData2);
> }
> }
> Also, here's how I'd like to improve t:selectItems. I've had a custom
> subclass of f:selectItems of this working for awhile. Notice how we can
> reuse the same propertyComparator component. This particular implementation
> can take a list of comparator children and implicitly wraps them in a
> MultipleComparator. That's not really possible with a dataTable facet, so
> we'd want to provide a MultipleComparator component.
> <my:orderedSelectItems value="#{bean.carList}">
> <my:propertyComparator
> property="style.color"
> descending="false" />
> </my:orderedSelectItems>
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.