FilteredList/SortedList

Bruce Alspaugh alspaughb at gmail.com
Wed Jan 16 13:35:42 PST 2013


Sorry if I'm a little late to this discussion since I am still very new
to JavaFX.  Have you taken a look at the approach to ObservableLists
that the Glazed Lists project takes?

An issue I see with the TransformationList is that it only provides
sorting and filtering transformations.  In general, you could have many
other types of arbitrary list transformations.  Those transformations
could depend on multiple ObservableLists or scalar ObservableValues.
See Glazed Lists for more examples of powerful list transformations.

Why not just implement SortedList and FilterList as concrete subclasses
of ListBinding that are bound to their source ObservableList and an
observable Comparator or predicate?  For convenience, you could provide
sort and filter methods to ListExpression that take the appropriate
observable Comparator or predicate and return another sorted or filtered
ListExpression so you can chain the calls and build a transformation
pipeline?  

This makes it possible to add more methods to ListExpression to provide
more types of list transformations in the future without breaking
anything, and end users can build their own custom transformations
simply by providing a concrete implementation of ListBinding and binding
to the appropriate dependencies.

I haven't had a chance to study the TableView API closely, but you may
be thinking you need a special interface on SortedList so that TableView
can change the Comparator on it when the user wants to change the sort
order.  Is that really true?  Why can't TableView simply make it's
Comparator properties observable and not be responsible for sorting the
list at all?  You could provide a convenient TableComparatorChooser that
registers itself as a listener that responses to changes in the
TableView comparators by updating the observable sort Comparator the
SortedList is bound to appropriately.  This borrows some ideas from the
Glazed Lists approach to sorting a table.

Bruce

-----Original Message-----
From: Martin Sladecek <martin.sladecek at oracle.com>
To: openjfx-dev at openjdk.java.net
Subject: FilteredList/SortedList
Date: Wed, 02 Jan 2013 16:58:26 +0100

Hello,

I would like to start discussion about a new API for ObservableLists 
that are filtered/sorted. This API was already in the repository before 
2.0 was released, but was withdrawn ( 
http://javafx-jira.kenai.com/browse/RT-15302).
In the original API, there were 3 new classes: FilteredList, SortedList 
and TransformationList (parent of the previous two). These 2 lists took 
a different (Observable)List, acting as a view for that list, firing 
change notifications when the view changed.

Since we have a different situation now, due to new (overlapping) 
features in JDK 8, I'd like to propose a different API for FilteredList 
and SortedList.

First of all, I don't think we need separate FilteredList and SortedList 
classes anymore. With defender methods, we can have a similar approach 
to JDK's stream(), having e.g. transform() method on ObservableList, 
that would allow filtering & sorting of the list.
The original API allowed "batch" mode, but this is now basically covered 
with List's stream(), although it's more cumbersome as you won't get a 
List directly of a Stream, not to mention ObservableList, which is what 
you need to pass as a model to various controls, like TableView.
Still, I'm not in favour of having this also in FX, but maybe something 
like Iterable to ObservableList conversion method would ease the FX 
development when using JDK 8 steams...

I want to keep TransformationList to serve both as a common parent for 
all current and future "transformation" lists, but also returning 
TransformationList on transform() call, having methods like filtered() 
and sorted() directly on the TransformationList.

So overall, the new API would look like this:

public abstract class TransformationList<E, F> implements 
ObservableList<E> {

     protected TransformationList(ObservableList<? extends F> source);

     public final ObservableList<? extends F> getDirectSource();

     // The first non-transformation list in the chain.
     public final ObservableList<?> getOriginalSource();

     // Called when a change from the source is triggered.
     protected abstract void onSourceChanged(Change<? extends F> c);

     // Maps the index of this list's element to an index in the direct 
source list.
     public abstract int getSourceIndex(int index);

     public final int getOriginalSourceIndex(int index);

     public final TransformationList<E, E> filtered(Predicate<? super E> 
predicate);

     public final TransformationList<E, E> sorted(Comparator<? super E> 
comparator);

}

ObservableList<E> interface would get a new defender method:

public TransformationList<E, E> transform();

this would return TransformationList representation of the current list.

Another appoach would be to have filtered(), sorted() directly on 
ObservableList as a defender methods, which would remove the necessity 
of calling transform() before filtered()/sorted(), but I find the first 
one more consistent with JDK API.

Any comments?

Thanks,
-Martin





More information about the openjfx-dev mailing list