]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/HintReflection.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / canvas / impl / HintReflection.java
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/HintReflection.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/HintReflection.java
new file mode 100644 (file)
index 0000000..3edd342
--- /dev/null
@@ -0,0 +1,185 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.g2d.canvas.impl;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.simantics.utils.datastructures.hints.IHintListener;\r
+import org.simantics.utils.datastructures.hints.IHintObservable;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+\r
+/**\r
+ * @author Toni Kalajainen\r
+ */\r
+public class HintReflection {\r
+\r
+       private final static HintListenerDefinition[] EMPTY = new HintListenerDefinition[0]; \r
+       \r
+       @Retention(RetentionPolicy.RUNTIME)\r
+       @Target(ElementType.METHOD)\r
+       public static @interface HintListener {\r
+               Class<?>        Class();\r
+               String          Field();                \r
+       }\r
+       \r
+       /**\r
+        * Scans an object for reflections of hint listeners  \r
+        * <p>\r
+        * Example:\r
+        * \r
+        *  @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")\r
+        *      public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
+        *     ...\r
+        *      }\r
+        *      @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")\r
+        *      public void hintRemoved(IHintObservable sender, Key key, Object oldValue) { \r
+        *     ...\r
+        *  }\r
+        * \r
+        * @param obj object to scan\r
+        * @return an array of painters and their priorities\r
+        */\r
+    public static HintListenerDefinition[] getDependencies(final Object obj)\r
+       {\r
+               Map<Key, HintListenerDefinition> result = new HashMap<Key, HintListenerDefinition>();\r
+               Class<?> clazz = obj.getClass();\r
+               _add(obj, clazz, result);\r
+               //if (result==null) return EMPTY;\r
+               return result.values().toArray(EMPTY);\r
+       }\r
+\r
+    private static void _add(final Object obj, Class<?> clazz, Map<Key, HintListenerDefinition> result)\r
+       {\r
+               try {\r
+                       for (final Method m : clazz.getDeclaredMethods()) {\r
+                               HintListener anno = (HintListener) m\r
+                                               .getAnnotation(HintListener.class);\r
+                               if (anno == null)\r
+                                       continue;\r
+\r
+                               Class<?> keyContainerClass = anno.Class();\r
+                               assert (keyContainerClass != null);\r
+                               String fieldName = anno.Field();\r
+                               assert (fieldName != null);\r
+                               Field field;\r
+                               field = keyContainerClass.getField(fieldName);\r
+                               assert (field != null);\r
+                               field.setAccessible(true);\r
+                               Object value = field.get(field != null);\r
+                               assert (value != null);\r
+                               assert (value instanceof Key);\r
+                               Key key = (Key) value;\r
+\r
+                               Class<?> returnType = m.getReturnType();\r
+                               assert (returnType == void.class);\r
+                               Class<?>[] params = m.getParameterTypes();\r
+                               assert (params.length == 4 || params.length == 3);\r
+                               assert (params[0].equals(IHintObservable.class));\r
+                               assert (params[1].equals(Key.class));\r
+                               assert (params[2].equals(Object.class));\r
+\r
+                               if (params.length == 4) \r
+                                       assert (params[3].equals(Object.class));\r
+\r
+                               HintListenerDefinition def = result.get(key);\r
+                               if (def==null) {\r
+                                       def = new HintListenerDefinition(key, obj);\r
+                                       result.put(key, def);\r
+                               }                                       \r
+                               \r
+                               m.setAccessible(true);                                  \r
+                               if (params.length == 4)\r
+                                       def.changedHandlerMethod = m;\r
+                               else\r
+                                       def.removedHandlerMethod = m;\r
+                       }\r
+               } catch (SecurityException e) {\r
+                       throw new Error(e);\r
+               } catch (NoSuchFieldException e) {\r
+                       throw new Error(e);\r
+               } catch (IllegalAccessException e) {\r
+                       throw new Error(e);\r
+               }\r
+               /*\r
+               for (final Field f : clazz.getDeclaredFields()) {\r
+                       Class c = f.getType();\r
+                       Dependency dep = (Dependency) f.getAnnotation(Dependency.class);\r
+                       Reference ref = (Reference) f.getAnnotation(Reference.class);\r
+                       if (dep==null && ref==null) continue;\r
+                       assert(ICanvasParticipant.class.isAssignableFrom( c ));                         \r
+                       assert(!(dep!=null && ref!=null));\r
+                       ReferenceDefinition rd = new ReferenceDefinition();\r
+                       rd.dependency = dep!=null;\r
+                       rd.field = f;\r
+                       rd.requirement = c;\r
+                       f.setAccessible(true);\r
+                       result.add(rd);\r
+               }\r
+               */\r
+               \r
+               Class<?> superClass = clazz.getSuperclass();\r
+               if (superClass!=null)\r
+                       _add(obj, superClass, result);\r
+       }\r
+\r
+       \r
+       public final static class HintListenerDefinition implements IHintListener {\r
+               public final Key key;\r
+               public final Object object;\r
+               public Method changedHandlerMethod;\r
+               public Method removedHandlerMethod;\r
+               \r
+               public HintListenerDefinition(Key key, Object object) {\r
+                       this.key = key;\r
+                       this.object = object;\r
+               }\r
+               \r
+               @Override\r
+               public void hintChanged(IHintObservable sender, Key key,\r
+                               Object oldValue, Object newValue) {\r
+                       if (changedHandlerMethod==null) return;\r
+                       try {\r
+                               changedHandlerMethod.invoke(object, sender, key, oldValue, newValue);\r
+                       } catch (IllegalArgumentException e) {\r
+                               throw new Error(e);\r
+                       } catch (IllegalAccessException e) {\r
+                               throw new Error(e);\r
+                       } catch (InvocationTargetException e) {\r
+                               throw new RuntimeException(e);\r
+                       }\r
+               }\r
+               @Override\r
+               public void hintRemoved(IHintObservable sender, Key key, Object oldValue) {\r
+                       if (removedHandlerMethod==null) return;\r
+                       try {\r
+                               removedHandlerMethod.invoke(object, sender, key, oldValue);\r
+                       } catch (IllegalArgumentException e) {\r
+                               throw new Error(e);\r
+                       } catch (IllegalAccessException e) {\r
+                               throw new Error(e);\r
+                       } catch (InvocationTargetException e) {\r
+                               throw new RuntimeException(e.getCause());\r
+                       }\r
+               }\r
+               \r
+               \r
+       }       \r
+       \r
+}\r