Bläddra i källkod

wyrzucenie pomysłu, który się nie sprawdził: NamedEvent...

ranides atterwim 13 år sedan
förälder
incheckning
763378a6b9

+ 1 - 1
pom.xml

@@ -4,7 +4,7 @@
 
     <groupId>net.ranides</groupId>
     <artifactId>assira</artifactId>
-    <version>0.58.4</version>
+    <version>0.59.0</version>
     <packaging>jar</packaging>
 
     <name>assira</name>

+ 0 - 1
src/main/java/net/ranides/assira/events/EventRouter.java

@@ -7,7 +7,6 @@
 
 package net.ranides.assira.events;
 
-import java.io.Serializable;
 import java.util.Collection;
 
 /**

+ 14 - 13
src/main/java/net/ranides/assira/events/EventRouterThread.java

@@ -77,7 +77,7 @@ public class EventRouterThread extends EventRouterDispatcher {
         this.maxtime = maxtime;
         this.events = new ArrayBlockingQueue<Event>(size, true);
         this.name = name;
-        this.exit = new ExitEvent(name);
+        this.exit = new ExitEvent(this);
         this.distributor = new Thread(name) {
 
             @Override
@@ -230,28 +230,29 @@ public class EventRouterThread extends EventRouterDispatcher {
     /**
      * Zdarzenie, które może zostać wysłane do routera, w celu zakończenia jego pracy.
      * Router rozsyła to zdarzenie do obserwatorów, tak samo jak każde inne.
-     * Router kończy działanie tylko jeśli nazwa w komunikacie jest taka sama,
-     * jak nazwa wątku zarządzanego przez router.
+     * Router kończy działanie tylko jeśli jako źródło podany jest referencja do
+     * routera.
      */
