]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/HintReflection.java
Automatically import also SCLMain modules of dependent index roots
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / canvas / impl / HintReflection.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g2d.canvas.impl;
13
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;
22 import java.util.Map;
23
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;
27
28 /**
29  * @author Toni Kalajainen
30  */
31 public class HintReflection {
32
33         private final static HintListenerDefinition[] EMPTY = new HintListenerDefinition[0]; 
34         
35         @Retention(RetentionPolicy.RUNTIME)
36         @Target(ElementType.METHOD)
37         public static @interface HintListener {
38                 Class<?>        Class();
39                 String          Field();                
40         }
41         
42         /**
43          * Scans an object for reflections of hint listeners  
44          * <p>
45          * Example:
46          * 
47          *  @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")
48          *      public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
49          *     ...
50          *      }
51          *      @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")
52          *      public void hintRemoved(IHintObservable sender, Key key, Object oldValue) { 
53          *     ...
54          *  }
55          * 
56          * @param obj object to scan
57          * @return an array of painters and their priorities
58          */
59     public static HintListenerDefinition[] getDependencies(final Object obj)
60         {
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);
66         }
67
68     private static void _add(final Object obj, Class<?> clazz, Map<Key, HintListenerDefinition> result)
69         {
70                 try {
71                         for (final Method m : clazz.getDeclaredMethods()) {
72                                 HintListener anno = (HintListener) m
73                                                 .getAnnotation(HintListener.class);
74                                 if (anno == null)
75                                         continue;
76
77                                 Class<?> keyContainerClass = anno.Class();
78                                 assert (keyContainerClass != null);
79                                 String fieldName = anno.Field();
80                                 assert (fieldName != null);
81                                 Field field;
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;
89
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));
97
98                                 if (params.length == 4) 
99                                         assert (params[3].equals(Object.class));
100
101                                 HintListenerDefinition def = result.get(key);
102                                 if (def==null) {
103                                         def = new HintListenerDefinition(key, obj);
104                                         result.put(key, def);
105                                 }                                       
106                                 
107                                 m.setAccessible(true);                                  
108                                 if (params.length == 4)
109                                         def.changedHandlerMethod = m;
110                                 else
111                                         def.removedHandlerMethod = m;
112                         }
113                 } catch (SecurityException e) {
114                         throw new Error(e);
115                 } catch (NoSuchFieldException e) {
116                         throw new Error(e);
117                 } catch (IllegalAccessException e) {
118                         throw new Error(e);
119                 }
120                 /*
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;
130                         rd.field = f;
131                         rd.requirement = c;
132                         f.setAccessible(true);
133                         result.add(rd);
134                 }
135                 */
136                 
137                 Class<?> superClass = clazz.getSuperclass();
138                 if (superClass!=null)
139                         _add(obj, superClass, result);
140         }
141
142         
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;
148                 
149                 public HintListenerDefinition(Key key, Object object) {
150                         this.key = key;
151                         this.object = object;
152                 }
153                 
154                 @Override
155                 public void hintChanged(IHintObservable sender, Key key,
156                                 Object oldValue, Object newValue) {
157                         if (changedHandlerMethod==null) return;
158                         try {
159                                 changedHandlerMethod.invoke(object, sender, key, oldValue, newValue);
160                         } catch (IllegalArgumentException e) {
161                                 throw new Error(e);
162                         } catch (IllegalAccessException e) {
163                                 throw new Error(e);
164                         } catch (InvocationTargetException e) {
165                                 throw new RuntimeException(e.getCause());
166                         }
167                 }
168                 @Override
169                 public void hintRemoved(IHintObservable sender, Key key, Object oldValue) {
170                         if (removedHandlerMethod==null) return;
171                         try {
172                                 removedHandlerMethod.invoke(object, sender, key, oldValue);
173                         } catch (IllegalArgumentException e) {
174                                 throw new Error(e);
175                         } catch (IllegalAccessException e) {
176                                 throw new Error(e);
177                         } catch (InvocationTargetException e) {
178                                 throw new RuntimeException(e.getCause());
179                         }
180                 }
181                 
182                 
183         }       
184         
185 }