/* * 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); } }