]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/AsmBindingClassLoader.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / reflection / AsmBindingClassLoader.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.databoard.binding.reflection;\r
13 \r
14 import java.lang.reflect.Field;\r
15 import java.lang.reflect.Method;\r
16 import java.lang.reflect.Modifier;\r
17 import java.util.HashMap;\r
18 import java.util.Map;\r
19 \r
20 import org.objectweb.asm.AnnotationVisitor;\r
21 import org.objectweb.asm.ClassVisitor;\r
22 import org.objectweb.asm.ClassWriter;\r
23 import org.objectweb.asm.FieldVisitor;\r
24 import org.objectweb.asm.Label;\r
25 import org.objectweb.asm.MethodVisitor;\r
26 import org.objectweb.asm.Opcodes;\r
27 import org.objectweb.asm.Type;\r
28 import org.simantics.databoard.binding.error.BindingConstructionException;\r
29 \r
30 public class AsmBindingClassLoader extends ClassLoader implements Opcodes {\r
31 \r
32         Map<String, Class<?>> map = new HashMap<String, Class<?>>();\r
33         \r
34         public AsmBindingClassLoader() {\r
35                 super(Thread.currentThread().getContextClassLoader());\r
36         }\r
37 \r
38         public AsmBindingClassLoader(ClassLoader parent) {\r
39                 super(parent);\r
40         }       \r
41         \r
42         public String toBindingClassName( String targetClassName )\r
43         {\r
44                 if ( targetClassName.startsWith("java" ) ) {\r
45                         return "x"+targetClassName+".Binding";\r
46                 }\r
47                 return targetClassName+".Binding";\r
48         }\r
49         \r
50         public String toTargetClassName( String bindingClassName )\r
51         {\r
52                 if (!bindingClassName.endsWith(".Binding")) return null;\r
53                 if (bindingClassName.substring(1,5).equals("java")) {\r
54                         return bindingClassName.substring(1, bindingClassName.length()-8);\r
55                 } else {\r
56                         return bindingClassName.substring(0, bindingClassName.length()-8);\r
57                 }\r
58         }\r
59         \r
60         @Override\r
61         protected synchronized Class<?> findClass(String bindingClassName) \r
62         throws ClassNotFoundException \r
63         {\r
64                 Class<?> c = map.get(bindingClassName);\r
65                 if ( c!= null) return c;\r
66                                 \r
67                 try {\r
68                         String targetClassName = toTargetClassName(bindingClassName);\r
69                         if ( targetClassName == null ) {\r
70 //                              try {\r
71                                         return super.findClass(bindingClassName);\r
72 //                              } catch( ClassNotFoundException e ) {\r
73 //                                      e.printStackTrace();\r
74 //                                      throw e;\r
75 //                              }\r
76                         }\r
77                         \r
78                         ClassLoader cl = getParent();\r
79                         if (cl==null) { \r
80                                 cl = Thread.currentThread().getContextClassLoader();\r
81                         }\r
82                         Class<?> targetClass = cl.loadClass( targetClassName );\r
83                         ClassInfo ci = ClassInfo.getInfo( targetClass );\r
84                         byte[] data = createBindingClass( ci, bindingClassName );\r
85                         Class<?> bindingClass = defineClass( bindingClassName, data, 0, data.length );\r
86                         map.put(bindingClassName, bindingClass);\r
87                         return bindingClass;\r
88                 } catch (BindingConstructionException e) {\r
89                         throw new ClassNotFoundException( e.getMessage(), e.getCause() );\r
90                 }               \r
91         }       \r
92         \r
93         public synchronized Class<?> getBindingClass(Class<?> targetClass)\r
94         throws ClassNotFoundException\r
95         {\r
96                 String targetClassName = targetClass.getName();\r
97                 String bindingClassName = toBindingClassName(targetClassName);\r
98                 Class<?> c = map.get(bindingClassName);\r
99                 if ( c!= null) return c;\r
100                                 \r
101                 try {\r
102                         ClassInfo ci = ClassInfo.getInfo( targetClass );\r
103                         byte[] data = createBindingClass( ci, bindingClassName );\r
104                         Class<?> bindingClass = defineClass( bindingClassName, data, 0, data.length );\r
105                         map.put(bindingClassName, bindingClass);\r
106                         return bindingClass;\r
107                 } catch (BindingConstructionException e) {\r
108                         throw new ClassNotFoundException( e.getMessage(), e.getCause() );\r
109                 }               \r
110                 \r
111         }\r
112 \r
113         public byte[] createBindingClass(ClassInfo ci, String bindingClassName)\r
114         {\r
115                 //System.out.println("BindingFactory: "+bindingClassName+" (for "+ci.clazz.getClassLoader()+")");\r
116                 int count = ci.fields.length;\r
117                 ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS );\r
118                 ClassVisitor cv = cw;//new CheckClassAdapter(cw);\r
119                 \r
120                 FieldVisitor fv;\r
121                 MethodVisitor mv;\r
122                 AnnotationVisitor av0;          \r
123         \r
124                 String className = ci.clazz.getName().replaceAll("\\.", "/");           \r
125                 bindingClassName = bindingClassName.replaceAll("\\.", "/");\r
126                 Object[] classNameX = new Object[] {className};\r
127                 String signature = "L"+bindingClassName+";";\r
128                 \r
129                 // Constructor\r
130                 String superClass = "org/simantics/databoard/binding/reflection/ClassBinding";\r
131                 cv.visit(V1_6, ACC_PUBLIC + ACC_SUPER, bindingClassName, null, superClass, null);       \r
132 \r
133                 // Constructor\r
134                 {\r
135                         mv = cv.visitMethod(ACC_PUBLIC, "<init>", "(Lorg/simantics/databoard/type/RecordType;)V", null, new String[] { "org/simantics/databoard/binding/error/BindingConstructionException" });\r
136                         \r
137                         mv.visitCode();\r
138                         Label l0 = new Label();                 \r
139                         mv.visitLabel(l0);\r
140                         mv.visitVarInsn(ALOAD, 0);\r
141                         mv.visitLdcInsn(Type.getType("L"+className+";"));                       \r
142                         mv.visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "(Ljava/lang/Class;)V");\r
143                         \r
144                         Label l1 = new Label();\r
145                         mv.visitLabel(l1);\r
146                         mv.visitVarInsn(ALOAD, 0);\r
147                         mv.visitVarInsn(ALOAD, 1);\r
148                         mv.visitFieldInsn(PUTFIELD, bindingClassName, "type", "Lorg/simantics/databoard/type/Datatype;");\r
149 \r
150                         Label l2 = new Label();\r
151                         mv.visitLabel(l2);\r
152                         mv.visitInsn(RETURN);\r
153 \r
154                         Label l3 = new Label();\r
155                         mv.visitLabel(l3);\r
156                         mv.visitLocalVariable("this", signature, null, l0, l3, 0);\r
157                         mv.visitLocalVariable("type", "Lorg/simantics/databoard/type/RecordType;", null, l0, l3, 1);\r
158                         mv.visitMaxs(2, 2);\r
159                         mv.visitEnd();\r
160                 }\r
161                 \r
162                 // getComponent\r
163                 {\r
164                         mv = cv.visitMethod(ACC_PUBLIC, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
165                         mv.visitCode();\r
166                         Label l0 = new Label();\r
167                         mv.visitLabel(l0);\r
168                         mv.visitVarInsn(ALOAD, 1);\r
169                         mv.visitTypeInsn(CHECKCAST, className);\r
170                         mv.visitVarInsn(ASTORE, 3);\r
171                         Label l1 = new Label();\r
172                         mv.visitLabel(l1);\r
173 \r
174                         Label caseLabels[] = createFieldLabels( ci );\r
175                         Label elseLabel = new Label();\r
176                         \r
177                         if ( count > 0 ) {\r
178                                 // Switch\r
179                                 mv.visitVarInsn(ILOAD, 2);\r
180                                 mv.visitTableSwitchInsn(0, count-1, elseLabel, caseLabels);\r
181                                 \r
182                                 // case i: x.field = value[i]\r
183                                 for (int i=0; i<count; i++) {\r
184                                         Label label = caseLabels[i];\r
185                                         Field field = ci.fields[i];\r
186                                         String fieldName = field.getName();\r
187                                         Class<?> fieldClass = ci.fields[i].getType();\r
188                                         String typeDescriptor = toTypeDescriptor( fieldClass );\r
189         \r
190                                         Method getter = ci.getters[i];\r
191                                         boolean useGetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && getter!=null;\r
192                                         \r
193                                         mv.visitLabel( label );\r
194                                         if ( i==0 ) {\r
195                                                 mv.visitFrame(Opcodes.F_APPEND,1, classNameX, 0, null);\r
196                                         } else {\r
197                                                 mv.visitFrame(Opcodes.F_SAME,0, null, 0, null);\r
198                                         }\r
199                                         \r
200                                         // Read instance argument\r
201                                         mv.visitVarInsn(ALOAD, 3);\r
202                                                 \r
203                                         if ( useGetter ) {\r
204                                                 // call getField\r
205                                                 mv.visitMethodInsn(INVOKEVIRTUAL, className, getter.getName(), "()"+typeDescriptor);\r
206                                         } else {\r
207                                                 // Read field\r
208                                                 mv.visitFieldInsn(GETFIELD, className, fieldName, typeDescriptor);\r
209                                         }\r
210                                                 \r
211                                         // Box \r
212                                         box(mv, fieldClass);\r
213                                                 \r
214                                         mv.visitInsn(ARETURN);\r
215                                 }\r
216         \r
217                         }\r
218                         \r
219                         mv.visitLabel(elseLabel);\r
220                         if (count>0) {\r
221                                 mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
222                         }                       \r
223                         mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
224                         mv.visitInsn(DUP);\r
225                         mv.visitLdcInsn("Illegal field index");\r
226                         mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
227                         mv.visitInsn(ATHROW);                   \r
228                         \r
229                         // End \r
230                         Label l19 = new Label();\r
231                         mv.visitLabel(l19);\r
232                         mv.visitLocalVariable("this", "L"+className+";", null, l0, l19, 0);\r
233                         mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l19, 1);\r
234                         mv.visitLocalVariable("index", "I", null, l0, l19, 2);\r
235                         //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, l1, l19, 3);\r
236                         mv.visitMaxs(3, 4);\r
237                         mv.visitEnd();\r
238                 }\r
239                 \r
240                 // Create\r
241                 {\r
242                         mv = cv.visitMethod(ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
243                         if ( ci.beanConstructor != null ) {\r
244                                 mv.visitCode();\r
245                                 Label l0 = new Label();\r
246                                 mv.visitLabel(l0);\r
247                                 mv.visitTypeInsn(NEW, className);\r
248                                 mv.visitInsn(DUP);\r
249                                 mv.visitVarInsn(ALOAD, 0);\r
250                                 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");\r
251                                 mv.visitVarInsn(ASTORE, 2);\r
252                                 Label l1 = new Label();\r
253                                 mv.visitLabel(l1);\r
254                                 mv.visitVarInsn(ALOAD, 0);\r
255                                 mv.visitVarInsn(ALOAD, 2);\r
256                                 mv.visitVarInsn(ALOAD, 1);\r
257                                 mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents", "(Ljava/lang/Object;[Ljava/lang/Object;)V");\r
258                                 Label l2 = new Label();\r
259                                 mv.visitLabel(l2);\r
260                                 mv.visitVarInsn(ALOAD, 2);\r
261                                 mv.visitInsn(ARETURN);\r
262                                 Label l3 = new Label();\r
263                                 mv.visitLabel(l3);\r
264                                 mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l3, 0);\r
265                                 mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);\r
266                                 //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);\r
267                                 mv.visitMaxs(3, 3);\r
268                                 mv.visitEnd();                          \r
269                         } else if ( ci.argsConstructor != null ) {\r
270                                 mv.visitCode();\r
271                                 Label l0 = new Label();\r
272                                 mv.visitLabel(l0);\r
273                                 mv.visitTypeInsn(NEW, className);\r
274                                 mv.visitInsn(DUP);\r
275                                 \r
276                                 String constArgsDescriptor = "(";\r
277                                 Class<?>[] args = ci.argsConstructor.getParameterTypes();\r
278                                 for (int i=0; i<count; i++) {\r
279                                         Label label = new Label();\r
280                                         Class<?> field = args[i];\r
281                                         String fieldName = field.getName();\r
282                                         Method getter = ci.getters[i];\r
283                                         Class<?> fieldClass = ci.fields[i].getType();\r
284                                         Class<?> boxClass = getBoxClass(fieldClass);\r
285                                         String typeDescriptor = toTypeDescriptor( fieldClass );\r
286                                         String boxTypeDescriptor = toTypeDescriptor( boxClass );\r
287                                         constArgsDescriptor += typeDescriptor;\r
288                                         \r
289                                         mv.visitLabel(label);\r
290                                         mv.visitVarInsn(ALOAD, 1);\r
291                                         if (i<6) {\r
292                                                 mv.visitInsn(ICONST_0 + i);\r
293                                         } else {\r
294                                                 mv.visitIntInsn(BIPUSH, i);                                             \r
295                                         }\r
296 \r
297                                         mv.visitInsn(AALOAD);\r
298                                         mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));\r
299                                         unbox(mv, fieldClass);                                  \r
300                                 }\r
301 \r
302                                 Label l17 = new Label();\r
303                                 mv.visitLabel(l17);\r
304                                 constArgsDescriptor += ")V";\r
305                                 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", constArgsDescriptor);\r
306                                 mv.visitInsn(ARETURN);\r
307                                 Label l18 = new Label();\r
308                                 mv.visitLabel(l18);\r
309                                 mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l18, 0);\r
310                                 mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l18, 1);\r
311                                 mv.visitMaxs(21, 2);\r
312                                 mv.visitEnd();\r
313                                 \r
314                         } else {\r
315                                 mv.visitCode();\r
316                                 Label l0 = new Label();\r
317                                 mv.visitLabel(l0);\r
318                                 mv.visitTypeInsn(NEW, className);\r
319                                 mv.visitInsn(DUP);\r
320                                 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");\r
321                                 mv.visitVarInsn(ASTORE, 2);\r
322                                 Label l1 = new Label();\r
323                                 mv.visitLabel(l1);\r
324                                 mv.visitVarInsn(ALOAD, 0);\r
325                                 mv.visitVarInsn(ALOAD, 2);\r
326                                 mv.visitVarInsn(ALOAD, 1);\r
327                                 mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents", "(Ljava/lang/Object;[Ljava/lang/Object;)V");\r
328                                 Label l2 = new Label();\r
329                                 mv.visitLabel(l2);\r
330                                 mv.visitVarInsn(ALOAD, 2);\r
331                                 mv.visitInsn(ARETURN);\r
332                                 Label l3 = new Label();\r
333                                 mv.visitLabel(l3);\r
334                                 mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l3, 0);\r
335                                 mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);\r
336                                 //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);\r
337                                 mv.visitMaxs(3, 3);\r
338                                 mv.visitEnd();                          \r
339                         }\r
340                 }\r
341                 \r
342                 // CreatePartial\r
343                 mv = cv.visitMethod(ACC_PUBLIC, "createPartial", "()Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
344                 if (ci.beanConstructor!=null)\r
345                 { \r
346                         mv.visitCode();\r
347                         Label l0 = new Label();\r
348                         mv.visitLabel(l0);\r
349                         mv.visitTypeInsn(NEW, className);\r
350                         mv.visitInsn(DUP);\r
351                         mv.visitVarInsn(ALOAD, 0);\r
352                         mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");\r
353                         mv.visitInsn(ARETURN);\r
354                         Label l1 = new Label();\r
355                         mv.visitLabel(l1);\r
356                         mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l1, 0);\r
357                         mv.visitMaxs(3, 1);\r
358                         mv.visitEnd();                  \r
359                 } else if (ci.noArgsConstructor != null)\r
360                 {\r
361                         // return new MyClass();\r
362                         mv.visitCode();\r
363                         Label l0 = new Label();\r
364                         mv.visitLabel(l0);\r
365                         mv.visitTypeInsn(NEW, className);\r
366                         mv.visitInsn(DUP);\r
367                         mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");\r
368                         mv.visitInsn(ARETURN);\r
369                         Label l1 = new Label();\r
370                         mv.visitLabel(l1);\r
371                         mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l1, 0);\r
372                         mv.visitMaxs(2, 1);\r
373                         mv.visitEnd();                  \r
374                 } else {\r
375                         mv.visitCode();\r
376                         Label l0 = new Label();\r
377                         mv.visitLabel(l0);\r
378                         mv.visitIntInsn(BIPUSH, count);\r
379                         mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");\r
380                         mv.visitVarInsn(ASTORE, 1);\r
381                         Label l1 = new Label();\r
382                         mv.visitLabel(l1);\r
383                         mv.visitInsn(ICONST_0);\r
384                         mv.visitVarInsn(ISTORE, 2);\r
385                         Label l2 = new Label();\r
386                         mv.visitLabel(l2);\r
387                         Label l3 = new Label();\r
388                         mv.visitJumpInsn(GOTO, l3);\r
389                         Label l4 = new Label();\r
390                         mv.visitLabel(l4);\r
391                         mv.visitFrame(Opcodes.F_APPEND,2, new Object[] {"[Ljava/lang/Object;", Opcodes.INTEGER}, 0, null);\r
392                         mv.visitVarInsn(ALOAD, 0);\r
393                         mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");\r
394                         mv.visitVarInsn(ILOAD, 2);\r
395                         mv.visitInsn(AALOAD);\r
396                         mv.visitVarInsn(ASTORE, 3);\r
397                         Label l5 = new Label();\r
398                         mv.visitLabel(l5);\r
399                         mv.visitVarInsn(ALOAD, 1);\r
400                         mv.visitVarInsn(ILOAD, 2);\r
401                         mv.visitVarInsn(ALOAD, 3);\r
402                         mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/Binding", "createDefault", "()Ljava/lang/Object;");\r
403                         mv.visitInsn(AASTORE);\r
404                         Label l6 = new Label();\r
405                         mv.visitLabel(l6);\r
406                         mv.visitIincInsn(2, 1);\r
407                         mv.visitLabel(l3);\r
408                         mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
409                         mv.visitVarInsn(ILOAD, 2);\r
410                         mv.visitVarInsn(ALOAD, 1);\r
411                         mv.visitInsn(ARRAYLENGTH);\r
412                         mv.visitJumpInsn(IF_ICMPLT, l4);\r
413                         Label l7 = new Label();\r
414                         mv.visitLabel(l7);\r
415                         mv.visitLineNumber(109, l7);\r
416                         mv.visitVarInsn(ALOAD, 0);\r
417                         mv.visitVarInsn(ALOAD, 1);\r
418                         mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "create", "([Ljava/lang/Object;)Ljava/lang/Object;");\r
419                         mv.visitInsn(ARETURN);\r
420                         Label l8 = new Label();\r
421                         mv.visitLabel(l8);\r
422                         mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l8, 0);\r
423                         mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l1, l8, 1);\r
424                         mv.visitLocalVariable("i", "I", null, l2, l7, 2);\r
425                         mv.visitLocalVariable("fb", "Lorg/simantics/databoard/binding/Binding;", null, l5, l6, 3);\r
426                         mv.visitMaxs(3, 4);\r
427                         mv.visitEnd();                  \r
428                 }\r
429                 \r
430                 // setComponent\r
431                 {\r
432                         mv = cv.visitMethod(ACC_PUBLIC, "setComponent", "(Ljava/lang/Object;ILjava/lang/Object;)V", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
433                         mv.visitCode();\r
434                         Label l0 = new Label();\r
435                         mv.visitLabel(l0);\r
436                         mv.visitVarInsn(ALOAD, 1);\r
437                         mv.visitTypeInsn(CHECKCAST, className);\r
438                         mv.visitVarInsn(ASTORE, 4);\r
439                         Label endLabel = new Label();\r
440                         Label l1 = new Label();\r
441                         mv.visitLabel(l1);\r
442                         \r
443                         Label elseLabel = new Label();\r
444                         Label labels[] = new Label[ count ];                    \r
445                         for (int i=0; i<count; i++) labels[i] = new Label();\r
446                         \r
447                         if (count>0) {\r
448                                 mv.visitVarInsn(ILOAD, 2);\r
449                                 mv.visitTableSwitchInsn(0, count-1, elseLabel, labels);\r
450                                 \r
451                                 for (int i=0; i<count; i++) {\r
452                                         Label label = labels[ i ];\r
453                                         mv.visitLabel(label);\r
454                                         Field field = ci.fields[i];\r
455                                         String fieldName = field.getName();\r
456                                         Class<?> fieldClass = ci.fields[i].getType();\r
457                                         Class<?> boxClass = getBoxClass(fieldClass);\r
458                                         String typeDescriptor = toTypeDescriptor( fieldClass );\r
459                                         String boxTypeDescriptor = toTypeDescriptor( boxClass );\r
460         \r
461                                         Method setter = ci.setters[i];\r
462                                         Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;\r
463                                         boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;\r
464                 \r
465                                         if (i==0) {\r
466                                                 mv.visitFrame(Opcodes.F_APPEND,1, classNameX, 0, null);\r
467                                         } else {\r
468                                                 mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
469                                         }\r
470                                         mv.visitVarInsn(ALOAD, 4);\r
471                                         mv.visitVarInsn(ALOAD, 3);\r
472                                         mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));\r
473                                         \r
474                                         if (useSetter) {\r
475                                                 unbox(mv, setterClass);\r
476                                                 mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");\r
477                                         } else {\r
478                                                 unbox(mv, fieldClass);\r
479                                                 mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);                                        \r
480                                         }\r
481                                         mv.visitInsn(RETURN);\r
482                                 }\r
483                         }\r
484                 \r
485                         mv.visitLabel(elseLabel);\r
486                         mv.visitLineNumber(178, elseLabel);\r
487                         if (count>0) {\r
488                                 mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
489                         }                       \r
490                         mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
491                         mv.visitInsn(DUP);\r
492                         mv.visitLdcInsn("Illegal field index");\r
493                         mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
494                         mv.visitInsn(ATHROW);\r
495 \r
496                         mv.visitLabel(endLabel);\r
497                         mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, endLabel, 0);\r
498                         mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);\r
499                         mv.visitLocalVariable("index", "I", null, l0, endLabel, 2);\r
500                         mv.visitLocalVariable("value", "Ljava/lang/Object;", null, l0, endLabel, 3);\r
501                         //mv.visitLocalVariable("x", "L"+className+";", null, l1, endLabel, 4);\r
502                         mv.visitMaxs(3, 5);\r
503                         mv.visitEnd();                  \r
504                 }\r
505                 \r
506                 // IsImmutable\r
507                 {\r
508                         mv = cv.visitMethod(ACC_PUBLIC, "isImmutable", "()Z", null, null);\r
509                         mv.visitCode();\r
510                         Label l0 = new Label();\r
511                         mv.visitLabel(l0);\r
512                         mv.visitInsn(ICONST_0);\r
513                         mv.visitInsn(IRETURN);\r
514                         Label l1 = new Label();\r
515                         mv.visitLabel(l1);\r
516                         mv.visitLocalVariable("this", "L"+className+";", null, l0, l1, 0);\r
517                         mv.visitMaxs(1, 1);\r
518                         mv.visitEnd();\r
519                 }\r
520 \r
521                 // IsInstance\r
522                 {\r
523                         mv = cv.visitMethod(ACC_PUBLIC, "isInstance", "(Ljava/lang/Object;)Z", null, null);\r
524                         mv.visitCode();\r
525                         Label l0 = new Label();\r
526                         mv.visitLabel(l0);\r
527                         mv.visitVarInsn(ALOAD, 1);\r
528                         mv.visitTypeInsn(INSTANCEOF, className);\r
529                         mv.visitInsn(IRETURN);\r
530                         Label l1 = new Label();\r
531                         mv.visitLabel(l1);\r
532                         mv.visitLocalVariable("this", "L"+className+";", null, l0, l1, 0);\r
533                         mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l1, 1);\r
534                         mv.visitMaxs(1, 2);\r
535                         mv.visitEnd();\r
536                 }\r
537 \r
538                 // SetComponents\r
539                 {                       \r
540                         mv = cv.visitMethod(ACC_PUBLIC + ACC_VARARGS, "setComponents", "(Ljava/lang/Object;[Ljava/lang/Object;)V", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
541                         mv.visitCode();\r
542                         Label l0 = new Label();\r
543                         mv.visitLabel(l0);\r
544                         mv.visitVarInsn(ALOAD, 1);\r
545                         mv.visitTypeInsn(CHECKCAST, className);\r
546                         mv.visitVarInsn(ASTORE, 3);\r
547                         Label firstLabel = l0;\r
548                         \r
549                         for (int i=0; i<count; i++) {\r
550                                 Label label = new Label();\r
551                                 if (firstLabel==l0) firstLabel = label;\r
552                                 Field field = ci.fields[i];\r
553                                 String fieldName = field.getName();\r
554                                 Class<?> fieldClass = ci.fields[i].getType();\r
555                                 Class<?> boxClass = getBoxClass(fieldClass);\r
556                                 String typeDescriptor = toTypeDescriptor( fieldClass );\r
557                                 String boxTypeDescriptor = toTypeDescriptor( boxClass );\r
558 \r
559                                 Method setter = ci.setters[i];\r
560                                 Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;\r
561                                 boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;\r
562                                 \r
563                                 mv.visitLabel(label);\r
564                                 mv.visitVarInsn(ALOAD, 3);\r
565                                 mv.visitVarInsn(ALOAD, 2);\r
566                                 if (i<6) {\r
567                                         mv.visitInsn(ICONST_0 + i);\r
568                                 } else {\r
569                                         mv.visitIntInsn(BIPUSH, i);                                             \r
570                                 }\r
571                                 mv.visitInsn(AALOAD);\r
572                                 mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));\r
573                                                         \r
574                                 if (useSetter) {\r
575                                         unbox(mv, setterClass);\r
576                                         mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");\r
577                                 } else {\r
578                                         unbox(mv, fieldClass);\r
579                                         mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);\r
580                                 }\r
581                                 \r
582                         }\r
583                         Label l17 = new Label();\r
584                         mv.visitLabel(l17);\r
585                         mv.visitInsn(RETURN);\r
586                         Label endLabel = new Label();\r
587                         mv.visitLabel(endLabel);\r
588                         mv.visitLocalVariable("this", "L"+className+";", null, l0, endLabel, 0);\r
589                         mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);\r
590                         mv.visitLocalVariable("value", "[Ljava/lang/Object;", null, l0, endLabel, 2);\r
591                         //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, firstLabel, endLabel, 3);\r
592                         mv.visitMaxs(3, 4);\r
593                         mv.visitEnd();\r
594                 }\r
595                 \r
596                 // Add primitive setters\r
597                 {\r
598                         addGetSetPrimitive(ci, cv, "Boolean", "Z", bindingClassName);\r
599                         addGetSetPrimitive(ci, cv, "Byte", "B", bindingClassName);\r
600                         addGetSetPrimitive(ci, cv, "Int", "I", bindingClassName);\r
601                         addGetSetPrimitive(ci, cv, "Long", "J", bindingClassName);\r
602                         addGetSetPrimitive(ci, cv, "Float", "F", bindingClassName);\r
603                         addGetSetPrimitive(ci, cv, "Double", "D", bindingClassName);\r
604                 }\r
605                 \r
606                 cv.visitEnd();\r
607                 return cw.toByteArray();\r
608         }\r
609         \r
610         private void addGetSetPrimitive(ClassInfo ci, ClassVisitor cv, String setterName, String signature, String bindingClassName)\r
611         {\r
612             String className = ci.clazz.getName().replaceAll("\\.", "/");\r
613             \r
614             Label firstLabel = new Label();\r
615             Label secondLabel = new Label();\r
616             Label errorLabel = new Label();\r
617             Label exitLabel = new Label();\r
618             Label lastLabel = new Label();\r
619             \r
620             boolean oneByte = !signature.equals("J") && !signature.equals("D");\r
621             \r
622             int c = 0;\r
623             for (Field f : ci.fields) {\r
624                 if ( toTypeDescriptor(getPrimitiveClass(f.getType())).equals( signature ) ) c++;                                \r
625             }\r
626             \r
627             int[] indices = new int[ c ];\r
628             Label[] caseLabel = new Label[ c ];\r
629 \r
630             c = 0;\r
631             for (int i=0; i<ci.fields.length; i++) \r
632             {\r
633                 Class<?> fieldClass = ci.fields[i].getType();\r
634                 fieldClass = getPrimitiveClass(fieldClass);\r
635                 String s = toTypeDescriptor(fieldClass);\r
636                 if ( !s.equals( signature ) ) continue;\r
637                 \r
638                 indices[c] = i;\r
639                 caseLabel[c] = new Label();\r
640                 c++;\r
641             }\r
642                     \r
643             //////////////////\r
644             /// Setter\r
645             ///\r
646             MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "set"+setterName, "(Ljava/lang/Object;I"+signature+")V", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
647             mv.visitCode();\r
648             mv.visitLabel(firstLabel);\r
649             mv.visitVarInsn(ALOAD, 1);\r
650             mv.visitTypeInsn(CHECKCAST, className);\r
651             mv.visitVarInsn(ASTORE, oneByte?4:5);\r
652 \r
653             mv.visitLabel(secondLabel);\r
654             mv.visitVarInsn(ILOAD, 2);\r
655 \r
656             // switch\r
657             mv.visitLookupSwitchInsn(errorLabel, indices, caseLabel);\r
658 \r
659             // case 1:\r
660             if ( c>0 ) {\r
661                     for (int i=0; i<c; i++) {\r
662                         int index = indices[i];\r
663                     Method setter = ci.setters[index];\r
664                     Field field = ci.fields[index];\r
665                     Class<?> fieldClass = field.getType();\r
666                     Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;\r
667                     boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;\r
668                     String typeDescriptor = toTypeDescriptor( useSetter ? setterClass : fieldClass );\r
669                         \r
670                     mv.visitLabel(caseLabel[i]);\r
671                     if ( i == 0 ) {\r
672                         mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {className}, 0, null);\r
673                     } else {\r
674                         mv.visitFrame(Opcodes.F_SAME, 0, new Object[] {className}, 0, null);\r
675                     }\r
676                     if ( signature.equals("F") ) {\r
677                             mv.visitVarInsn(ALOAD, 4);\r
678                             mv.visitVarInsn(FLOAD, 3);\r
679                     } else if ( signature.equals("D") ) {\r
680                             mv.visitVarInsn(ALOAD, 5);\r
681                             mv.visitVarInsn(DLOAD, 3);\r
682                     } else if ( signature.equals("J") ) {\r
683                             mv.visitVarInsn(ALOAD, 5);\r
684                             mv.visitVarInsn(LLOAD, 3);\r
685                     } else {\r
686                             mv.visitVarInsn(ALOAD, 4);\r
687                             mv.visitVarInsn(ILOAD, 3);\r
688                     }\r
689                     \r
690                     if ( useSetter ) {\r
691                         boxTo(mv, setterClass);\r
692                         mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");\r
693                     } else {\r
694                         boxTo(mv, fieldClass);\r
695                         mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);\r
696                     }\r
697                     mv.visitJumpInsn(GOTO, exitLabel);\r
698                     }\r
699             } else {\r
700                 mv.visitInsn(POP);              \r
701             }\r
702 \r
703             // default: (error)\r
704             /*\r
705             mv.visitLabel(errorLabel);\r
706             mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
707             mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
708             mv.visitInsn(DUP);\r
709             mv.visitLdcInsn("Field is not "+setterName);\r
710             mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
711             mv.visitInsn(ATHROW);\r
712             */\r
713             \r
714             // default: setComponent\r
715             mv.visitLabel(errorLabel);\r
716             mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
717             mv.visitVarInsn(ALOAD, 0);\r
718             mv.visitVarInsn(ALOAD, 1);\r
719             mv.visitVarInsn(ILOAD, 2);\r
720             mv.visitVarInsn(ALOAD, 0);\r
721             mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");\r
722             mv.visitVarInsn(ILOAD, 2);\r
723             mv.visitInsn(AALOAD);\r
724             if ( signature.equals("F") ) {\r
725                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/FloatBinding");\r
726                     mv.visitVarInsn(FLOAD, 3);\r
727                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/FloatBinding", "create", "(F)Ljava/lang/Object;");\r
728             } else if ( signature.equals("D") ) {\r
729                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/DoubleBinding");\r
730                     mv.visitVarInsn(DLOAD, 3);\r
731                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/DoubleBinding", "create", "(D)Ljava/lang/Object;");\r
732             } else if ( signature.equals("J") ) {\r
733                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/LongBinding");\r
734                     mv.visitVarInsn(LLOAD, 3);\r
735                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/LongBinding", "create", "(J)Ljava/lang/Object;");\r
736             } else if ( signature.equals("Z") ){\r
737                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/BooleanBinding");\r
738                     mv.visitVarInsn(ILOAD, 3);\r
739                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/BooleanBinding", "create", "(Z)Ljava/lang/Object;");\r
740             } else if ( signature.equals("I") ){\r
741                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/IntBinding");\r
742                     mv.visitVarInsn(ILOAD, 3);\r
743                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/IntBinding", "create", "(I)Ljava/lang/Object;");\r
744             } else if ( signature.equals("B") ){\r
745                 mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/ByteBinding");\r
746                     mv.visitVarInsn(ILOAD, 3);\r
747                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/ByteBinding", "create", "(B)Ljava/lang/Object;");\r
748             }       \r
749             mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponent", "(Ljava/lang/Object;ILjava/lang/Object;)V");\r
750 \r
751             // return\r
752             mv.visitLabel(exitLabel);\r
753             mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
754             mv.visitInsn(RETURN);\r
755 \r
756             // Something at the end\r
757             mv.visitLabel(lastLabel);\r
758 //          mv.visitLocalVariable("this", "L"+bindingClassName+";", null, firstLabel, lastLabel, 0);\r
759 //          mv.visitLocalVariable("r", "Ljava/lang/Object;", null, firstLabel, lastLabel, 1);\r
760 //          mv.visitLocalVariable("index", "I", null, firstLabel, lastLabel, 2);\r
761 //          mv.visitLocalVariable("z", signature, null, firstLabel, lastLabel, 3);\r
762 //          mv.visitLocalVariable("x", "L"+className+";", null, secondLabel, lastLabel, 4);\r
763             mv.visitMaxs(oneByte?5:6, oneByte?5:6);\r
764             mv.visitEnd();\r
765             \r
766             \r
767             //////////////////\r
768             /// Getter\r
769             ///\r
770             firstLabel = new Label();\r
771             secondLabel = new Label();\r
772             errorLabel = new Label();\r
773             exitLabel = new Label();\r
774             lastLabel = new Label();\r
775             for (int i=0; i<c; i++) caseLabel[i] = new Label();\r
776             mv = cv.visitMethod(ACC_PUBLIC, "get"+setterName, "(Ljava/lang/Object;I)"+signature, null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
777             mv.visitCode();\r
778             mv.visitLabel(firstLabel);\r
779             mv.visitVarInsn(ALOAD, 1);\r
780             mv.visitTypeInsn(CHECKCAST, className);\r
781             mv.visitVarInsn(ASTORE, 3);\r
782 \r
783             mv.visitLabel(secondLabel);\r
784             mv.visitVarInsn(ILOAD, 2);\r
785 \r
786             // switch\r
787             if ( c>0 ) {\r
788                     mv.visitLookupSwitchInsn(errorLabel, indices, caseLabel);\r
789         \r
790                     // case i:\r
791                     for (int i=0; i<c; i++) {\r
792                         int index = indices[i];\r
793                     Method getter = ci.getters[index];\r
794                     Field field = ci.fields[index];\r
795                     Class<?> fieldClass = field.getType();\r
796                     Class<?> getterClass = getter!=null?getter.getReturnType():null;\r
797                     boolean useGetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && getter!=null;\r
798                     String typeDescriptor = toTypeDescriptor( useGetter ? getterClass : fieldClass );\r
799                         \r
800                     mv.visitLabel(caseLabel[i]);\r
801                     if ( i == 0 ) {\r
802                         mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {className}, 0, null);\r
803                     } else {\r
804                         mv.visitFrame(Opcodes.F_SAME, 0, new Object[] {className}, 0, null);\r
805                     }\r
806         \r
807                     mv.visitVarInsn(ALOAD, 3);\r
808                     \r
809                     if ( useGetter ) {\r
810                         mv.visitMethodInsn(INVOKEVIRTUAL, className, getter.getName(), "()"+typeDescriptor);\r
811                         unboxFrom(mv, getterClass);\r
812                     } else {\r
813                         mv.visitFieldInsn(GETFIELD, className, field.getName(), typeDescriptor);\r
814                         unboxFrom(mv, fieldClass);\r
815                     }\r
816                     \r
817                     if ( signature.equals("F") ) {\r
818                             mv.visitInsn(FRETURN);\r
819                     } else if ( signature.equals("D") ) {\r
820                             mv.visitInsn(DRETURN);\r
821                     } else if ( signature.equals("J") ) {\r
822                             mv.visitInsn(LRETURN);\r
823                     } else {\r
824                             mv.visitInsn(IRETURN);\r
825                     }\r
826                     }\r
827             } else {\r
828                 mv.visitInsn(POP);              \r
829             }\r
830 \r
831             // default: (error)\r
832             /*\r
833             mv.visitLabel(errorLabel);\r
834             mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
835             mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
836             mv.visitInsn(DUP);\r
837             mv.visitLdcInsn("Field is not "+setterName);\r
838             mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
839             mv.visitInsn(ATHROW);\r
840             */\r
841             \r
842             // default:\r
843             mv.visitLabel(errorLabel);\r
844             mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
845             mv.visitVarInsn(ALOAD, 0);\r
846             mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");\r
847             mv.visitVarInsn(ILOAD, 2);\r
848             mv.visitInsn(AALOAD);\r
849             if ( signature.equals("Z") ) {\r
850                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/BooleanBinding");\r
851                     mv.visitVarInsn(ALOAD, 0);\r
852                     mv.visitVarInsn(ALOAD, 1);\r
853                     mv.visitVarInsn(ILOAD, 2);\r
854                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
855                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/BooleanBinding", "getValue_", "(Ljava/lang/Object;)Z");\r
856                     mv.visitInsn(IRETURN);\r
857             } else if ( signature.equals("B") ) {\r
858                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/ByteBinding");\r
859                     mv.visitVarInsn(ALOAD, 0);\r
860                     mv.visitVarInsn(ALOAD, 1);\r
861                     mv.visitVarInsn(ILOAD, 2);\r
862                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
863                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/ByteBinding", "getValue_", "(Ljava/lang/Object;)B");\r
864                     mv.visitInsn(IRETURN);\r
865             } else if ( signature.equals("I") ) {\r
866                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/IntBinding");\r
867                     mv.visitVarInsn(ALOAD, 0);\r
868                     mv.visitVarInsn(ALOAD, 1);\r
869                     mv.visitVarInsn(ILOAD, 2);\r
870                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
871                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/IntBinding", "getValue_", "(Ljava/lang/Object;)I");\r
872                     mv.visitInsn(IRETURN);\r
873             } else if ( signature.equals("J") ) {\r
874                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/LongBinding");\r
875                     mv.visitVarInsn(ALOAD, 0);\r
876                     mv.visitVarInsn(ALOAD, 1);\r
877                     mv.visitVarInsn(ILOAD, 2);\r
878                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
879                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/LongBinding", "getValue_", "(Ljava/lang/Object;)J");\r
880                     mv.visitInsn(LRETURN);\r
881             } else if ( signature.equals("F") ) {\r
882                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/FloatBinding");\r
883                     mv.visitVarInsn(ALOAD, 0);\r
884                     mv.visitVarInsn(ALOAD, 1);\r
885                     mv.visitVarInsn(ILOAD, 2);\r
886                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
887                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/FloatBinding", "getValue_", "(Ljava/lang/Object;)F");\r
888                     mv.visitInsn(FRETURN);\r
889             } else if ( signature.equals("D") ) {\r
890                     mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/DoubleBinding");\r
891                     mv.visitVarInsn(ALOAD, 0);\r
892                     mv.visitVarInsn(ALOAD, 1);\r
893                     mv.visitVarInsn(ILOAD, 2);\r
894                     mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
895                     mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/DoubleBinding", "getValue_", "(Ljava/lang/Object;)D");\r
896                     mv.visitInsn(DRETURN);\r
897             }       \r
898 \r
899             // Something at the end\r
900             mv.visitLabel(lastLabel);\r
901 //          mv.visitLocalVariable("this", "Lorg/simantics/databoard/binding/reflection/MyBinding;", null, firstLabel, lastLabel, 0);\r
902 //          mv.visitLocalVariable("r", "Ljava/lang/Object;", null, firstLabel, lastLabel, 1);\r
903 //          mv.visitLocalVariable("index", "I", null, firstLabel, lastLabel, 2);\r
904 //          mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, secondLabel, lastLabel, 3);\r
905             mv.visitMaxs(4, 4);\r
906             mv.visitEnd();          \r
907             \r
908         }\r
909 \r
910 \r
911         public static Label[] createFieldLabels(ClassInfo ci) \r
912         {\r
913                 Label caseLabels[] = new Label[ ci.fields.length ];\r
914                 for (int i=0; i<ci.fields.length; i++) caseLabels[i] = new Label();\r
915                 return caseLabels;\r
916         }\r
917         \r
918         public static String toTypeDescriptor(Class<?> clazz) {\r
919                 if (clazz==void.class) return "V";\r
920                 if (clazz==boolean.class) return "Z";\r
921                 if (clazz==char.class) return "C";\r
922                 if (clazz==byte.class) return "B";\r
923                 if (clazz==short.class) return "S";\r
924                 if (clazz==int.class) return "I";\r
925                 if (clazz==float.class) return "F";\r
926                 if (clazz==long.class) return "J";\r
927                 if (clazz==double.class) return "D";\r
928                 if (clazz.isArray()) return clazz.getName().replaceAll("\\.", "/");             \r
929                 return "L"+clazz.getName().replaceAll("\\.", "/")+";";\r
930         }\r
931         \r
932         /**\r
933          * Get respective boxed class\r
934          * @param clazz\r
935          * @return box-class\r
936          */\r
937         public static Class<?> getBoxClass(Class<?> clazz) {\r
938                 if (clazz==void.class) return null;\r
939                 if (clazz==boolean.class) return Boolean.class;\r
940                 if (clazz==char.class) return Character.class;\r
941                 if (clazz==byte.class) return Byte.class;\r
942                 if (clazz==short.class) return Short.class;\r
943                 if (clazz==int.class) return Integer.class;\r
944                 if (clazz==float.class) return Float.class;\r
945                 if (clazz==long.class) return Long.class;\r
946                 if (clazz==double.class) return Double.class;\r
947                 return clazz;\r
948         }\r
949         \r
950         /**\r
951          * Get respective primitive class\r
952          * @param clazz\r
953          * @return primitive-class\r
954          */\r
955         public static Class<?> getPrimitiveClass(Class<?> clazz) {\r
956             if (clazz==Boolean.class) return boolean.class;\r
957             if (clazz==Character.class) return char.class;\r
958             if (clazz==Byte.class) return byte.class;\r
959             if (clazz==Short.class) return short.class;\r
960             if (clazz==Integer.class) return int.class;\r
961             if (clazz==Float.class) return float.class;\r
962             if (clazz==Long.class) return long.class;\r
963             if (clazz==Double.class) return double.class;\r
964             return clazz;\r
965         }          \r
966         \r
967         public static boolean isPrimitive(Class<?> clazz) {\r
968                 return clazz==boolean.class || clazz==char.class || clazz==byte.class ||\r
969                                 clazz==short.class || clazz==int.class || clazz==float.class ||\r
970                                 clazz==long.class || clazz==double.class;\r
971         }\r
972         \r
973         public static void unbox(MethodVisitor mv, Class<?> clazz) {\r
974                 if (clazz==boolean.class) {\r
975                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");\r
976                 } else if (clazz==char.class) {\r
977                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); // C?\r
978                 } else if (clazz==byte.class) {\r
979                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");\r
980                 } else if (clazz==short.class) {\r
981                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");\r
982                 } else if (clazz==int.class) {\r
983                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");\r
984                 } else if (clazz==float.class) {\r
985                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");\r
986                 } else if (clazz==long.class) {\r
987                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");\r
988                 } else if (clazz==double.class) {\r
989                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");\r
990                 }               \r
991         }\r
992 \r
993         public static void box(MethodVisitor mv, Class<?> clazz) {\r
994                 if (clazz==boolean.class) {\r
995                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");                     \r
996                 } else if (clazz==char.class) {\r
997                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");                         \r
998                 } else if (clazz==byte.class) {\r
999                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");                   \r
1000                 } else if (clazz==short.class) {\r
1001                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");                         \r
1002                 } else if (clazz==int.class) {\r
1003                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");                     \r
1004                 } else if (clazz==float.class) {\r
1005                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");                         \r
1006                 } else if (clazz==long.class) {\r
1007                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");                   \r
1008                 } else if (clazz==double.class) {\r
1009                         mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");                       \r
1010                 }               \r
1011         }\r
1012         \r
1013     public static void boxTo(MethodVisitor mv, Class<?> clazz) {\r
1014         if (clazz==Boolean.class) {\r
1015             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");         \r
1016         } else if (clazz==Character.class) {\r
1017             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");             \r
1018         } else if (clazz==Byte.class) {\r
1019             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");           \r
1020         } else if (clazz==Short.class) {\r
1021             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");             \r
1022         } else if (clazz==Integer.class) {\r
1023             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");             \r
1024         } else if (clazz==Float.class) {\r
1025             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");             \r
1026         } else if (clazz==Long.class) {\r
1027             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");           \r
1028         } else if (clazz==Double.class) {\r
1029             mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");           \r
1030         }       \r
1031     }\r
1032     \r
1033     public static void unboxFrom(MethodVisitor mv, Class<?> clazz) {\r
1034                 if (clazz==Boolean.class) {\r
1035                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");\r
1036                 } else if (clazz==Character.class) {\r
1037                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); // C?\r
1038                 } else if (clazz==Byte.class) {\r
1039                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");\r
1040                 } else if (clazz==Short.class) {\r
1041                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");\r
1042                 } else if (clazz==Integer.class) {\r
1043                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");\r
1044                 } else if (clazz==Float.class) {\r
1045                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");\r
1046                 } else if (clazz==Long.class) {\r
1047                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");\r
1048                 } else if (clazz==Double.class) {\r
1049                         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");\r
1050                 }               \r
1051     }   \r
1052     \r
1053         \r
1054         public static String toClassCanonicalName(Class<?> clazz)\r
1055         {\r
1056                 return clazz.getName().replaceAll("\\.", "/");\r
1057         }\r
1058 \r
1059         \r
1060         \r
1061 }\r