package org.bukkit.event; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.RegisteredListener; import java.util.*; import java.util.Map.Entry; /** * A list of event handlers, stored per-event. Based on lahwran's fevents. */ public class HandlerList { /** * Handler array. This field being an array is the key to this system's speed. */ private RegisteredListener[] handlers = null; /** * Dynamic handler lists. These are changed using register() and * unregister() and are automatically baked to the handlers array any * time they have changed. */ private final EnumMap> handlerslots; /** * List of all HandlerLists which have been created, for use in bakeAll() */ private static ArrayList allLists = new ArrayList(); /** * Bake all handler lists. Best used just after all normal event * registration is complete, ie just after all plugins are loaded if * you're using fevents in a plugin system. */ public static void bakeAll() { for (HandlerList h : allLists) { h.bake(); } } /** * Unregister all listeners from all handler lists. */ public static void unregisterAll() { for (HandlerList h : allLists) { for (List list : h.handlerslots.values()) { list.clear(); } h.handlers = null; } } /** * Unregister a specific plugin's listeners from all handler lists. * * @param plugin plugin to unregister */ public static void unregisterAll(Plugin plugin) { for (HandlerList h : allLists) { h.unregister(plugin); } } /** * Unregister a specific listener from all handler lists. * * @param listener listener to unregister */ public static void unregisterAll(Listener listener) { for (HandlerList h : allLists) { h.unregister(listener); } } /** * Create a new handler list and initialize using EventPriority * The HandlerList is then added to meta-list for use in bakeAll() */ public HandlerList() { handlerslots = new EnumMap>(EventPriority.class); for (EventPriority o : EventPriority.values()) { handlerslots.put(o, new ArrayList()); } allLists.add(this); } /** * Register a new listener in this handler list * * @param listener listener to register */ public void register(RegisteredListener listener) { if (handlerslots.get(listener.getPriority()).contains(listener)) throw new IllegalStateException("This listener is already registered to priority " + listener.getPriority().toString()); handlers = null; handlerslots.get(listener.getPriority()).add(listener); } /** * Register a collection of new listeners in this handler list * * @param listeners listeners to register */ public void registerAll(Collection listeners) { for (RegisteredListener listener : listeners) { register(listener); } } /** * Remove a listener from a specific order slot * * @param listener listener to remove */ public void unregister(RegisteredListener listener) { if (handlerslots.get(listener.getPriority()).remove(listener)) { handlers = null; } } /** * Remove a specific plugin's listeners from this handler * * @param plugin plugin to remove */ public void unregister(Plugin plugin) { boolean changed = false; for (List list : handlerslots.values()) { for (ListIterator i = list.listIterator(); i.hasNext();) { if (i.next().getPlugin().equals(plugin)) { i.remove(); changed = true; } } } if (changed) handlers = null; } /** * Remove a specific listener from this handler * * @param listener listener to remove */ public void unregister(Listener listener) { boolean changed = false; for (List list : handlerslots.values()) { for (ListIterator i = list.listIterator(); i.hasNext();) { if (i.next().getListener().equals(listener)) { i.remove(); changed = true; } } } if (changed) handlers = null; } /** * Bake HashMap and ArrayLists to 2d array - does nothing if not necessary */ public void bake() { if (handlers != null) return; // don't re-bake when still valid List entries = new ArrayList(); for (Entry> entry : handlerslots.entrySet()) { entries.addAll(entry.getValue()); } handlers = entries.toArray(new RegisteredListener[entries.size()]); } /** * Get the baked registered listeners associated with this handler list * * @return the array of registered listeners */ public RegisteredListener[] getRegisteredListeners() { bake(); return handlers; } /** * Get a specific plugin's registered listeners associated with this handler list * * @param plugin the plugin to get the listeners of * * @return the list of registered listeners */ public static ArrayList getRegisteredListeners(Plugin plugin) { ArrayList listeners = new ArrayList(); for (HandlerList h : allLists) { for (List list : h.handlerslots.values()) { for (RegisteredListener listener : list) { if (listener.getPlugin().equals(plugin)) { listeners.add(listener); } } } } return listeners; } /** * Get a list of all handler lists for every event type * * @return the list of all handler lists */ @SuppressWarnings("unchecked") public static ArrayList getHandlerLists() { return (ArrayList) allLists.clone(); } }