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 *******************************************************************************/
12 package org.simantics.g2d.canvas.impl;
14 import java.lang.annotation.ElementType;
15 import java.lang.annotation.Retention;
16 import java.lang.annotation.RetentionPolicy;
17 import java.lang.annotation.Target;
18 import java.lang.reflect.Field;
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21 import java.util.HashMap;
24 import org.simantics.utils.datastructures.hints.IHintListener;
25 import org.simantics.utils.datastructures.hints.IHintObservable;
26 import org.simantics.utils.datastructures.hints.IHintContext.Key;
29 * @author Toni Kalajainen
31 public class HintReflection {
33 private final static HintListenerDefinition[] EMPTY = new HintListenerDefinition[0];
35 @Retention(RetentionPolicy.RUNTIME)
36 @Target(ElementType.METHOD)
37 public static @interface HintListener {
43 * Scans an object for reflections of hint listeners
47 * @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")
48 * public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
51 * @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")
52 * public void hintRemoved(IHintObservable sender, Key key, Object oldValue) {
56 * @param obj object to scan
57 * @return an array of painters and their priorities
59 public static HintListenerDefinition[] getDependencies(final Object obj)
61 Map<Key, HintListenerDefinition> result = new HashMap<Key, HintListenerDefinition>();
62 Class<?> clazz = obj.getClass();
63 _add(obj, clazz, result);
64 //if (result==null) return EMPTY;
65 return result.values().toArray(EMPTY);
68 private static void _add(final Object obj, Class<?> clazz, Map<Key, HintListenerDefinition> result)
71 for (final Method m : clazz.getDeclaredMethods()) {
72 HintListener anno = (HintListener) m
73 .getAnnotation(HintListener.class);
77 Class<?> keyContainerClass = anno.Class();
78 assert (keyContainerClass != null);
79 String fieldName = anno.Field();
80 assert (fieldName != null);
82 field = keyContainerClass.getField(fieldName);
83 assert (field != null);
84 field.setAccessible(true);
85 Object value = field.get(field != null);
86 assert (value != null);
87 assert (value instanceof Key);
88 Key key = (Key) value;
90 Class<?> returnType = m.getReturnType();
91 assert (returnType == void.class);
92 Class<?>[] params = m.getParameterTypes();
93 assert (params.length == 4 || params.length == 3);
94 assert (params[0].equals(IHintObservable.class));
95 assert (params[1].equals(Key.class));
96 assert (params[2].equals(Object.class));
98 if (params.length == 4)
99 assert (params[3].equals(Object.class));
101 HintListenerDefinition def = result.get(key);
103 def = new HintListenerDefinition(key, obj);
104 result.put(key, def);
107 m.setAccessible(true);
108 if (params.length == 4)
109 def.changedHandlerMethod = m;
111 def.removedHandlerMethod = m;
113 } catch (SecurityException e) {
115 } catch (NoSuchFieldException e) {
117 } catch (IllegalAccessException e) {
121 for (final Field f : clazz.getDeclaredFields()) {
122 Class c = f.getType();
123 Dependency dep = (Dependency) f.getAnnotation(Dependency.class);
124 Reference ref = (Reference) f.getAnnotation(Reference.class);
125 if (dep==null && ref==null) continue;
126 assert(ICanvasParticipant.class.isAssignableFrom( c ));
127 assert(!(dep!=null && ref!=null));
128 ReferenceDefinition rd = new ReferenceDefinition();
129 rd.dependency = dep!=null;
132 f.setAccessible(true);
137 Class<?> superClass = clazz.getSuperclass();
138 if (superClass!=null)
139 _add(obj, superClass, result);
143 public final static class HintListenerDefinition implements IHintListener {
144 public final Key key;
145 public final Object object;
146 public Method changedHandlerMethod;
147 public Method removedHandlerMethod;
149 public HintListenerDefinition(Key key, Object object) {
151 this.object = object;
155 public void hintChanged(IHintObservable sender, Key key,
156 Object oldValue, Object newValue) {
157 if (changedHandlerMethod==null) return;
159 changedHandlerMethod.invoke(object, sender, key, oldValue, newValue);
160 } catch (IllegalArgumentException e) {
162 } catch (IllegalAccessException e) {
164 } catch (InvocationTargetException e) {
165 throw new RuntimeException(e.getCause());
169 public void hintRemoved(IHintObservable sender, Key key, Object oldValue) {
170 if (removedHandlerMethod==null) return;
172 removedHandlerMethod.invoke(object, sender, key, oldValue);
173 } catch (IllegalArgumentException e) {
175 } catch (IllegalAccessException e) {
177 } catch (InvocationTargetException e) {
178 throw new RuntimeException(e.getCause());