(refs #7326) Better handling of exceptions in Java->SCL interface
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / utils / ValueFromMethod.java
1 package org.simantics.scl.compiler.internal.codegen.utils;
2
3 import java.lang.reflect.InvocationTargetException;
4 import java.lang.reflect.Method;
5
6 import org.simantics.scl.runtime.function.FunctionImpl1;
7 import org.simantics.scl.runtime.function.FunctionImpl2;
8 import org.simantics.scl.runtime.function.FunctionImpl3;
9 import org.simantics.scl.runtime.function.FunctionImpl4;
10 import org.simantics.scl.runtime.function.FunctionImplN;
11 import org.simantics.scl.runtime.tuple.Tuple0;
12
13 public class ValueFromMethod {
14
15     private static final class Arity1Func extends FunctionImpl1<Object, Object> {
16         private final Method method;
17         private final boolean returnsVoid;
18
19         private Arity1Func(Method method, boolean returnsVoid) {
20             this.method = method;
21             this.returnsVoid = returnsVoid;
22         }
23
24         @Override
25         public Object apply(Object p0) {
26             try {
27                 Object ret = method.invoke(null, p0);
28                 return returnsVoid ? Tuple0.INSTANCE : ret;
29             } catch (ReflectiveOperationException e) {
30                 if (e instanceof InvocationTargetException) {
31                     Throwable cause = e.getCause();
32                     if(cause instanceof RuntimeException)
33                         throw (RuntimeException)cause;
34                     else
35                         throw new RuntimeException(cause);
36                 }
37                 throw new RuntimeException(e);
38             }
39         }
40
41         @Override
42         public int hashCode() {
43             return method == null ? 0 : method.hashCode();
44         }
45
46         @Override
47         public boolean equals(Object obj) {
48             if (this == obj)
49                 return true;
50             if (obj == null)
51                 return false;
52             if (getClass() != obj.getClass())
53                 return false;
54             Arity1Func other = (Arity1Func) obj;
55             return method.equals(other.method);
56         }
57     }
58
59     private static final class Arity2Func extends FunctionImpl2<Object, Object, Object> {
60         private final Method method;
61         private final boolean returnsVoid;
62
63         private Arity2Func(Method method, boolean returnsVoid) {
64             this.method = method;
65             this.returnsVoid = returnsVoid;
66         }
67
68         @Override
69         public Object apply(Object p0, Object p1) {
70             try {
71                 Object ret = method.invoke(null, p0, p1);
72                 return returnsVoid ? Tuple0.INSTANCE : ret;
73             } catch (ReflectiveOperationException e) {
74                 if (e instanceof InvocationTargetException) {
75                     Throwable cause = e.getCause();
76                     if(cause instanceof RuntimeException)
77                         throw (RuntimeException)cause;
78                     else
79                         throw new RuntimeException(cause);
80                 }
81                 throw new RuntimeException(e);
82             }
83         }
84         
85         @Override
86         public int hashCode() {
87             return method == null ? 0 : method.hashCode();
88         }
89
90         @Override
91         public boolean equals(Object obj) {
92             if (this == obj)
93                 return true;
94             if (obj == null)
95                 return false;
96             if (getClass() != obj.getClass())
97                 return false;
98             Arity2Func other = (Arity2Func) obj;
99             return method.equals(other.method);
100         }
101     }
102
103     private static final class Arity3Func extends FunctionImpl3<Object, Object, Object, Object> {
104         private final Method method;
105         private final boolean returnsVoid;
106
107         private Arity3Func(Method method, boolean returnsVoid) {
108             this.method = method;
109             this.returnsVoid = returnsVoid;
110         }
111
112         @Override
113         public Object apply(Object p0, Object p1, Object p2) {
114             try {
115                 Object ret = method.invoke(null, p0, p1, p2);
116                 return returnsVoid ? Tuple0.INSTANCE : ret;
117             } catch (ReflectiveOperationException e) {
118                 if (e instanceof InvocationTargetException) {
119                     Throwable cause = e.getCause();
120                     if(cause instanceof RuntimeException)
121                         throw (RuntimeException)cause;
122                     else
123                         throw new RuntimeException(cause);
124                 }
125                 throw new RuntimeException(e);
126             }
127         }
128         
129         @Override
130         public int hashCode() {
131             return method == null ? 0 : method.hashCode();
132         }
133
134         @Override
135         public boolean equals(Object obj) {
136             if (this == obj)
137                 return true;
138             if (obj == null)
139                 return false;
140             if (getClass() != obj.getClass())
141                 return false;
142             Arity3Func other = (Arity3Func) obj;
143             return method.equals(other.method);
144         }
145     }
146
147     private static final class Arity4Func extends FunctionImpl4<Object, Object, Object, Object, Object> {
148         private final Method method;
149         private final boolean returnsVoid;
150
151         private Arity4Func(Method method, boolean returnsVoid) {
152             this.method = method;
153             this.returnsVoid = returnsVoid;
154         }
155
156         @Override
157         public Object apply(Object p0, Object p1, Object p2, Object p3) {
158             try {
159                 Object ret = method.invoke(null, p0, p1, p2, p3);
160                 return returnsVoid ? Tuple0.INSTANCE : ret;
161             } catch (ReflectiveOperationException e) {
162                 if (e instanceof InvocationTargetException) {
163                     Throwable cause = e.getCause();
164                     if(cause instanceof RuntimeException)
165                         throw (RuntimeException)cause;
166                     else
167                         throw new RuntimeException(cause);
168                 }
169                 throw new RuntimeException(e);
170             }
171         }
172         
173         @Override
174         public int hashCode() {
175             return method == null ? 0 : method.hashCode();
176         }
177
178         @Override
179         public boolean equals(Object obj) {
180             if (this == obj)
181                 return true;
182             if (obj == null)
183                 return false;
184             if (getClass() != obj.getClass())
185                 return false;
186             Arity4Func other = (Arity4Func) obj;
187             return method.equals(other.method);
188         }
189     }
190
191     private static final class ArityNFunc extends FunctionImplN {
192         private final Method method;
193         private final boolean returnsVoid;
194
195         private ArityNFunc(int arity, Method method, boolean returnsVoid) {
196             super(arity);
197             this.method = method;
198             this.returnsVoid = returnsVoid;
199         }
200
201         @Override
202         public Object doApply(Object... ps) {
203             try {
204                 Object ret =  method.invoke(null, ps);
205                 return returnsVoid ? Tuple0.INSTANCE : ret;
206             } catch (ReflectiveOperationException e) {
207                 if (e instanceof InvocationTargetException) {
208                     Throwable cause = e.getCause();
209                     if(cause instanceof RuntimeException)
210                         throw (RuntimeException)cause;
211                     else
212                         throw new RuntimeException(cause);
213                 }
214                 throw new RuntimeException(e);
215             }
216         }
217         
218         @Override
219         public int hashCode() {
220             return method == null ? 0 : method.hashCode();
221         }
222
223         @Override
224         public boolean equals(Object obj) {
225             if (this == obj)
226                 return true;
227             if (obj == null)
228                 return false;
229             if (getClass() != obj.getClass())
230                 return false;
231             ArityNFunc other = (ArityNFunc) obj;
232             return method.equals(other.method);
233         }
234     }
235
236     public static Object getValueFromStaticMethod(final Method method) throws ReflectiveOperationException {
237         int arity = method.getParameterTypes().length;
238         final boolean returnsVoid = method.getReturnType().equals(void.class);
239         switch(arity) {
240         case 0: {
241             Object ret = method.invoke(null);
242             return returnsVoid ? Tuple0.INSTANCE : ret;
243         }
244         case 1:
245             return new Arity1Func(method, returnsVoid);
246         case 2:
247             return new Arity2Func(method, returnsVoid);
248         case 3:
249             return new Arity3Func(method, returnsVoid);
250         case 4:
251             return new Arity4Func(method, returnsVoid);
252         default:
253             return new ArityNFunc(arity, method, returnsVoid);
254         }
255     }
256     
257 }