/*______________________________________________________________________________ * * org.eidola.kernel.event.EventBroadcaster * * Part of the Eidola Kernel Reference Implementation * See http://eidola.org for oodles of relevant fun! * *______________________________________________________________________________ * * Copyright 2000-2001 Paul Cantrell * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2, as published by the * Free Software Foundation. See the file LICENSE.html for more information. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc. / 59 Temple * Place, Suite 330 / Boston, MA 02111-1307 / USA. *_______________________________________________________________________________ */ package org.eidola.kernel.event; import org.eidola.util.CollectionDiff; import java.util.*; /** A source of Eidola {@link Event}s. Implementors of the {@link EventListener} interface can register themselves with an EventBroadcaster via {@link #addListener(EventListener listener, EventQueue queue) addListener()}. When registering, the new listener must specify an {@link EventQueue}. When an EventBroadcaster sends out an event (through a call to {@link #broadcastEvent(Event) broadcastEvent()}), the registered {@link EventListener}s receive it on their respective {@link EventQueue}s.

Eidola allows associates different listeners with potentially different queues in order to encourage multithreading. Each queue can run on a different thread (or {@link org.eidola.util.ThreadFlock}). So, for example, three threads can compile elements while another thread concurrently updates their display in a UI. @see Event @see EventListener @see EventQueue @author Paul Cantrell @version [Development version] */ public class EventBroadcaster { /** Create a new broadcaster with no listeners. */ public EventBroadcaster() { listeners = new HashMap(); } /** Registers a listener with this broadcaster. A listener * may only be associated with one queue at a time; registering * a listener with a new queue unregisters it with the old one. * @param listener The listener which wishes to receive events from this broadcaster. * @param queue The queue on which the events will appear. */ public void addListener(EventListener listener, EventQueue queue) { if(listener == null) throw new NullPointerException("listener == null " + this + " q == " + queue); synchronized(listeners) { listeners.put(listener, queue); } } /** Unregisters a listener with this broadcaster. * @param listener A listener which no longer wishes to receive events. */ public void removeListener(EventListener listener) { synchronized(listeners) { listeners.remove(listener); } } /** Broadcasts an event to all registered listeners on their respective queues. * Subclasses might override this to track events or impose conditions on which * kinds this broadcaster can broadcast. * @param event The event to broadcast */ public void broadcastEvent(Event event) { if(debugEvents) System.out.println(" #(e) " + event.toString()); synchronized(listeners) { for(Iterator l = listeners.keySet().iterator(); l.hasNext(); ) { EventListener target = (EventListener) l.next(); EventQueue queue = (EventQueue) listeners.get(target); queue.addEvent(event, target); } } } /** A utility method to make a broadcaster's listeners mirror a changing collection. * This method compares an old and a new collection of EventBroadcasters. *

* @param listener The listener which will mirror the additions and removals. * @param eventq The queue on which newly added broadcasters will get registered. * @param oldBroadcasters The collection of EventBroadcasters as it was. * @param newBroadcasters The collection of EventBroadcasters as it is now. */ static public void updateBroadcasters( EventListener listener, EventQueue eventq, Collection oldBroadcasters, Collection newBroadcasters) { CollectionDiff diff = new CollectionDiff(oldBroadcasters, newBroadcasters); for(Iterator a = diff.getAdded().iterator(); a.hasNext(); ) ((EventBroadcaster) a.next()).addListener(listener, eventq); for(Iterator r = diff.getRemoved().iterator(); r.hasNext(); ) ((EventBroadcaster) r.next()).removeListener(listener); } private Map /*[EventListener,EventQueue]*/ listeners; static public boolean debugEvents = false; }