I can subclass it of course, but because HtmlDataTable (in createDataModel
method) checks if the DataModel is an instance of SortableDataModel, it will
actually wrap my extended BaseSortableModel into a SortableModel, that will
not use my custom defined comparator. 

I would expect that HtmlDataTable to use only BaseSortableModel and every
time a column header link is clicked to notify me by which column the data
to be sorted. 

Or maybe I got it wrong. Could you explain in few words how would you
implement a custom sortable model starting from BaseSortableModel?

Thanks.
Catalin


Mike Kienenberger wrote:
> 
> It was left that way to provide identical backward compatible behavior.
> 
> However, you should be able to subclass (or use) BaseSortableModel
> instead of the default sortable model.
> 
> On 11/27/07, CatalinPetrisor <[EMAIL PROTECTED]> wrote:
>>
>> That's a very good idea. However, in the latest svn sources the
>> HtmlDataTable
>> component still uses SortableModel class to set the current sort column.
>> Wouldn't be normal to use BaseSortableModel class to allow extensibility?
>>
>> Thanks.
>>
>>
>> Mike Kienenberger wrote:
>> >
>> > As a first step in this process, I've separated SortableDataModel into
>> > SortableDataModel (current behavior, final, subclass of
>> > BaseSortableDataModel) and BaseSortableDataModel (extendable, works on
>> > Comparators).
>> >
>> > I tested all of the simple examples involving dataTable at one point,
>> > but it's possible that something may have slipped by me that I didn't
>> > notice.
>> >
>> >
>> > On 3/14/07, Mike Kienenberger <[EMAIL PROTECTED]> wrote:
>> >> I took a look at SortableModel and t:dataTable sorting again last
>> >> night.  My requirements in most cases are to simply 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>
>> >>
>> >
>> >
>>
>> --
>> View this message in context:
>> http://www.nabble.com/SortableModel-and-t%3AdataTable-changes-improvements-tf3403639.html#a13967432
>> Sent from the My Faces - Dev mailing list archive at Nabble.com.
>>
>>
> 
> 

-- 
View this message in context: 
http://www.nabble.com/SortableModel-and-t%3AdataTable-changes-improvements-tf3403639.html#a13976924
Sent from the My Faces - Dev mailing list archive at Nabble.com.

Reply via email to