Skip to main content

Any Custom Filters

12 replies [Last post]
sumitkishore
Offline
Joined: 2003-06-10
Points: 0

Have people written custom filters for JXTable? Can anyone post the code showing so? It seems to me that Filters are not abstracted enough. The abstract Filter class has too many abstract methods that could have been put in a base class. With

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
dhall
Offline
Joined: 2006-02-17
Points: 0

In the broad strokes, it's somewhat similar -- I'm starting from the same place: a desire to reduce Filter to a single one arg method.

here's a sketch

[code]
public interface TableModelExt extends TableModel {
public T getRow(int row);
}

/*
*JXTable requires TableModelExt: if it gets TableModel, it is wrapped in:
*/

public class ExtTableModelWrapper implements TableModelExt

{ // All TableModel methods go to delegate private TableModel delegate; public Object[] getRow(int row) { int numColumns = delegate.getColumnCount(); Object[] rowvals = new Object[numColumns]; for(int col = 0; col < delegate.getColumnCount(); ++col) { rowvals[col] = delegate.getValueAt(row, col); } return rowvals; } } /* * JXTable grows getRow(int row):Object method -- possibly generic */ // TableFilter -- JXTable has exactly one instance public class TableFilter { private int[] indexmap; private JXTable table; private Filter filter; public void refresh() { List indexmap = new ArrayList(); for (int row = 0; row < table.getRowCount(); ++row) { if (filter.include(table.getRow(row))) indexmap.add(row); } } } public interface Filter { public boolean include(T value); } /* * JXTable grows setFilter(Filter filter):void method */ // Filter Implementations public class FilterPipeline implements Filter { private List> filters; public boolean include(T value) { for (Filter filter : filters) if (!filter.include(value)) return false; } return true; } } public class RangeFilter impements Filter { private T min, max; public boolean include(T value) { return value.compareTo(min) >= 0 && value.compareTo(Max) <= 0; } } public class NotNullFilter implements Filter { public boolean include(Tvalue) { return value != null; } } public class FunctorFilter implements Filter { private UnaryFunctor functor; public boolean include(T value) { return functor.fn(value); } } [/code] Here's where I think I'm taking a left turn: we're working (up to this point) essentially with list-type models. If we want to filter on some property (either indexed or named), we need some way to take the value from the list and return a logical column value. In other (made up) words, we need to munge the row to get the column value to be tested. [code] public class MungingFilter implements Filter { private Discriminant disc; private Filter filter; public boolean include(T1 value) { return filter.include(disc.munge(value)); } } // Discriminants public interface Discriminant { public ColType munge(RowType row); } public class DefaultDiscriminant implements Discriminant { public Object munge(Object value) { return value; } } public class ColumnBoundDiscriminant implements Discriminant{ private int column; public T munge(Object[] row) { return (T) row[column]; } } public class FunctorDiscriminant { private UnaryFunctor uf; public V munge(R row) { return uf.fn(row); } } [/code] It's got many, many details to work out, as you can tell. However, JList can certainly work with the exact same collection of Filter implementations, and I think JTree can as well (T might be Node, or it might the Object stored in a Node, depending). Wherever we end up, I want to be able to write this class: [code] public class ScriptedFilter implements Filter { private UnaryFunctor functor; public ScriptedFilter (Class type, String expression) { functor = parse(expression, type, Boolean.class); } public boolean include(T value) { return functor.fn(value); } } [/code]
dhall
Offline
Joined: 2006-02-17
Points: 0

> jdnc-interest@javadesktop.org wrote:
> > I wrote one several months ago -- it's in my incubator area as FunctorFilter.
>
>
> Just noticed that you removed it? On a not to deep try, my elder local
> version (which was more or less in synch with current swingx) appears
> not to work with your newer jga. What I wanted to check was if the
> search ui support could be reasonably easy enough adjusted to use the
> raw text input instead of the compiled pattern (as it does in the
> standard search widgets).
>
> >
> > The filter API has changed since then,
>
> Hmm, not so much as to seriously break the FunctorFilter ...

I did pull all of the older material from the incubator (right around the same time that I proposed cleaning up the lib/share area). I was trying to do three different things at that point, and having to continually move the old code out of the way to get the ant demo task and the data value demo working.

I did take a stab at bringing the filter up to date: it appears that all of the packages changed (from swing -> swingx) (which is, of course, not hard to change) and a couple of the model mapping methods/map maintenance routines were refactored (which I chose not to track down at that point).

The change with the new jga jar was one that I was pretty sure affected only me, not thinking that anyone would try to build the FunctorFilter. The fix is easy -- the embedded parser in FunctorFilter should extend JFXGParser instead of GenericParser.

(I'm moving some names around in jga's parser packge, which is a two release process. Obviously I missed a few things in GenericParser, which I'll get fixed for the next point release)

I have every intention of reinstating that demo, but Patrick was right (in another thread) about the real need to document the DataValue parser as it currently stands, so that's what I've been doing.

>
>
> > and also struggling to resist the temptation to counterpropose a
> > dramtically simpler filter design).
>
> re-design of filter/sorter is postponed to the next swingx version,
> didn't make it into 1.0. Looking forward to a lively discussion then.
>

Almost two weeks before anyone picked up on that little aside ;)

