1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
14 * @author Toni Kalajainen
16 package org.simantics.scenegraph.g2d.events;
18 import java.lang.annotation.ElementType;
19 import java.lang.annotation.Retention;
20 import java.lang.annotation.RetentionPolicy;
21 import java.lang.annotation.Target;
22 import java.lang.reflect.InvocationTargetException;
23 import java.lang.reflect.Method;
24 import java.util.ArrayList;
25 import java.util.List;
28 * @author Toni Kalajainen
30 public class EventHandlerReflection {
32 @Retention(RetentionPolicy.RUNTIME)
33 @Target(ElementType.METHOD)
34 public static @interface EventHandler {
39 * Scans an object with reflection for all event handler methods and returns
40 * an array of IEventHandler and priorities.
42 * The corresponding class of obj must contain methods that meet the
43 * following criteria: 1) must return boolean 2) 1 argument, which is Event
44 * 3) has annotation EventHandler 4) may not throw any Exception 5) method
49 * @EventHandler(priority = Integer.MAX_VALUE) public boolean
50 * handleEvent(Event e) { return false; }
52 * @param obj object to scan
53 * @return an array of painters and their priorities
55 @SuppressWarnings("unchecked")
56 public static EventHandlerDefinition[] getEventHandlers(final Object obj) {
57 List<EventHandlerDefinition> result = new ArrayList<EventHandlerDefinition>();
58 Class<?> clazz = obj.getClass();
60 for (final Method m : clazz.getMethods()) {
61 EventHandler anno = (EventHandler) m.getAnnotation(EventHandler.class);
65 Class<?> returnType = m.getReturnType();
66 if (!returnType.equals(boolean.class))
67 throw new RuntimeException(clazz.getName() + "." + m.getName() + " return type is invalid");
69 @SuppressWarnings("rawtypes")
70 Class[] argTypes = m.getParameterTypes();
71 if (argTypes.length != 1 || !Event.class.isAssignableFrom(argTypes[0]))
72 throw new RuntimeException(clazz.getName() + "." + m.getName() + " invalid arguments");
74 @SuppressWarnings("rawtypes")
75 Class argClass = argTypes[0];
77 @SuppressWarnings("rawtypes")
78 Class[] exceptionTypes = m.getExceptionTypes();
79 if (exceptionTypes.length != 0)
80 throw new RuntimeException(clazz.getName() + "." + m.getName() + " invalid exceptions");
82 int priority = anno.priority();
85 m.setAccessible(true);
86 } catch (Throwable t) {
91 final int eventMask = EventTypes.toTypeMask(argClass);
93 IEventHandler eventHandler = new IEventHandler() {
95 public int getEventMask() {
99 public boolean handleEvent(Event e1) {
101 return (Boolean) m.invoke(obj, e1);
102 } catch (IllegalArgumentException e) {
104 } catch (IllegalAccessException e) {
105 throw new RuntimeException(e);
106 } catch (InvocationTargetException e) {
107 throw new RuntimeException(e.getCause());
111 EventHandlerDefinition handler = new EventHandlerDefinition(obj, eventHandler, priority, argClass);
115 return result.toArray(new EventHandlerDefinition[0]);
118 public final static class EventHandlerDefinition {
119 public final Object obj;
120 public final IEventHandler origEventHandler;
121 public final IEventHandler eventHandler;
122 public final int priority;
123 public final Class<Event> eventSuperClass;
125 public EventHandlerDefinition(Object obj, IEventHandler eventHandler, int priority, Class<Event> eventSuperClass) {
127 this.priority = priority;
128 this.eventSuperClass = eventSuperClass;
129 this.origEventHandler = eventHandler;
130 final int eventMask = EventTypes.toTypeMask(eventSuperClass);
131 if (eventSuperClass.equals(Event.class)) {
132 this.eventHandler = eventHandler;
134 this.eventHandler = new IEventHandler() {
136 public int getEventMask() {
141 public boolean handleEvent(Event e) {
142 // Event masking already taken care of, no need to check eventMask
143 if (EventHandlerDefinition.this.eventSuperClass.isAssignableFrom(e.getClass()))
144 return EventHandlerDefinition.this.origEventHandler.handleEvent(e);
149 public String toString() {
150 return EventHandlerDefinition.this.toString();
157 public String toString() {
158 return String.format("[%11d] %s (%s)", priority, obj.getClass().getSimpleName(),
159 eventSuperClass.getSimpleName());