-    public static class ExitEvent implements Event {
-        private final String name;
-
+    public static class ExitEvent extends DisposeEvent {
         /**
-         * Tworzy nowy komunikat nakazujący zakończenie pracy każdemu routerowi,
-         * który zarządza wątkiem o podanej nazwie.
+         * Tworzy nowy komunikat nakazujący zakończenie pracy podanemu routerowi.
          * @param name
          */
-        public ExitEvent(String name) {
-            this.name = name;
+        public ExitEvent(EventRouterThread router) {
+            super(router);
+        }
+
+        @Override
+        public EventRouterThread source() {
+            return (EventRouterThread)super.source();
         }
 
         /**
-         * Nazwa wątku. Każdy router zakończy pracę, jeśli otrzyma ten komunikat,
-         * i zarządza wątkiem o tej nazwie.
+         * Nazwa wątku, którym zarządza router wskazany do zakończenia pracy.
          * @return
          */
         public String thread() {
-            return name;
+            return source().name;
         }
     }
 

+ 0 - 45
src/main/java/net/ranides/assira/events/NamedEvent.java

@@ -1,45 +0,0 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.events;
-
-import java.io.Serializable;
-
-/**
- * Klasa bazowa dla wszystkich zdarzeń, które posiadają nazwę.
- * Podstawowy model pozwala na przesyłanie dowolnych zdarzeń  i wiązanie na
- * podstawie typu. W oparciu o klasę {@code NamedEvent} stworzony jest model
- * rozszerzony - pozwalający przekazywać zdarzenia i wiązać obserwatorów na
- * podstawie typu oraz nazwy zdarzenia.
- *
- * @see NamedEventRouter
- * @see NamedEventListener
- * @author ranides
- */
-public class NamedEvent implements Event, Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    private final String name;
-
-    /**
-     * Tworzy nowe zdarzenie o określonej nazwie.
-     * @param name
-     */
-    public NamedEvent(String name) {
-        this.name = name;
-    }
-
-    /**
-     * Nazwa zdarzenia. Klasy {@link NamedEventRouter} oraz {@link NamedEventListener}
-     * przetwarzają zdarzenia o wartość zwróconą przez tę metodę.
-     * @return
-     */
-    public String name() {
-        return name;
-    }
-
-}

+ 0 - 262
src/main/java/net/ranides/assira/events/NamedEventListener.java

@@ -1,262 +0,0 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.events;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import net.ranides.assira.annotations.Meta;
-import net.ranides.assira.collection.map.MultiHashMap;
-import net.ranides.assira.collection.map.MultiMap;
-import net.ranides.assira.events.ReflectEventListener.ReflectAdapter;
-import net.ranides.assira.reflection.ClassInspector;
-
-/**
- * Obserwator pozwalający tworzyć wiązania z obserwatorami nasłuchującymi zdarzeń
- * o określonym typie oraz nazwie. Wszystkie nazwane zdarzenia dziedziczą po
- * {@link NamedEvent}. Ponieważ mechanizm obsługi zdarzeń nazwanych jest rozszerzeniem
- * klasycznej infrastruktury przekazywania zdarzeń, to może być dowolnie łączony
- * ze standardowymi obiektami {@link EventListener} oraz {@link EventRouter}.
- *
- * <p>
- * {@code NamedEventListener} posiada funkcjonalność bardzo podobną do {@link
- * ReflectEventListener}. Klasy pochodne mogą deklarować metody (niekoniecznie
- * publiczne), które zostaną uruchomione, jeśli do obserwatora zostanie wysłane
- * określone zdarzenie. Deklaracja metody obsługi zdarzeń ma następującą postać:
- * <ul>
- *      <li>metoda pobiera tylko jeden argument</li>
- *      <li>typ argumentu odpowiada typowi obserwowanego zdarzenia</li>
- *      <li>metoda jest adnotowana za pomocą {@link net.ranides.assira.annotations.Meta.EventHandler}</li>
- *      <li>{@link net.ranides.assira.annotations.Meta.EventHandler} obowiązkowo zawiera nazwę obserwowanego zdarzenia</li>
- *      <li>{@link net.ranides.assira.annotations.Meta.EventHandler} opcjonalnie określa sposób synchronizacji metody względem innych wątków</li>
- * </ul>
- * </p>
- *
- * <table style="margin: 10px 0 0 0; background: #c0F0c0; border: solid 1px #006000;" cellpadding="0"><tr><td>thread-safe class</td></tr></table>
- *
- * @author ranides
- */
-public class NamedEventListener implements Observable {
-
-    private static final String GLOBAL = "global://*";
-
-    private final MultiMap<String, EventListener<? super Event>> listeners = new MultiHashMap<String, EventListener<? super Event>>(){
-        @Override
-        protected Collection<EventListener<? super Event>> createCollection() {
-            return new LinkedList<EventListener<? super Event>>();
-        }
-    };
-
-    /**
-     * {@code NamedEventListener} nie może tworzony bez pośrednio - można jedynie
-     * tworzyć jego klasy pochodne. Po otrzymaniu zdarzenia uruchamia wszystkich
-     * podległych obserwatorów oraz wszystkie metody obsługi zdarzeń. Przeczytaj
-     * opis klasy, aby poznać wymagania wobec metod obsługi zdarzeń.
-     */
-    protected NamedEventListener() {
-        this(true);
-    }
-
-    NamedEventListener(boolean useReflection) {
-        if(!useReflection) {
-            return;
-        }
-        for(Method method : ClassInspector.getDeepMethods(getClass())) {
-            EventListener<Event> adapter = ReflectEventListener.wrap(this, method);
-            if( adapter != null ) {
-                Meta.EventHandler info = method.getAnnotation(Meta.EventHandler.class);
-                listeners.putItem(info.value(), adapter);
-            }
-        }
-    }
-
-    @Override
-    public final void handleEvent(Event event) {
-        signalEvent(event);
-    }
-
-    @Override
-    public boolean signalEvent(Event event) {
-        return (event instanceof NamedEvent) ? dispatchEvent((NamedEvent)event) : false;
-    }
-
-    @Override
-    public synchronized void dispose() {
-        listeners.clear();
-    }
-
-    /**
-     * Metoda blokująca, uruchamia kolejno obsługę zdarzenia u wszystkich
-     * zarejestrowanych obserwatorów, które na zdarzenie o określonym typie oczekują.
-     * Domyślna implementacja wywołuje tę metodę bezpośrednio w {@link #signalEvent}.
-     * Metody pochodne mogą użyć poniższej metody w zupełnie inny sposób i w
-     * zupełnie innym wątku, aby zaimplementować inną strategię przetwarzania zdarzeń.
-     *
-     * <table style="margin: 10px 0 0 0; background: #c0F0c0; border: solid 1px #006000;" cellpadding="0"><tr><td>thread-safe method</td></tr></table>
-     * @param event
-     * @return
-     */
-    protected final synchronized boolean dispatchEvent(NamedEvent event) {
-        if(listeners == null) {
-            return false;
-        }
-        runBindings(listeners.get(GLOBAL), event);
-        runBindings(listeners.get( event.name() ), event);
-        return true;
-    }
-
-    private void runBindings(Collection<EventListener<? super Event>> list, NamedEvent event) {
-        if(list == null) {
-            return;
-        }
-        for(EventListener<? super Event> listener : list) {
-            listener.handleEvent(event);
-        }
-    }
-
-    @Override
-    public final synchronized NamedEventListener bind(String name, EventListener<? super NamedEvent> listener) {
-        listeners.putItem(name, new TypedListener(listener) );
-        return this;
-    }
-
-    @Override
-    public final synchronized <T extends NamedEvent> Observable bind(String name, Class<T> type, EventListener<? super T> listener) {
-        listeners.putItem(name, new TypedListener(type, listener) );
-        return this;
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public final synchronized NamedEventListener unbind(String name, EventListener<? super NamedEvent> listener) {
-        // świadome rzutowanie: zobacz opis TypedListener
-        listeners.removeItem(name, (EventListener)listener );
-        return this;
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public final synchronized NamedEventListener unbind(EventListener<? super NamedEvent> listener) {
-        for(String name : listeners.keySet()) {
-            // świadome rzutowanie: zobacz opis TypedListener
-            listeners.removeItem(name, (EventListener)listener );
-        }
-        return this;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public final <T extends Event> void addEventListener(Class<T> event, EventListener<? super T> listener) {
-        if( !NamedEvent.class.isAssignableFrom(event) ) {
-            throw new UnsupportedOperationException("Direct adding listener without name is not permitted. Use bind instead.");
-        }
-        bind(GLOBAL, (Class)event, (EventListener)listener);
-    }
-
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public final <T extends Event> void removeEventListener(Class<T> event, EventListener<? super T> listener) {
-        if( !NamedEvent.class.isAssignableFrom(event) ) {
-            throw new UnsupportedOperationException("Direct removing listener without name is not permitted. Use unbind instead.");
-        }
-        unbind(GLOBAL, (EventListener)listener);
-    }
-
-    @Override
-    public synchronized Collection<EventBinding<?>> getEventListeners() {
-        Collection<EventListener<? super Event>> source = listeners.get(GLOBAL);
-        List<EventBinding<?>> result = new ArrayList<EventBinding<?>>(source.size());
-        for(EventListener<? super Event> listener : source) {
-            result.add(EventBinding.make(NamedEvent.class, listener));
-        }
-        return result;
-    }
-
-    /**
-     * {@inheritDoc}
-     * <p>Uwaga! Jeśli klasa posiada zadeklarowane metody adnotowane za
-     * pomocą {@link net.ranides.assira.annotations.Meta.EventHandler}, to
-     * zdarzenia nadal są do nich delegowane. Nie istnieje możliwość usunięcia
-     * metod zadeklarowanych w czasie kompilacji.</p>
-     */
-    @Override
-    public final synchronized void removeAllEventListeners() {
-        for(Collection<EventListener<? super Event>> list : listeners.values()) {
-            Iterator<EventListener<? super Event>> iterator = list.iterator();
-            while(iterator.hasNext()) {
-                EventListener<? super Event> value = iterator.next();
-                if( !(value instanceof ReflectAdapter) ) {
-                    iterator.remove();
-                }
-            }
-        }
-        Iterator<Collection<EventListener<? super Event>>> iterator = listeners.values().iterator();
-        while(iterator.hasNext()) {
-            Collection<EventListener<? super Event>> value = iterator.next();
-            if(value.isEmpty()) {
-                iterator.remove();
-            }
-        }
-    }
-
-/* ************************************************************************** */
-
-    /**
-     * Klasa ma napisaną metodę {@code equals} w taki sposób, że adapter jest
-     * równy samemu sobie, innemu adapterowi wrappującemu obserwatora oraz
-     * <b>opakowanemu obserwatorowi</b>.
-     * <p>
-     * Dzięki temu, jeśli chcemy sprawdzić, czy
-     * dany obserwator został dodany do jakiejś kolekcji (albo usunąć go), to
-     * nie musimy go wrappować - możemy go przekazać bezpośrednio.
-     * </p>
-     */
-    static final class TypedListener implements EventListener<Event> {
-        private final Class<?> type;
-        private final EventListener<Event> handler;
-
-        @SuppressWarnings("unchecked")
-        public <E> TypedListener(Class<E> type, EventListener<? super E> handler) {
-            this.type = type;
-            this.handler = (EventListener<Event>)handler;
-        }
-
-        @SuppressWarnings("unchecked")
-        public <E> TypedListener(EventListener<? super NamedEvent> handler) {
-            this.type = NamedEvent.class;
-            this.handler = (EventListener<Event>)handler;
-        }
-
-        @Override
-        public void handleEvent(Event event) {
-            if(type.isInstance(event)) {
-                this.handler.handleEvent(event);
-            }
-        }
-
-        @Override
-        public boolean equals(Object object) {
-            if( this == object || handler.equals(object)) {
-                return true;
-            }
-            if( object instanceof TypedListener) {
-                return ((TypedListener)object).handler == handler;
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return this.handler.hashCode();
-        }
-    }
-
-}

+ 0 - 149
src/main/java/net/ranides/assira/events/NamedEventRouter.java

@@ -1,149 +0,0 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.events;
-
-/**
- * EventRouter oferujący wsparcie dla rozszerzonej obsługi nazwanych zdarzeń
- * (dziedziczących po {@link NamedEvent}. Klasa może realizować propagację
- * komunikatów w sposób identyczny jak {@link EventRouterDispatcher} albo według
- * strategii {@link EventRouterThread} - zależnie od tego, za pomocą której metody
- * statycznej zostanie utworzona.
- *
- *
- * <p>
- * {@code NamedEventListener} posiada funkcjonalność wiązania  podobną do {@link
- * ReflectEventListener}. Klasy pochodne mogą deklarować metody (niekoniecznie
- * publiczne), które zostaną uruchomione, jeśli do obserwatora zostanie wysłane
- * określone zdarzenie. Deklaracja metody obsługi zdarzeń ma następującą postać:
- * <ul>
- *      <li>metoda pobiera tylko jeden argument</li>
- *      <li>typ argumentu odpowiada typowi obserwowanego zdarzenia</li>
- *      <li>metoda jest adnotowana za pomocą {@link net.ranides.assira.annotations.Meta.EventHandler}</li>
- *      <li>{@link net.ranides.assira.annotations.Meta.EventHandler} obowiązkowo zawiera nazwę obserwowanego zdarzenia</li>
- *      <li>{@link net.ranides.assira.annotations.Meta.EventHandler} opcjonalnie określa sposób synchronizacji metody względem innych wątków</li>
- * </ul>
- * </p>
- *
- * <table style="margin: 10px 0 0 0; background: #c0F0c0; border: solid 1px #006000;" cellpadding="0"><tr><td>thread-safe class</td></tr></table>
- * @author ranides
- */
-public class NamedEventRouter extends NamedEventListener {
-
-    /**
-     * Tworzy nowy router typu {@code NamedEventRouter}, który kolejkuje zdarzenia.
-     * Wywołuje procedury obsługi w bliżej nieokreślonym czasie po zasygnalizowaniu zdarzenia.
-     * Utworzony obiekt należy zniszczyć po użyciu za pomocą {@link #dispose() }.
-     * <p>
-     * Utworzony obiekt {@code EventRouter} obsługuje mechanizm złączania zdarzeń
-     * w oparciu o strategię realizowaną przez {@link EventJoiner} przekazany jako
-     * argument.
-     * </p>
-     * @param name nazwa wątku, który będzie przetwarzał zdarzenia
-     * @param size maksymalny rozmiar wewnętrznej kolejki komunikatów
-     * @param maxtime maksymalny czas oczekiwania na miejsce w kolejce komunikatów
-     * @param joiner procedura implementująca mechanizm łączenia wielu zdarzeń w jedno
-     * @see EventRouterThread
-     * @return
-     */
-    public static NamedEventRouter newInstance(String name, int size, int maxtime, EventJoiner joiner) {
-        return new RouterDelegator( EventRouterThread.newInstance(name, size, maxtime, joiner) ).init();
-    }
-
-    /**
-     * Tworzy nowy router typu {@code NamedEventRouter}, który kolejkuje zdarzenia.
-     * Wywołuje procedury obsługi w bliżej nieokreślonym czasie po zasygnalizowaniu zdarzenia.
-     * Utworzony obiekt należy zniszczyć po użyciu za pomocą {@link #dispose() }.
-     * @param name nazwa wątku, który będzie przetwarzał zdarzenia
-     * @param size maksymalny rozmiar wewnętrznej kolejki komunikatów
-     * @param maxtime maksymalny czas oczekiwania na miejsce w kolejce komunikatów
-     * @see EventRouterThread
-     * @return
-     */
-    public static NamedEventRouter newInstance(String name, int size, int maxtime) {
-        return new RouterDelegator( EventRouterThread.newInstance(name, size, maxtime) ).init();
-    }
-
-    /**
-     * Tworzy nowy router typu {@code NamedEventRouter}, który nie kolejkuje zdarzeń.
-     * Wywołuje procedury obsługi natychmiast po wywołaniu zdarzenia, w wątku, który
-     * zasygnalizował event.
-     * @see EventRouterDispatcher
-     * @return
-     */
-    public static NamedEventRouter newInstance() {
-        return new NamedEventRouter();
-    }
-
-    private NamedEventRouter() {
-        super(false);
-    }
-
-/* ************************************************************************** */
-
-    private static final class RouterDelegator extends NamedEventRouter {
-        private final EventRouter router;
-        private final EventListener<DelegateEvent> handler;
-
-        public RouterDelegator(EventRouter router) {
-            this.router = router;
-            this.handler = new DelegateListener(this);
-        }
-
-        public NamedEventRouter init() {
-            router.addEventListener(DelegateEvent.class, handler);
-            return this;
-        }
-
-        @Override
-        public void dispose() {
-            router.removeEventListener(DelegateEvent.class, handler);
-            super.dispose();
-        }
-
-        @Override
-        public boolean signalEvent(Event event) {
-            if(!(event instanceof NamedEvent)) {
-                return false;
-            }
-            return router.signalEvent(new DelegateEvent(this, (NamedEvent)event) );
-        }
-    }
-
-/* ************************************************************************** */
-
-    private static final class DelegateEvent implements Event {
-        private final NamedEventRouter target;
-        private final NamedEvent cause;
-
-        public DelegateEvent(NamedEventRouter target, NamedEvent cause) {
-            this.target = target;
-            this.cause = cause;
-        }
-        public NamedEvent cause() {
-            return cause;
-        }
-        public NamedEventRouter target() {
-            return target;
-        }
-    }
-
-    private static final class DelegateListener implements EventListener<DelegateEvent> {
-        private final NamedEventRouter owner;
-
-        public DelegateListener(NamedEventRouter owner) {
-            this.owner = owner;
-        }
-        @Override
-        public void handleEvent(DelegateEvent event) {
-            if( owner.equals(event.target()) ) {
-                    owner.dispatchEvent(event.cause());
-                }
-        }
-    }
-
-
-}

+ 0 - 58
src/main/java/net/ranides/assira/events/Observable.java

@@ -1,58 +0,0 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.events;
-
-/**
- * Interfejs reprezentujący obiekty sygnalizujące zdarzenia {@link NamedEvent}, 
- * a więc do których można podpiąć obserwatory oczekujące na zdarzenia określonego
- * typu o określonej nazwie.
- * @author ranides
- */
-public interface Observable extends EventRouter {
-    
-    /**
-     * Rejestruje obserwatora, który otrzyma wszystkie zdarzenia o podanej nazwie.
-     * @param name
-     * @param listener
-     * @return
-     */
-    Observable bind(String name, EventListener<? super NamedEvent> listener);
-    
-    /**
-     * Rejestruje obserwatora, który otrzyma wszystkie zdarzenia o podanej
-     * nazwie oraz typie.
-     * @param <T>
-     * @param name
-     * @param type
-     * @param listener
-     * @return
-     */
-    <T extends NamedEvent> Observable bind(String name, Class<T> type, EventListener<? super T> listener);
-    
-    /**
-     * Usuwa obserwatora, którego wcześniej dodano za pomocą metody {@link #bind}.
-     * Jeśli zajestrowano go wielokrotnie dla wielu różnych zdarzeń o podanej 
-     * nazwie - usuwane jest tylko jedno wiązanie. Jeśli zajestrowano go również dla
-     * zdarzeń o innych nazwach - zostają one nadal. Wiekrotna rejestrowane obserwatory 
-     * musi zostać usunięte również wielokrotnie.
-     * zachowane.
-     * @param name
-     * @param listener
-     * @return
-     */
-    Observable unbind(String name, EventListener<? super NamedEvent> listener);
-    
-    /**
-     * Usuwa obserwatora, którego wcześniej dodano za pomocą metody {@link #bind}.
-     * Usuwane są wszystkie powiązania, bez względu na typ i nazwy obserwowanych
-     * zdarzeń, jeśli obserwator był rejestrowany wielokrotnie.
-     * @param listener
-     * @return
-     */
-    Observable unbind(EventListener<? super NamedEvent> listener);
-    
-}

+ 7 - 3
src/test/java/net/ranides/assira/events/EventRouterThreadTest.java

@@ -54,6 +54,7 @@ public class EventRouterThreadTest {
     @Test
     public void testPropagation() {
         HitMap hits = new HitMap();
+        EventRouterThread unknown = EventRouterThread.newInstance("unknown", 32, 1000);
         EventRouterThread main = EventRouterThread.newInstance("name", 32, 1000);
 
         main.addEventListener(Event.class, hits.new HitListener<Event>("global") );
@@ -66,8 +67,8 @@ public class EventRouterThreadTest {
         main.signalEvent(new WriteEvent());
         main.signalEvent(new ReadEvent());
         main.signalEvent(new Event(){});
-        main.signalEvent(new ExitEvent("unknown") );
-        main.signalEvent(new ExitEvent("name") );
+        main.signalEvent(new ExitEvent(unknown) );
+        main.signalEvent(new ExitEvent(main) );
 
         main.stop();
 
@@ -79,18 +80,20 @@ public class EventRouterThreadTest {
         assertEquals(ArrayUtils.asList(8,10), hits.get("exit"));
         assertEquals(ArrayUtils.asList(12), hits.get("shutdown"));
 
+        unknown.dispose();
     }
 
     @Test
     public void testStop() {
         HitMap hits = new HitMap();
+        EventRouterThread unknown = EventRouterThread.newInstance("unknown", 32, 1000);
         EventRouterThread main = EventRouterThread.newInstance("name", 32, 1000);
 
         main.addEventListener(Event.class, hits.new HitListener<Event>("global") );
         main.addEventListener(ShutdownEvent.class, hits.new HitListener<ShutdownEvent>("shutdown") );
         main.addEventListener(ExitEvent.class, hits.new HitListener<ExitEvent>("exit") );
 
-        main.signalEvent(new ExitEvent("unknown") );
+        main.signalEvent(new ExitEvent(unknown) );
 
         main.stop();
 
@@ -99,6 +102,7 @@ public class EventRouterThreadTest {
         assertEquals(ArrayUtils.asList(1,3), hits.get("exit"));
         assertEquals(ArrayUtils.asList(5), hits.get("shutdown"));
 
+        unknown.dispose();
     }
 
     @SuppressWarnings("PMD")

+ 0 - 194
src/test/java/net/ranides/assira/events/NamedEventListenerTest.java

@@ -1,194 +0,0 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-
-package net.ranides.assira.events;
-
-import java.util.LinkedList;
-import java.util.List;
-import net.ranides.assira.annotations.Meta;
-import net.ranides.assira.collection.ArrayUtils;
-import net.ranides.assira.collection.SetUtils;
-import net.ranides.assira.collection.map.LazyMap;
-import net.ranides.assira.trace.LoggerUtils;
-import org.junit.Test;
-import static org.junit.Assert.*;
-
-/**
- *
- * @author ranides
- */
-@SuppressWarnings("PMD.AvoidDuplicateLiterals")
-public class NamedEventListenerTest {
-    
-    public NamedEventListenerTest() {
-        LoggerUtils.initTest();
-    }
-    
-    private static class LoadListener extends NamedEventListener {
-        
-        @Meta.EventHandler("load")
-        public void onLoad(NamedEvent event) {
-            /* do nothing */
-        }
-        
-    }
-    
-    private static class HitMap extends LazyMap<String, List<Integer>>  {
-        private int counter = 0;
-
-        @Override
-        public List<Integer> apply(String source) {
-            return new LinkedList<Integer>();
-        }
-        
-        public void add(String name) {
-            get(name).add(counter++);
-        }
-
-    };
-    
-    @Test
-    public void testHandle() {
-        final HitMap hits = new HitMap();
-        
-        NamedEventListener handler = new NamedEventListener() {
-
-            @Meta.EventHandler("load")
-            public void onLoad(NamedEvent event) {
-                hits.add("load");
-            }
-
-            @Meta.EventHandler("click")
-            public void onClick(NamedEvent event) {
-                hits.add("click");
-            }
-
-            @Meta.EventHandler("unload")
-            protected void onUnload(NamedEvent event) {
-                hits.add("unload");
-            }
-        };
-        
-        handler.bind("dynamic", new EventListener<NamedEvent>(){
-            @Override
-            public void handleEvent(NamedEvent event) {
-                hits.add("dynamic");
-            }
-        });
-        handler.bind("io", new EventListener<NamedEvent>(){
-            @Override
-            public void handleEvent(NamedEvent event) {
-                hits.add("nio");
-            }
-        });
-        handler.bind("io", IOEvent.class, new EventListener<NamedEvent>(){
-            @Override
-            public void handleEvent(NamedEvent event) {
-                hits.add("io");
-            }
-        });
-        
-        EventRouter main = new EventRouterDispatcher();
-        
-        main.addEventListener(NamedEvent.class, handler);
-        
-        main.signalEvent(new NamedEvent("load"));
-        main.signalEvent(new NamedEvent("click"));
-        main.signalEvent(new NamedEvent("click"));
-        main.signalEvent(new NamedEvent("unload"));
-        main.signalEvent(new NamedEvent("dynamic"));
-        main.signalEvent(new IOEvent());
-        main.signalEvent(new NamedEvent("io"));
-        
-        assertEquals(SetUtils.asHashSet("load", "unload", "click", "dynamic", "io", "nio"), hits.keySet());
-        assertEquals(ArrayUtils.asList(0), hits.get("load"));
-        assertEquals(ArrayUtils.asList(1,2), hits.get("click"));
-        assertEquals(ArrayUtils.asList(3), hits.get("unload"));
-        
-        assertEquals(ArrayUtils.asList(4), hits.get("dynamic"));
-        assertEquals(ArrayUtils.asList(6), hits.get("io"));
-        assertEquals(ArrayUtils.asList(5,7), hits.get("nio"));
-    }
-    
-    
-    @Test
-    public void testOverrideHandle() {
-        final HitMap hits = new HitMap();
-        
-        LoadListener handler = new LoadListener() {
-            @Override
-            public void onLoad(NamedEvent event) {
-                hits.add("load");
-            }
-        };
-        
-        EventRouter main = new EventRouterDispatcher();
-        
-        main.addEventListener(NamedEvent.class, handler);
-        
-        main.signalEvent(new NamedEvent("load"));
-        
-        assertEquals(SetUtils.asHashSet("load"), hits.keySet());
-        assertEquals(ArrayUtils.asList(0), hits.get("load"));
-
-    }
-    
-    
-    @Test
-    public void testBindings() {
-        final HitMap hits = new HitMap();
-        
-        NamedEventListener handler = new NamedEventListener();
-        
-        handler.bind("load", new EventListener<NamedEvent>(){
-            @Override public void handleEvent(NamedEvent event) {
-                hits.add("load");
-            }
-        });
-        handler.bind("unload", new EventListener<NamedEvent>(){
-            @Override public void handleEvent(NamedEvent event) { 
-                hits.add("unload"); 
-            }
-        });    
-        handler.bind("io", new EventListener<NamedEvent>(){
-            @Override public void handleEvent(NamedEvent event) { 
-                hits.add("io"); 
-            }
-        });
-        handler.bind("io", IOEvent.class, new EventListener<IOEvent>(){
-            @Override public void handleEvent(IOEvent event) { 
-                hits.add("tio"); 
-            }
-        });
-        
-        EventRouter main = new EventRouterDispatcher();
-        
-        main.addEventListener(NamedEvent.class, handler);
-        
-        main.signalEvent(new NamedEvent("load"));
-        main.signalEvent(new NamedEvent("unload"));
-        main.signalEvent(new IOEvent());
-        main.signalEvent(new NamedEvent("io"));
-        
-        
-        assertEquals(SetUtils.asHashSet("unload","load", "io", "tio"), hits.keySet());
-        assertEquals(ArrayUtils.asList(0), hits.get("load"));
-        assertEquals(ArrayUtils.asList(1), hits.get("unload"));
-        assertEquals(ArrayUtils.asList(2,4), hits.get("io"));
-        assertEquals(ArrayUtils.asList(3), hits.get("tio"));
-
-    }
-    
-    class IOEvent extends NamedEvent {
-
-        public IOEvent() {
-            super("io");
-        }
-        
-    }
-
-}