]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/SGNodeReflection.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / canvas / impl / SGNodeReflection.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 /*
13  *
14  * @author Toni Kalajainen
15  */
16 package org.simantics.g2d.canvas.impl;
17
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;
26
27 import org.simantics.g2d.canvas.SGDesignation;
28 import org.simantics.scenegraph.g2d.G2DParentNode;
29
30
31 public class SGNodeReflection {
32
33     @Retention(RetentionPolicy.RUNTIME)
34     @Target(ElementType.METHOD)
35     public static @interface SGInit {
36         SGDesignation designation() default SGDesignation.CANVAS;
37     }
38
39     @Retention(RetentionPolicy.RUNTIME)
40     @Target(ElementType.METHOD)
41     public static @interface SGCleanup {
42     }
43
44     /**
45      * Scans an object with reflection for all painter methods and returns
46      * an array of ICanvasPainters and priorities.
47      * <p>
48      * The corresponding class of obj must contain methods that meet the following
49      * criteria:
50      *  1) no return value
51      *  2) 1 argument, which is Graphics2D
52      *  3) has annotation Painter
53      *  4) may not throw any Exception
54      *  5) method must be accessible
55      * <p>
56      * Example:
57      *
58      *  @Painter(priority = Integer.MIN_VALUE)
59      *  public void prePaint(GraphicsContext gc) {
60      *  }
61      *
62      * @param obj object to scan
63      * @return an array of painters and their priorities
64      */
65     public static CanvasSGNodeDefinition[] getSGHandlers(final Object obj)
66     {
67         List<CanvasSGNodeDefinition> result = new ArrayList<CanvasSGNodeDefinition>();
68         Class<?> clazz = obj.getClass();
69
70         for (final Method m : clazz.getMethods()) {
71             SGInit initAnno = m.getAnnotation(SGInit.class);
72             if (initAnno==null) continue;
73
74             SGDesignation initDesignation = initAnno.designation();
75
76             Class<?> returnType = m.getReturnType();
77             if (!returnType.equals(void.class))
78                 throw new RuntimeException(clazz.getName()+"."+m.getName()+" return type is invalid");
79
80             @SuppressWarnings("rawtypes")
81             Class[] argTypes = m.getParameterTypes();
82             if (argTypes.length!=1 || !argTypes[0].equals(G2DParentNode.class))
83                 throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid arguments");
84
85             @SuppressWarnings("rawtypes")
86             Class[] exceptionTypes = m.getExceptionTypes();
87             if (exceptionTypes.length!=0)
88                 throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid exceptions");
89
90             try {
91                 m.setAccessible(true);
92             } catch (Throwable t)
93             {
94                 t.printStackTrace();
95                 throw new Error(t);
96             }
97
98             CanvasSGNodeDefinition def = new CanvasSGNodeDefinition(m, initDesignation, null, obj);
99             result.add(def);
100         }
101
102         for (final Method m : clazz.getMethods()) {
103             SGCleanup cleanupAnno = m.getAnnotation(SGCleanup.class);
104             if (cleanupAnno==null) continue;
105
106             Class<?> returnType = m.getReturnType();
107             if (!returnType.equals(void.class))
108                 throw new RuntimeException(clazz.getName()+"."+m.getName()+" return type is invalid");
109
110             @SuppressWarnings("rawtypes")
111             Class[] argTypes = m.getParameterTypes();
112             if (argTypes.length!=0)
113                 throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid arguments");
114
115             @SuppressWarnings("rawtypes")
116             Class[] exceptionTypes = m.getExceptionTypes();
117             if (exceptionTypes.length!=0)
118                 throw new RuntimeException(clazz.getName()+"."+m.getName()+" invalid exceptions");
119
120             try {
121                 m.setAccessible(true);
122             } catch (Throwable t)
123             {
124                 t.printStackTrace();
125                 throw new Error(t);
126             }
127
128             CanvasSGNodeDefinition def = new CanvasSGNodeDefinition(null, null, m, obj);
129             result.add(def);
130         }
131
132         return result.toArray(new CanvasSGNodeDefinition[0]);
133     }
134
135     public static class CanvasSGNodeDefinition { // FIXME: own classes for init and cleanup
136         public final Method initMethod;
137         public final SGDesignation initDesignation;
138         public final Method cleanupMethod;
139         public final Object obj;
140
141         public void init(G2DParentNode parent) {
142             if(initMethod == null) return;
143             try {
144                 initMethod.invoke(obj, parent);
145             } catch (IllegalArgumentException e) {
146                 throw new Error(e);
147             } catch (IllegalAccessException e) {
148                 throw new Error(e);
149             } catch (InvocationTargetException e) {
150                 throw new RuntimeException(e.getCause());
151             }
152         }
153         public void cleanup() {
154             if(cleanupMethod == null) return;
155             try {
156                 cleanupMethod.invoke(obj);
157             } catch (IllegalArgumentException e) {
158                 throw new Error(e);
159             } catch (IllegalAccessException e) {
160                 throw new Error(e);
161             } catch (InvocationTargetException e) {
162                 throw new RuntimeException(e.getCause());
163             }
164         }
165         public CanvasSGNodeDefinition(Method initMethod, SGDesignation initDesignation, Method cleanupMethod, Object obj) {
166             this.initMethod = initMethod;
167             this.initDesignation = initDesignation;
168             this.cleanupMethod = cleanupMethod;
169             this.obj = obj;
170         }
171         @Override
172         public String toString() {
173             return String.format("%s %s %s %s",
174                     obj.getClass().getSimpleName(),
175                     initMethod != null ? initMethod.getName() : "no init method",
176                     initDesignation != null ? initDesignation.toString() : "no init designation",
177                     cleanupMethod != null ? cleanupMethod.getName() : "no cleanup method");
178         }
179     }
180 }