Skip to main content

Using Comparators to define Event notification order?

58 replies [Last post]

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
leouser
Offline
Joined: 2005-12-12
Points: 0

its not that simple, there are listeners that want to do it before and after the event listeners. There are also listeners that want a specific order to their notification.

Just doing it for:
before model notification
model notification
after model notification

in itself, does not appear to solve the problem. In the case sited above, there is a need for an ordering that isn't exactly a pre post listener. The user needed to guarantee that A gets notified before E.

There may be even cases that need to mutate their ordering dependant upon the state of something:
ABC ok, for a particular state
CAB needed for another

As for the models tossing an event to the component which in turn propagates to its listeners, the user if needs to can listen to the models and apply any ordering he needs to.

BH

Scott Violet

I agree that you need pre and post listeners, but don't see how one
could implement a Comparator without knowing something about the
listener classes.

The idea I had for this is to introduce a new interface, perhaps
something like:

public interface EventOrdering {
public int getEventOrder();
}

Any time you add a listener EventListenerList (and others) would check
to see if the listener implements EventOrdering, if it does it's added
relative to the other listeners based on their eventOrder. Here's an
example.

Let's say you have three listeners, A, B, C all of which implement
EventOrdering with values of 1, 2, and 3 respectively.

Here's the results of invoking add with the listeners and the order the
listeners would be notified in:

addXXXListener(B); // order of notification is B
addXXXListener(C); // order of notification is B, C
addXXXListener(A); // order of notification is A, B, C

This is pretty generic, and by itself doesn't address the problem at
hand. To solve that we would need to change all of Swing's internal
listeners to use a specific range of ids. Developers wanting to add
their listener before/after Swing listeners would then pick a value on
either side of the range Swing uses.

For compatibility EventOrdering listeners are notified AFTER listeners
that don't implement EventOrdering. This keeps the current
implementation behavior of having the listeners notified in the reverse
order they were added in.

Thoughts?

-Scott

leouser
Offline
Joined: 2005-12-12
Points: 0

yes, that's one question that Ive had as Ive gone along, how will the user differentiate between the ones they want to move around. A problem I see with the interface is that it becomes hard to change the order.

If a listener is always returning an EventOrder of 1, will that 1 fit in all situations? If the user doesn't have the option of altering the returned value, how can they change the ordering? The user should be able to change how orderings are done.

One idea that I have is to do a mix of the Comparator/EventOrdering interface:
1. Have a default Comparator set on the classes that respects the users EventOrdering getEventOrder value
2. Allow the user to override the Ordering mechanism, through setting a Comparator on the value.

This way there is an option to create their own ordering mechanism.

One thing Ive thought about is doing the ordering on the array returned by the getListenerList, but I dislike this because it erases the add order history.

Ive got an intial set of diffs of classes that Ive done some work on their event notification ordering(which Ill see if I can get up in Collab land). Im going define a Comparator that tries the EventOrdering interface idea out. Given that Ive seen the orderings work fine so far, I don't question that EventOrdering will work. :)

BH

leouser
Offline
Joined: 2005-12-12
Points: 0

yep,

the Comparator/EventOrdering pair works quite well together. Ive got a JTable which is an EventOrdering and 2 TableModelListeners which are EventOrderings as well. All are attached to an AbstractTabelModel which is ordered by a EventOrderingComparator and when a change occurs we get this nice print out:
2 -> The first Listener added, I believe without ordering imposed it would be the 2nd notified
5 -> JTable
9 -> the second added, would be the first notified after the table without ordering.

So by adding an interface to these classes it was relatively simple to take control of who gets notified.

BH

leouser
Offline
Joined: 2005-12-12
Points: 0

oh yeah, the Comparator would be intended to sort the array returned by this call:
getListeners(Class t)

since it doesn't return any internals, it gives us the opportunity to control the order.

BH

leouser
Offline
Joined: 2005-12-12
Points: 0

getListeners would be a bad choice in that it constrains the listeners returned. For example, in the JComboBox, the ActionListeners are stored in the EventListenerList and they are not EventListener subinterfaces. This leads me to favor:
getSortedListeners(Class c)

which builds up a List of Class c and sorts it.

Anyway, the theory so far appears to work in code. Ive got JComboBox and JList instrumented to work with the notification order.

The basic rule for using the notification order is:
1. See if there is a Comparator in the listenerList.
If yes:
Use the SortedListener list as the notification list.
If no:
Use the old way

BH

alexfromsun
Offline
Joined: 2005-09-05
Points: 0

Hello Brian

Nice to see you here !
(I am returning to work after the great vacation in US)

pre- and post-listeners is a really interesting idea

I have a question about that:
what if pre-listener initiate the new event and start to notify all listeners, what the ordering will be set ?

I mean a new generated event from pre-listener will notify all new pre and post listeners and then back to the old pre ones ?

(I put it in a bit tangled way :-)

Thanks
alexp

leouser
Offline
Joined: 2005-12-12
Points: 0

Hello Alex! :)

hmm... that is a good question....

with the Comparator strategy here, you definately gain control over the order of who gets notified but this in itself does not stop an endless cycle of notifications.

So if we have a list with this listeners
A B C(with the Comparator setting the notification order to A B C).

A initiates an event that causes its list to start being notified:
So:
A B C
are notified in that order. But if A cannot discern that its the cause of its own event and it starts to fire another event because of this, well that is a problem. Though Im not sure if the endless notification cycle is particulary connected to the pre/post listener rfe. A listener like that needs to know when it shouldn't start up another event within a notification it has started.

This weird scenario:
A B C D A X T A(where this is the order created by the Comparator)

where A starts things would mean that A would be notified 3 times.

If we take the case here(from the bug report):
------------------------------------
---- B -- C --
/ A D
\ /
------ E ----

If A fires events and B and E are listeners to A, then we may want some way to guarantee that the path A-B-C-D arrives before A-E-D. Food for thought.
------------------------
I think this one can be handled fairly well with the Comparator strategy, it just needs to provide an ordering where B comes before E. Just provide a Comparator with the smarts to do it.

In the tests Ive done so far, Ive been adding Listeners which have a random number assigned to them. The Comparator orders them according to the number and when the event transpires I get a nicely ordered list of numbers printed out on the console.

BH