[Home]PluggableRobot/ListenerDelegate

Robo Home | PluggableRobot | Changes | Preferences | AllPages

/*
 * PluggableRobot, by Robert J. Walker
 * Home page: http://robowiki.net/cgi-bin/robowiki?PluggableRobot
 * This software is made available under the RoboWiki Limited Public Code License (RWLPCL). The full
 * text of the license may be found at http://robowiki.net/cgi-bin/robowiki?RWLPCL.
 */
package rjw.pluggablerobot;

import java.util.*;

import robocode.*;

/**
 * Class that manages all the event listeners for a PluggableRobot and delegates events to the
 * appropriate EventListeners. Unlike the default Robocode behavior, events are doled out first by
 * listener (first registered, first notified), then by the order of the listener interfaces
 * declared on the listener implementation. So a class with a declaration like this:
 *     public class MyClass implements ScannedRobotListener, EventListener.Death
 * ...will get notified of the ScannedRobotEvent *before* the DeathEvent!
 * @author Robert J. Walker
 */
public class ListenerDelegate {
	private ArrayList<EventListener> _listeners = new ArrayList<EventListener>();
	private static HashMap<Class<? extends EventListener>, ListenerInvoker> _invokers;

	// Build the invoker map, allowing us to look up invokers by listener class
	static {
		_invokers = new HashMap<Class<? extends EventListener>, ListenerInvoker>();
		_invokers.put(EventListener.Death.class,
				new ListenerInvoker<EventListener.Death, DeathEvent>() {
					protected Class<DeathEvent> eventClass() { return DeathEvent.class; }
					protected void invokeListener(EventListener.Death listener, DeathEvent event) {
						listener.notifyDeath(event);
					}
				}
		);
		_invokers.put(EventListener.Win.class,
				new ListenerInvoker<EventListener.Win, WinEvent>() {
					protected Class<WinEvent> eventClass() { return WinEvent.class; }
					protected void invokeListener(EventListener.Win listener, WinEvent event) {
						listener.notifyWin(event);
					}
				}
		);
		_invokers.put(EventListener.SkippedTurn.class,
				new ListenerInvoker<EventListener.SkippedTurn, SkippedTurnEvent>() {
					protected Class<SkippedTurnEvent> eventClass() { return SkippedTurnEvent.class; }
					protected void invokeListener(EventListener.SkippedTurn listener, SkippedTurnEvent event) {
						listener.notifySkippedTurn(event);
					}
				}
		);
		_invokers.put(EventListener.ScannedRobot.class,
				new ListenerInvoker<EventListener.ScannedRobot, ScannedRobotEvent>() {
					protected Class<ScannedRobotEvent> eventClass() { return ScannedRobotEvent.class; }
					protected void invokeListener(EventListener.ScannedRobot listener, ScannedRobotEvent event) {
						listener.notifyScannedRobot(event);
					}
				}
		);
		_invokers.put(EventListener.HitByBullet.class,
				new ListenerInvoker<EventListener.HitByBullet, HitByBulletEvent>() {
					protected Class<HitByBulletEvent> eventClass() { return HitByBulletEvent.class; }
					protected void invokeListener(EventListener.HitByBullet listener, HitByBulletEvent event) {
						listener.notifyHitByBullet(event);
					}
				}
		);
		_invokers.put(EventListener.BulletHit.class,
				new ListenerInvoker<EventListener.BulletHit, BulletHitEvent>() {
					protected Class<BulletHitEvent> eventClass() { return BulletHitEvent.class; }
					protected void invokeListener(EventListener.BulletHit listener, BulletHitEvent event) {
						listener.notifyBulletHit(event);
					}
				}
		);
		_invokers.put(EventListener.BulletHitBullet.class,
				new ListenerInvoker<EventListener.BulletHitBullet, BulletHitBulletEvent>() {
					protected Class<BulletHitBulletEvent> eventClass() { return BulletHitBulletEvent.class; }
					protected void invokeListener(EventListener.BulletHitBullet listener, BulletHitBulletEvent event) {
						listener.notifyBulletHitBullet(event);
					}
				}
		);
		_invokers.put(EventListener.BulletMissed.class,
				new ListenerInvoker<EventListener.BulletMissed, BulletMissedEvent>() {
					protected Class<BulletMissedEvent> eventClass() { return BulletMissedEvent.class; }
					protected void invokeListener(EventListener.BulletMissed listener, BulletMissedEvent event) {
						listener.notifyBulletMissed(event);
					}
				}
		);
		_invokers.put(EventListener.HitRobot.class,
				new ListenerInvoker<EventListener.HitRobot, HitRobotEvent>() {
					protected Class<HitRobotEvent> eventClass() { return HitRobotEvent.class; }
					protected void invokeListener(EventListener.HitRobot listener, HitRobotEvent event) {
						listener.notifyHitRobot(event);
					}
				}
		);
		_invokers.put(EventListener.HitWall.class,
				new ListenerInvoker<EventListener.HitWall, HitWallEvent>() {
					protected Class<HitWallEvent> eventClass() { return HitWallEvent.class; }
					protected void invokeListener(EventListener.HitWall listener, HitWallEvent event) {
						listener.notifyHitWall(event);
					}
				}
		);
		_invokers.put(EventListener.RobotDeath.class,
				new ListenerInvoker<EventListener.RobotDeath, RobotDeathEvent>() {
					protected Class<RobotDeathEvent> eventClass() { return RobotDeathEvent.class; }
					protected void invokeListener(EventListener.RobotDeath listener, RobotDeathEvent event) {
						listener.notifyRobotDeath(event);
					}
				}
		);
	}

	/**
	 * Register a new EventListener.
	 */
	public void register(EventListener listener) {
		_listeners.add(listener);
	}

	/**
	 * Hand out event notifications to the EventListeners. 
	 */
	public void processEvents(Vector<Event> events) {
		// Notify listeners in the order they were registered
		for(EventListener listener : _listeners) {
			Class[] interfaces = listener.getClass().getInterfaces();

			// Iterate the interfaces on each listener that descend from EventListener
			for(Class iface : interfaces) {
				if(!EventListener.class.isAssignableFrom(iface)) continue;

				// Get the invoker and the corresponding event class for this interface
				ListenerInvoker invoker = _invokers.get(iface);
				Class<? extends Event> eventClass = invoker.eventClass();

				// Iterate the events and hand the ones of the proper type to the invoker
				for(Event event : events) {
					if(!eventClass.isAssignableFrom(event.getClass())) continue;
					invoker.invokeListener(listener, event);
				}
			}
		}
	}

	
	/**
	 * An object that knows about a Robocode Event class and how to invoke its corresponding
	 * EventListener.
	 * @author Robert J. Walker
	 */
	private static abstract class ListenerInvoker<K extends EventListener, V extends Event> {
		/**
		 * Returns the Robocode Event class handled by this ListenerInvoker.
		 */
		protected abstract Class<V> eventClass();

		/**
		 * Invokes the given EventListener, passing in a Robocode Event object.
		 */
		protected abstract void invokeListener(K listener, V event);
	}
}

Robo Home | PluggableRobot | Changes | Preferences | AllPages
Edit text of this page | View other revisions
Last edited November 2, 2007 23:51 EST by RobertWalker (diff)
Search: