/** * EventListenerList.java * * Created on 08.04.2010 */ package org.mage.plugins.card.dl.beans; import com.google.common.base.Function; import com.google.common.collect.AbstractIterator; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import java.util.*; import static java.util.Arrays.asList; /** * The class EventListenerList. * * @version V0.0 08.04.2010 * @author Clemens Koza */ public class EventListenerList extends javax.swing.event.EventListenerList { private static final long serialVersionUID = -7545754245081842909L; /** * Returns an iterable over all listeners for the specified classes. the * listener classes are in the specified order. for every class, listeners * are in the reverse order of registering. A listener contained multiple * times (for a single or multiple classes) is only returned the first time * it occurs. */ public <T extends EventListener> Iterable<T> getIterable(final Class<? extends T>... listenerClass) { //transform class -> iterable List<Iterable<T>> l = Lists.transform(asList(listenerClass), new ClassToIterableFunction<>()); //compose iterable (use an arraylist to memoize the function's results) final Iterable<T> it = Iterables.concat(new ArrayList<>(l)); //transform to singleton iterators return () -> new SingletonIterator<>(it.iterator()); } /** * Returns an iterator over all listeners for the specified classes. the * listener classes are in the specified order. for every class, listeners * are in the reverse order of registering. A listener contained multiple * times (for a single or multiple classes) is only returned the first time * it occurs. * * @param <T> * @param listenerClass * @return */ public <T extends EventListener> Iterator<T> getIterator(Class<? extends T>... listenerClass) { return getIterable(listenerClass).iterator(); } /** * Iterates backwards over the listeners registered for a class by using the * original array. The Listener runs backwards, just as listener * notification usually works. */ private class ListenerIterator<T> extends AbstractIterator<T> { private final Class<? extends T> listenerClass; private final Object[] listeners = listenerList; private int index = listeners.length; private ListenerIterator(Class<? extends T> listenerClass) { this.listenerClass = listenerClass; } @Override @SuppressWarnings("unchecked") protected T computeNext() { for (index -= 2; index >= 0; index -= 2) { if (listenerClass == listeners[index]) { return (T) listeners[index + 1]; } } return endOfData(); } } /** * Transforms a class to the associated listener iterator */ private class ClassToIterableFunction<T> implements Function<Class<? extends T>, Iterable<T>> { public Iterable<T> apply(final Class<? extends T> from) { return () -> new ListenerIterator<>(from); } } /** * Filters the delegate iterator so that every but the first occurrence of * every element is ignored. */ private static class SingletonIterator<T> extends AbstractIterator<T> { private final Iterator<T> it; private final HashSet<T> previous = new HashSet<>(); public SingletonIterator(Iterator<T> it) { this.it = it; } @Override protected T computeNext() { while (it.hasNext()) { T next = it.next(); if (previous.add(next)) { return next; } } return endOfData(); } } }