kleopatra
Offline
Joined: 2003-06-11
Points: 0

Hi Dave,

>
> I did take a stab at bringing the filter up to date:
> it appears that all of the packages changed (from
> swing -> swingx) (which is, of course, not hard to
> change) and a couple of the model mapping methods/map
> maintenance routines were refactored (which I chose
> not to track down at that point).
>

that about sums it up ... I had updated your code to compile and (mostly) work with the new imports and the changed api

> The change with the new jga jar was one that I was
> pretty sure affected only me, not thinking that
> anyone would try to build the FunctorFilter. The fix
> is easy -- the embedded parser in FunctorFilter
> should extend JFXGParser instead of GenericParser.
>

ahhh, that did the trick - now it's running again! Thanks a lot.

> I have every intention of reinstating that demo, but
> Patrick was right (in another thread) about the real
> need to document the DataValue parser as it currently
> stands, so that's what I've been doing.
>

no problem - go as you like.

> >
> >
> > > and also struggling to resist the temptation to
> counterpropose a
> > > dramtically simpler filter design).
> >
> > re-design of filter/sorter is postponed to the
> next swingx version,
> > didn't make it into 1.0. Looking forward to a
> lively discussion then.
> >
>
> Almost two weeks before anyone picked up on that
> little aside ;)

Sorry for the delay - had been knocked out by a nasty cold during most of that time.

Jeanette

rbair
Offline
Joined: 2003-07-08
Points: 0

Hey Dave

> (and also struggling to resist the temptation to
> counterpropose a dramtically simpler filter design).

Have you looked at the sort/filter design that Scott did for Mustang? Since that API has to be supported forever, it might be more worth the effort to compare your filter thoughts with that implementation.

Richard

Scott Violet

jdnc-interest@javadesktop.org wrote:
> Hey Dave
>
>
>>(and also struggling to resist the temptation to
>>counterpropose a dramtically simpler filter design).
>
>
> Have you looked at the sort/filter design that Scott did for Mustang?
> Since that API has to be supported forever, it might be more worth the
> effort to compare your filter thoughts with that implementation.

The filtering part of the sorting API in mustang is quite a bit
different from that in swing labs. The filtering API in mustang takes
the perspective that a filter should be a simple stateless object that
tells you whether or not an entry should be shown in the view. For
example, show me all my important email messages, or show me all files
starting with 'j*'. As such, the filter class (RowFilter) only has only
one method:

public abstract boolean include(Entry entry);

For simplicity I've left out the generics, but it's signature is really:

public abstract boolean include(Entry entry);

There are factory methods for creating implementations that search for
strings, dates, numbers, as well as methods for getting filters that
string together other filters such as or/and/not.

Details can be found at:

http://download.java.net/jdk6/docs/api/javax/swing/RowFilter.html

-Scott

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Sumit Kishore

That kind of agrees with what made me start this discussion. Filter in
SwingX is not abstracted enough.

GlazedLists also has a design where the Filter interface only has one method
with the signature

boolean matches( Object o )

The scaffolding in the SwingX Filter is too troublesome for easily
implementing custom filters.

Sumit.

On 9/27/05, Scott Violet wrote:
>
> jdnc-interest@javadesktop.org wrote:
> > Hey Dave
> >
> >
> >>(and also struggling to resist the temptation to
> >>counterpropose a dramtically simpler filter design).
> >
> >
> > Have you looked at the sort/filter design that Scott did for Mustang?
> > Since that API has to be supported forever, it might be more worth the
> > effort to compare your filter thoughts with that implementation.
>
> The filtering part of the sorting API in mustang is quite a bit
> different from that in swing labs. The filtering API in mustang takes
> the perspective that a filter should be a simple stateless object that
> tells you whether or not an entry should be shown in the view. For
> example, show me all my important email messages, or show me all files
> starting with 'j*'. As such, the filter class (RowFilter) only has only
> one method:
>
> public abstract boolean include(Entry entry);
>
> For simplicity I've left out the generics, but it's signature is really:
>
> public abstract boolean include(Entry entry);
>
> There are factory methods for creating implementations that search for
> strings, dates, numbers, as well as methods for getting filters that
> string together other filters such as or/and/not.
>
> Details can be found at:
>
> http://download.java.net/jdk6/docs/api/javax/swing/RowFilter.html
>
> -Scott
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>
>
[att1.html]

rameshgupta
Offline
Joined: 2004-06-04
Points: 0

> (and also struggling to resist the temptation to
> counterpropose a dramtically simpler filter design).

If what's keeping you from making your proposal is this (http://www.javadesktop.org/forums/thread.jspa?forumID=53&threadID=17463&...), then please don't let that stop you. The intent was not to chill discussion on a worthy idea, especially when it promises dramatic simplification, but to urge restraint in making sweeping API changes unless the gains clearly outweigh the pain in switching APIs. Looking forward to your proposal whenever you are ready to share it ;-)

Ramesh

dhall
Offline
Joined: 2006-02-17
Points: 0

