Skip to content

Commit bdf7467

Browse files
committed
EventHandler: add optional key attribute
This attribute is a unique subscription key. If multiple EventHandler annotations exist with the same key, only the first to be subscribed will be respected; the others will be silently ignored. If no key is specified, the event handler is always subscribed. This feature exists to enable better extensibility of event handling: if code exists that handles an event in an undesirable way, that logic can be completely intercepted and overridden by writing more code that handles the event in a better way, specifying the same key as the original.
1 parent ca91f4e commit bdf7467

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

src/main/java/org/scijava/event/DefaultEventService.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.lang.reflect.Method;
3636
import java.util.ArrayList;
3737
import java.util.Collection;
38+
import java.util.HashSet;
3839
import java.util.List;
3940
import java.util.WeakHashMap;
4041

@@ -79,6 +80,12 @@ public class DefaultEventService extends AbstractService implements
7980

8081
private DefaultEventBus eventBus;
8182

83+
/**
84+
* Set of claimed {@link EventHandler#key()}s. Additional event handlers
85+
* specifying the same key will be ignored rather than subscribed.
86+
*/
87+
private final HashSet<String> keys = new HashSet<String>();
88+
8289
// -- EventService methods --
8390

8491
@Override
@@ -100,11 +107,23 @@ public List<EventSubscriber<?>> subscribe(final Object o) {
100107
final List<Method> eventHandlers =
101108
ClassUtils.getAnnotatedMethods(o.getClass(), EventHandler.class);
102109
for (final Method m : eventHandlers) {
110+
// verify that the event handler method is valid
103111
final Class<? extends SciJavaEvent> eventClass = getEventClass(m);
104112
if (eventClass == null) {
105113
log.warn("Invalid EventHandler method: " + m);
106114
continue;
107115
}
116+
117+
// verify that the event handler key isn't already claimed
118+
final String key = m.getAnnotation(EventHandler.class).key();
119+
if (!key.isEmpty()) {
120+
synchronized (keys) {
121+
if (keys.contains(key)) continue;
122+
keys.add(key);
123+
}
124+
}
125+
126+
// subscribe the event handler
108127
subscribers.add(subscribe(eventClass, o, m));
109128
}
110129
return subscribers;

src/main/java/org/scijava/event/EventHandler.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,19 @@
5959
@Retention(RetentionPolicy.RUNTIME)
6060
@Target(ElementType.METHOD)
6161
public @interface EventHandler {
62-
// no attributes
62+
63+
/**
64+
* Unique subscription key. If multiple {@code @EventHandler} annotations
65+
* exist with the same key, only the first to be subscribed will be respected;
66+
* the others will be silently ignored. If no key is specified, the event
67+
* handler is always subscribed.
68+
* <p>
69+
* This feature exists to enable better extensibility of event handling: if
70+
* code exists that handles an event in an undesirable way, that logic can be
71+
* completely intercepted and overridden by writing more code that handles the
72+
* event in a better way, specifying the same key as the original.
73+
* </p>
74+
*/
75+
String key() default "";
76+
6377
}

0 commit comments

Comments
 (0)