buildcraft/common/buildcraft/transport/PipeEventBus.java
2015-09-20 11:20:30 +02:00

125 lines
3.7 KiB
Java

package buildcraft.transport;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import buildcraft.transport.pipes.events.PipeEvent;
import buildcraft.transport.pipes.events.PipeEventPriority;
public class PipeEventBus {
private class EventHandler {
public Method method;
public Object owner;
public EventHandler(Method m, Object o) {
this.method = m;
this.owner = o;
}
@Override
public boolean equals(Object o) {
if (o == null || !(o instanceof EventHandler)) {
return false;
}
EventHandler e = (EventHandler) o;
return e.method.equals(method) && e.owner == owner;
}
}
private static class EventHandlerCompare implements Comparator<EventHandler> {
private int getPriority(EventHandler eh) {
PipeEventPriority p = eh.method.getAnnotation(PipeEventPriority.class);
return p != null ? p.priority() : 0;
}
@Override
public int compare(EventHandler o1, EventHandler o2) {
int priority1 = getPriority(o1);
int priority2 = getPriority(o2);
return priority2 - priority1;
}
}
private static final EventHandlerCompare COMPARATOR = new EventHandlerCompare();
private static final HashSet<Object> globalHandlers = new HashSet<Object>();
private final HashSet<Object> registeredHandlers = new HashSet<Object>();
private final HashMap<Object, Map<Method, Class<? extends PipeEvent>>> handlerMethods = new HashMap<Object, Map<Method, Class<? extends PipeEvent>>>();
private final HashMap<Class<? extends PipeEvent>, List<EventHandler>> eventHandlers = new HashMap<Class<? extends PipeEvent>, List<EventHandler>>();
public PipeEventBus() {
for (Object o : globalHandlers) {
registerHandler(o);
}
}
public static void registerGlobalHandler(Object globalHandler) {
globalHandlers.add(globalHandler);
}
private List<EventHandler> getHandlerList(Class<? extends PipeEvent> event) {
if (!eventHandlers.containsKey(event)) {
eventHandlers.put(event, new ArrayList<EventHandler>());
}
return eventHandlers.get(event);
}
public void registerHandler(Object handler) {
if (registeredHandlers.contains(handler)) {
return;
}
registeredHandlers.add(handler);
Map<Method, Class<? extends PipeEvent>> methods = new HashMap<Method, Class<? extends PipeEvent>>();
for (Method m : handler.getClass().getDeclaredMethods()) {
if ("eventHandler".equals(m.getName())) {
Class<?>[] parameters = m.getParameterTypes();
if (parameters.length == 1 && PipeEvent.class.isAssignableFrom(parameters[0])) {
Class<? extends PipeEvent> eventType = (Class<? extends PipeEvent>) parameters[0];
List<EventHandler> eventHandlerList = getHandlerList(eventType);
eventHandlerList.add(new EventHandler(m, handler));
updateEventHandlers(eventHandlerList);
methods.put(m, eventType);
}
}
}
handlerMethods.put(handler, methods);
}
private void updateEventHandlers(List<EventHandler> eventHandlerList) {
Collections.sort(eventHandlerList, COMPARATOR);
}
public void unregisterHandler(Object handler) {
if (!registeredHandlers.contains(handler)) {
return;
}
registeredHandlers.remove(handler);
Map<Method, Class<? extends PipeEvent>> methodMap = handlerMethods.get(handler);
for (Method m : methodMap.keySet()) {
getHandlerList(methodMap.get(m)).remove(new EventHandler(m, handler));
}
handlerMethods.remove(handler);
}
public void handleEvent(Class<? extends PipeEvent> eventClass, PipeEvent event) {
for (EventHandler eventHandler : getHandlerList(eventClass)) {
try {
eventHandler.method.invoke(eventHandler.owner, event);
} catch (Exception e) {
}
}
}
}