>> If what's keeping you from making your proposal is this (http://www.javadesktop.org/forums/thread.jspa?forumID=53&threadID=17463&...), then please don't let that stop you. The intent was not to chill discussion on a worthy idea, especially when it promises dramatic simplification, but to urge restraint in making sweeping API changes unless the gains clearly outweigh the pain in switching APIs. Looking forward to your proposal whenever you are ready to share it

Not at all, Ramesh -- it's just time, or the lack thereof, along with too many things ahead of it that are more fully cooked. I know that around here, you really have to bring code to the table, and I need to carve out some time to let the code cure a bit. As tempting as it is, there are other things that have to take priority for now.

Dave

rameshgupta
Offline
Joined: 2004-06-04
Points: 0

> I know that around here, you really have to bring
> code to the table, and I need to carve out some
> time to let the code cure a bit.
>
> Dave

That just helps add credibility to a proposal. But you've already established credibility with this crowd ;-) Anyway, feel no pressure -- We can wait until you are ready.

Ramesh

dhall
Offline
Joined: 2006-02-17
Points: 0

I wrote one several months ago -- it's in my incubator area as FunctorFilter. The basic idea was to write one filter class that used jga functors as a strategy implemention. This class can do everything that all of the existing filters do, at the cost of increasing the dependency on a third party library (which, understandably, gives the project as a whole reason for caution -- I can't be the one to answer the questions "Does this work well enough and do we need this badly enough to require the use of jga?")

The filter API has changed since then, thus my incubtator is somewhat out of date. I'm currently struggling to find the time to update the proposal (and also struggling to resist the temptation to counterpropose a dramtically simpler filter design).

Kleopatra

jdnc-interest@javadesktop.org wrote:
> I wrote one several months ago -- it's in my incubator area as FunctorFilter.

Just noticed that you removed it? On a not to deep try, my elder local
version (which was more or less in synch with current swingx) appears
not to work with your newer jga. What I wanted to check was if the
search ui support could be reasonably easy enough adjusted to use the
raw text input instead of the compiled pattern (as it does in the
standard search widgets).

>
> The filter API has changed since then,

Hmm, not so much as to seriously break the FunctorFilter ...

> and also struggling to resist the temptation to counterpropose a
> dramtically simpler filter design).

re-design of filter/sorter is postponed to the next swingx version,
didn't make it into 1.0. Looking forward to a lively discussion then.

Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Shai Almog

I wrote some filters but I did something really bad ;)
I went around the filters to the underlying model since I needed additional
information that is not mapped to a database column but appears within the
model (I use my own version of a table model that maps JavaBean properties
to columns).
Essentially what I do is this:
public abstract class BasicFilter extends Filter {
/**
* An index to the underlying model offsets
*/
private List index = new ArrayList();
private FastTableModel model;
private Filter underlying;

public void setModel(FastTableModel model) {
this.model = model;
}

public void setUnderlying(Filter underlying) {
this.underlying = underlying;
}

/**
* Provides filter-specific initialization. Called from the
Filter
* constructor.
*/
protected void init() {
}

/**
* Resets the internal row mappings from this filter to the previous filter.
*/
protected void reset() {
index.clear();
}

/**
* Performs the filter operation defined by this filter.
*/
protected final void filter() {
// update the index for internal offsets, this occurs on the Swing thread
// so there is no need to synchronize
List elements = model.getElements();
index.clear();
if(PeopleForm.getCurrentPerson() != null) {
filter(elements, index);
if(underlying != null) {
List newList = new ArrayList();
for(int iter = 0 ; iter < index.size() ; iter++) {
int row = ((Number)index.get(iter)).intValue();
row = underlying.convertRowIndexToView(row);
if(row > -1) {
newList.add(new Integer(row));
}
}
index = newList;
}
} else {
schedualRefresh();
}
}

/**
* A method to patch exceptions and bugs in the filter
*/
private void schedualRefresh() {
// not much we can do... We need to try to refresh the damn filter later on:
javax.swing.Timer timer = new javax.swing.Timer(500, new ActionListener() {
public void actionPerformed(ActionEvent ev) {
refresh();
}
});
timer.setRepeats(false);
timer.start();
}

protected abstract void filter(List elements, List index);

/**
* Returns the number of records that remain in this filter's "view"
* after the input records have been filtered.
*
* @return the number of records that remain in this filter's "view"
* after the input records have been filtered
*/
public int getSize() {
return index.size();
}

protected int mapTowardView(int row) {
return index.indexOf(new Integer(row));
}

protected int mapTowardModel(int row) {
return ((Number)index.get(row)).intValue();
}
}

public class ProjectFilter extends BasicFilter {
/**
* Performs the filter operation defined by this filter.
*/
protected void filter(List elements, List index) {
for(int iter = 0 ; iter < elements.size() ; iter++) {
// if this project is one of the projects to whom the user belongs
Project current = (Project)elements.get(iter);
if(ProjectsForm.isMyProject(current)) {
index.add(new Integer(iter));
}
}
}
}

--
Shai Almog
vPrise Consulting
http://www.vprise.com/
[att1.html]