]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/AsmBindingClassLoader.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/AsmBindingClassLoader.java
new file mode 100644 (file)
index 0000000..3593565
--- /dev/null
@@ -0,0 +1,1061 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.databoard.binding.reflection;\r
+\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.Modifier;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.objectweb.asm.AnnotationVisitor;\r
+import org.objectweb.asm.ClassVisitor;\r
+import org.objectweb.asm.ClassWriter;\r
+import org.objectweb.asm.FieldVisitor;\r
+import org.objectweb.asm.Label;\r
+import org.objectweb.asm.MethodVisitor;\r
+import org.objectweb.asm.Opcodes;\r
+import org.objectweb.asm.Type;\r
+import org.simantics.databoard.binding.error.BindingConstructionException;\r
+\r
+public class AsmBindingClassLoader extends ClassLoader implements Opcodes {\r
+\r
+       Map<String, Class<?>> map = new HashMap<String, Class<?>>();\r
+       \r
+       public AsmBindingClassLoader() {\r
+               super(Thread.currentThread().getContextClassLoader());\r
+       }\r
+\r
+       public AsmBindingClassLoader(ClassLoader parent) {\r
+               super(parent);\r
+       }       \r
+       \r
+       public String toBindingClassName( String targetClassName )\r
+       {\r
+               if ( targetClassName.startsWith("java" ) ) {\r
+                       return "x"+targetClassName+".Binding";\r
+               }\r
+               return targetClassName+".Binding";\r
+       }\r
+       \r
+       public String toTargetClassName( String bindingClassName )\r
+       {\r
+               if (!bindingClassName.endsWith(".Binding")) return null;\r
+               if (bindingClassName.substring(1,5).equals("java")) {\r
+                       return bindingClassName.substring(1, bindingClassName.length()-8);\r
+               } else {\r
+                       return bindingClassName.substring(0, bindingClassName.length()-8);\r
+               }\r
+       }\r
+       \r
+       @Override\r
+       protected synchronized Class<?> findClass(String bindingClassName) \r
+       throws ClassNotFoundException \r
+       {\r
+               Class<?> c = map.get(bindingClassName);\r
+               if ( c!= null) return c;\r
+                               \r
+               try {\r
+                       String targetClassName = toTargetClassName(bindingClassName);\r
+                       if ( targetClassName == null ) {\r
+//                             try {\r
+                                       return super.findClass(bindingClassName);\r
+//                             } catch( ClassNotFoundException e ) {\r
+//                                     e.printStackTrace();\r
+//                                     throw e;\r
+//                             }\r
+                       }\r
+                       \r
+                       ClassLoader cl = getParent();\r
+                       if (cl==null) { \r
+                               cl = Thread.currentThread().getContextClassLoader();\r
+                       }\r
+                       Class<?> targetClass = cl.loadClass( targetClassName );\r
+                       ClassInfo ci = ClassInfo.getInfo( targetClass );\r
+                       byte[] data = createBindingClass( ci, bindingClassName );\r
+                       Class<?> bindingClass = defineClass( bindingClassName, data, 0, data.length );\r
+                       map.put(bindingClassName, bindingClass);\r
+                       return bindingClass;\r
+               } catch (BindingConstructionException e) {\r
+                       throw new ClassNotFoundException( e.getMessage(), e.getCause() );\r
+               }               \r
+       }       \r
+       \r
+       public synchronized Class<?> getBindingClass(Class<?> targetClass)\r
+       throws ClassNotFoundException\r
+       {\r
+               String targetClassName = targetClass.getName();\r
+               String bindingClassName = toBindingClassName(targetClassName);\r
+               Class<?> c = map.get(bindingClassName);\r
+               if ( c!= null) return c;\r
+                               \r
+               try {\r
+                       ClassInfo ci = ClassInfo.getInfo( targetClass );\r
+                       byte[] data = createBindingClass( ci, bindingClassName );\r
+                       Class<?> bindingClass = defineClass( bindingClassName, data, 0, data.length );\r
+                       map.put(bindingClassName, bindingClass);\r
+                       return bindingClass;\r
+               } catch (BindingConstructionException e) {\r
+                       throw new ClassNotFoundException( e.getMessage(), e.getCause() );\r
+               }               \r
+               \r
+       }\r
+\r
+       public byte[] createBindingClass(ClassInfo ci, String bindingClassName)\r
+       {\r
+               //System.out.println("BindingFactory: "+bindingClassName+" (for "+ci.clazz.getClassLoader()+")");\r
+               int count = ci.fields.length;\r
+               ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS );\r
+               ClassVisitor cv = cw;//new CheckClassAdapter(cw);\r
+               \r
+               FieldVisitor fv;\r
+               MethodVisitor mv;\r
+               AnnotationVisitor av0;          \r
+       \r
+               String className = ci.clazz.getName().replaceAll("\\.", "/");           \r
+               bindingClassName = bindingClassName.replaceAll("\\.", "/");\r
+               Object[] classNameX = new Object[] {className};\r
+               String signature = "L"+bindingClassName+";";\r
+               \r
+               // Constructor\r
+               String superClass = "org/simantics/databoard/binding/reflection/ClassBinding";\r
+               cv.visit(V1_6, ACC_PUBLIC + ACC_SUPER, bindingClassName, null, superClass, null);       \r
+\r
+               // Constructor\r
+               {\r
+                       mv = cv.visitMethod(ACC_PUBLIC, "<init>", "(Lorg/simantics/databoard/type/RecordType;)V", null, new String[] { "org/simantics/databoard/binding/error/BindingConstructionException" });\r
+                       \r
+                       mv.visitCode();\r
+                       Label l0 = new Label();                 \r
+                       mv.visitLabel(l0);\r
+                       mv.visitVarInsn(ALOAD, 0);\r
+                       mv.visitLdcInsn(Type.getType("L"+className+";"));                       \r
+                       mv.visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "(Ljava/lang/Class;)V");\r
+                       \r
+                       Label l1 = new Label();\r
+                       mv.visitLabel(l1);\r
+                       mv.visitVarInsn(ALOAD, 0);\r
+                       mv.visitVarInsn(ALOAD, 1);\r
+                       mv.visitFieldInsn(PUTFIELD, bindingClassName, "type", "Lorg/simantics/databoard/type/Datatype;");\r
+\r
+                       Label l2 = new Label();\r
+                       mv.visitLabel(l2);\r
+                       mv.visitInsn(RETURN);\r
+\r
+                       Label l3 = new Label();\r
+                       mv.visitLabel(l3);\r
+                       mv.visitLocalVariable("this", signature, null, l0, l3, 0);\r
+                       mv.visitLocalVariable("type", "Lorg/simantics/databoard/type/RecordType;", null, l0, l3, 1);\r
+                       mv.visitMaxs(2, 2);\r
+                       mv.visitEnd();\r
+               }\r
+               \r
+               // getComponent\r
+               {\r
+                       mv = cv.visitMethod(ACC_PUBLIC, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+                       mv.visitCode();\r
+                       Label l0 = new Label();\r
+                       mv.visitLabel(l0);\r
+                       mv.visitVarInsn(ALOAD, 1);\r
+                       mv.visitTypeInsn(CHECKCAST, className);\r
+                       mv.visitVarInsn(ASTORE, 3);\r
+                       Label l1 = new Label();\r
+                       mv.visitLabel(l1);\r
+\r
+                       Label caseLabels[] = createFieldLabels( ci );\r
+                       Label elseLabel = new Label();\r
+                       \r
+                       if ( count > 0 ) {\r
+                               // Switch\r
+                               mv.visitVarInsn(ILOAD, 2);\r
+                               mv.visitTableSwitchInsn(0, count-1, elseLabel, caseLabels);\r
+                               \r
+                               // case i: x.field = value[i]\r
+                               for (int i=0; i<count; i++) {\r
+                                       Label label = caseLabels[i];\r
+                                       Field field = ci.fields[i];\r
+                                       String fieldName = field.getName();\r
+                                       Class<?> fieldClass = ci.fields[i].getType();\r
+                                       String typeDescriptor = toTypeDescriptor( fieldClass );\r
+       \r
+                                       Method getter = ci.getters[i];\r
+                                       boolean useGetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && getter!=null;\r
+                                       \r
+                                       mv.visitLabel( label );\r
+                                       if ( i==0 ) {\r
+                                               mv.visitFrame(Opcodes.F_APPEND,1, classNameX, 0, null);\r
+                                       } else {\r
+                                               mv.visitFrame(Opcodes.F_SAME,0, null, 0, null);\r
+                                       }\r
+                                       \r
+                                       // Read instance argument\r
+                                       mv.visitVarInsn(ALOAD, 3);\r
+                                               \r
+                                       if ( useGetter ) {\r
+                                               // call getField\r
+                                               mv.visitMethodInsn(INVOKEVIRTUAL, className, getter.getName(), "()"+typeDescriptor);\r
+                                       } else {\r
+                                               // Read field\r
+                                               mv.visitFieldInsn(GETFIELD, className, fieldName, typeDescriptor);\r
+                                       }\r
+                                               \r
+                                       // Box \r
+                                       box(mv, fieldClass);\r
+                                               \r
+                                       mv.visitInsn(ARETURN);\r
+                               }\r
+       \r
+                       }\r
+                       \r
+                       mv.visitLabel(elseLabel);\r
+                       if (count>0) {\r
+                               mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+                       }                       \r
+                       mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
+                       mv.visitInsn(DUP);\r
+                       mv.visitLdcInsn("Illegal field index");\r
+                       mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
+                       mv.visitInsn(ATHROW);                   \r
+                       \r
+                       // End \r
+                       Label l19 = new Label();\r
+                       mv.visitLabel(l19);\r
+                       mv.visitLocalVariable("this", "L"+className+";", null, l0, l19, 0);\r
+                       mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l19, 1);\r
+                       mv.visitLocalVariable("index", "I", null, l0, l19, 2);\r
+                       //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, l1, l19, 3);\r
+                       mv.visitMaxs(3, 4);\r
+                       mv.visitEnd();\r
+               }\r
+               \r
+               // Create\r
+               {\r
+                       mv = cv.visitMethod(ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+                       if ( ci.beanConstructor != null ) {\r
+                               mv.visitCode();\r
+                               Label l0 = new Label();\r
+                               mv.visitLabel(l0);\r
+                               mv.visitTypeInsn(NEW, className);\r
+                               mv.visitInsn(DUP);\r
+                               mv.visitVarInsn(ALOAD, 0);\r
+                               mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");\r
+                               mv.visitVarInsn(ASTORE, 2);\r
+                               Label l1 = new Label();\r
+                               mv.visitLabel(l1);\r
+                               mv.visitVarInsn(ALOAD, 0);\r
+                               mv.visitVarInsn(ALOAD, 2);\r
+                               mv.visitVarInsn(ALOAD, 1);\r
+                               mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents", "(Ljava/lang/Object;[Ljava/lang/Object;)V");\r
+                               Label l2 = new Label();\r
+                               mv.visitLabel(l2);\r
+                               mv.visitVarInsn(ALOAD, 2);\r
+                               mv.visitInsn(ARETURN);\r
+                               Label l3 = new Label();\r
+                               mv.visitLabel(l3);\r
+                               mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l3, 0);\r
+                               mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);\r
+                               //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);\r
+                               mv.visitMaxs(3, 3);\r
+                               mv.visitEnd();                          \r
+                       } else if ( ci.argsConstructor != null ) {\r
+                               mv.visitCode();\r
+                               Label l0 = new Label();\r
+                               mv.visitLabel(l0);\r
+                               mv.visitTypeInsn(NEW, className);\r
+                               mv.visitInsn(DUP);\r
+                               \r
+                               String constArgsDescriptor = "(";\r
+                               Class<?>[] args = ci.argsConstructor.getParameterTypes();\r
+                               for (int i=0; i<count; i++) {\r
+                                       Label label = new Label();\r
+                                       Class<?> field = args[i];\r
+                                       String fieldName = field.getName();\r
+                                       Method getter = ci.getters[i];\r
+                                       Class<?> fieldClass = ci.fields[i].getType();\r
+                                       Class<?> boxClass = getBoxClass(fieldClass);\r
+                                       String typeDescriptor = toTypeDescriptor( fieldClass );\r
+                                       String boxTypeDescriptor = toTypeDescriptor( boxClass );\r
+                                       constArgsDescriptor += typeDescriptor;\r
+                                       \r
+                                       mv.visitLabel(label);\r
+                                       mv.visitVarInsn(ALOAD, 1);\r
+                                       if (i<6) {\r
+                                               mv.visitInsn(ICONST_0 + i);\r
+                                       } else {\r
+                                               mv.visitIntInsn(BIPUSH, i);                                             \r
+                                       }\r
+\r
+                                       mv.visitInsn(AALOAD);\r
+                                       mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));\r
+                                       unbox(mv, fieldClass);                                  \r
+                               }\r
+\r
+                               Label l17 = new Label();\r
+                               mv.visitLabel(l17);\r
+                               constArgsDescriptor += ")V";\r
+                               mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", constArgsDescriptor);\r
+                               mv.visitInsn(ARETURN);\r
+                               Label l18 = new Label();\r
+                               mv.visitLabel(l18);\r
+                               mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l18, 0);\r
+                               mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l18, 1);\r
+                               mv.visitMaxs(21, 2);\r
+                               mv.visitEnd();\r
+                               \r
+                       } else {\r
+                               mv.visitCode();\r
+                               Label l0 = new Label();\r
+                               mv.visitLabel(l0);\r
+                               mv.visitTypeInsn(NEW, className);\r
+                               mv.visitInsn(DUP);\r
+                               mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");\r
+                               mv.visitVarInsn(ASTORE, 2);\r
+                               Label l1 = new Label();\r
+                               mv.visitLabel(l1);\r
+                               mv.visitVarInsn(ALOAD, 0);\r
+                               mv.visitVarInsn(ALOAD, 2);\r
+                               mv.visitVarInsn(ALOAD, 1);\r
+                               mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents", "(Ljava/lang/Object;[Ljava/lang/Object;)V");\r
+                               Label l2 = new Label();\r
+                               mv.visitLabel(l2);\r
+                               mv.visitVarInsn(ALOAD, 2);\r
+                               mv.visitInsn(ARETURN);\r
+                               Label l3 = new Label();\r
+                               mv.visitLabel(l3);\r
+                               mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l3, 0);\r
+                               mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);\r
+                               //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);\r
+                               mv.visitMaxs(3, 3);\r
+                               mv.visitEnd();                          \r
+                       }\r
+               }\r
+               \r
+               // CreatePartial\r
+               mv = cv.visitMethod(ACC_PUBLIC, "createPartial", "()Ljava/lang/Object;", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+               if (ci.beanConstructor!=null)\r
+               { \r
+                       mv.visitCode();\r
+                       Label l0 = new Label();\r
+                       mv.visitLabel(l0);\r
+                       mv.visitTypeInsn(NEW, className);\r
+                       mv.visitInsn(DUP);\r
+                       mv.visitVarInsn(ALOAD, 0);\r
+                       mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");\r
+                       mv.visitInsn(ARETURN);\r
+                       Label l1 = new Label();\r
+                       mv.visitLabel(l1);\r
+                       mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l1, 0);\r
+                       mv.visitMaxs(3, 1);\r
+                       mv.visitEnd();                  \r
+               } else if (ci.noArgsConstructor != null)\r
+               {\r
+                       // return new MyClass();\r
+                       mv.visitCode();\r
+                       Label l0 = new Label();\r
+                       mv.visitLabel(l0);\r
+                       mv.visitTypeInsn(NEW, className);\r
+                       mv.visitInsn(DUP);\r
+                       mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");\r
+                       mv.visitInsn(ARETURN);\r
+                       Label l1 = new Label();\r
+                       mv.visitLabel(l1);\r
+                       mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l1, 0);\r
+                       mv.visitMaxs(2, 1);\r
+                       mv.visitEnd();                  \r
+               } else {\r
+                       mv.visitCode();\r
+                       Label l0 = new Label();\r
+                       mv.visitLabel(l0);\r
+                       mv.visitIntInsn(BIPUSH, count);\r
+                       mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");\r
+                       mv.visitVarInsn(ASTORE, 1);\r
+                       Label l1 = new Label();\r
+                       mv.visitLabel(l1);\r
+                       mv.visitInsn(ICONST_0);\r
+                       mv.visitVarInsn(ISTORE, 2);\r
+                       Label l2 = new Label();\r
+                       mv.visitLabel(l2);\r
+                       Label l3 = new Label();\r
+                       mv.visitJumpInsn(GOTO, l3);\r
+                       Label l4 = new Label();\r
+                       mv.visitLabel(l4);\r
+                       mv.visitFrame(Opcodes.F_APPEND,2, new Object[] {"[Ljava/lang/Object;", Opcodes.INTEGER}, 0, null);\r
+                       mv.visitVarInsn(ALOAD, 0);\r
+                       mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");\r
+                       mv.visitVarInsn(ILOAD, 2);\r
+                       mv.visitInsn(AALOAD);\r
+                       mv.visitVarInsn(ASTORE, 3);\r
+                       Label l5 = new Label();\r
+                       mv.visitLabel(l5);\r
+                       mv.visitVarInsn(ALOAD, 1);\r
+                       mv.visitVarInsn(ILOAD, 2);\r
+                       mv.visitVarInsn(ALOAD, 3);\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/Binding", "createDefault", "()Ljava/lang/Object;");\r
+                       mv.visitInsn(AASTORE);\r
+                       Label l6 = new Label();\r
+                       mv.visitLabel(l6);\r
+                       mv.visitIincInsn(2, 1);\r
+                       mv.visitLabel(l3);\r
+                       mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+                       mv.visitVarInsn(ILOAD, 2);\r
+                       mv.visitVarInsn(ALOAD, 1);\r
+                       mv.visitInsn(ARRAYLENGTH);\r
+                       mv.visitJumpInsn(IF_ICMPLT, l4);\r
+                       Label l7 = new Label();\r
+                       mv.visitLabel(l7);\r
+                       mv.visitLineNumber(109, l7);\r
+                       mv.visitVarInsn(ALOAD, 0);\r
+                       mv.visitVarInsn(ALOAD, 1);\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "create", "([Ljava/lang/Object;)Ljava/lang/Object;");\r
+                       mv.visitInsn(ARETURN);\r
+                       Label l8 = new Label();\r
+                       mv.visitLabel(l8);\r
+                       mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, l8, 0);\r
+                       mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l1, l8, 1);\r
+                       mv.visitLocalVariable("i", "I", null, l2, l7, 2);\r
+                       mv.visitLocalVariable("fb", "Lorg/simantics/databoard/binding/Binding;", null, l5, l6, 3);\r
+                       mv.visitMaxs(3, 4);\r
+                       mv.visitEnd();                  \r
+               }\r
+               \r
+               // setComponent\r
+               {\r
+                       mv = cv.visitMethod(ACC_PUBLIC, "setComponent", "(Ljava/lang/Object;ILjava/lang/Object;)V", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+                       mv.visitCode();\r
+                       Label l0 = new Label();\r
+                       mv.visitLabel(l0);\r
+                       mv.visitVarInsn(ALOAD, 1);\r
+                       mv.visitTypeInsn(CHECKCAST, className);\r
+                       mv.visitVarInsn(ASTORE, 4);\r
+                       Label endLabel = new Label();\r
+                       Label l1 = new Label();\r
+                       mv.visitLabel(l1);\r
+                       \r
+                       Label elseLabel = new Label();\r
+                       Label labels[] = new Label[ count ];                    \r
+                       for (int i=0; i<count; i++) labels[i] = new Label();\r
+                       \r
+                       if (count>0) {\r
+                               mv.visitVarInsn(ILOAD, 2);\r
+                               mv.visitTableSwitchInsn(0, count-1, elseLabel, labels);\r
+                               \r
+                               for (int i=0; i<count; i++) {\r
+                                       Label label = labels[ i ];\r
+                                       mv.visitLabel(label);\r
+                                       Field field = ci.fields[i];\r
+                                       String fieldName = field.getName();\r
+                                       Class<?> fieldClass = ci.fields[i].getType();\r
+                                       Class<?> boxClass = getBoxClass(fieldClass);\r
+                                       String typeDescriptor = toTypeDescriptor( fieldClass );\r
+                                       String boxTypeDescriptor = toTypeDescriptor( boxClass );\r
+       \r
+                                       Method setter = ci.setters[i];\r
+                                       Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;\r
+                                       boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;\r
+               \r
+                                       if (i==0) {\r
+                                               mv.visitFrame(Opcodes.F_APPEND,1, classNameX, 0, null);\r
+                                       } else {\r
+                                               mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+                                       }\r
+                                       mv.visitVarInsn(ALOAD, 4);\r
+                                       mv.visitVarInsn(ALOAD, 3);\r
+                                       mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));\r
+                                       \r
+                                       if (useSetter) {\r
+                                               unbox(mv, setterClass);\r
+                                               mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");\r
+                                       } else {\r
+                                               unbox(mv, fieldClass);\r
+                                               mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);                                        \r
+                                       }\r
+                                       mv.visitInsn(RETURN);\r
+                               }\r
+                       }\r
+               \r
+                       mv.visitLabel(elseLabel);\r
+                       mv.visitLineNumber(178, elseLabel);\r
+                       if (count>0) {\r
+                               mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+                       }                       \r
+                       mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
+                       mv.visitInsn(DUP);\r
+                       mv.visitLdcInsn("Illegal field index");\r
+                       mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
+                       mv.visitInsn(ATHROW);\r
+\r
+                       mv.visitLabel(endLabel);\r
+                       mv.visitLocalVariable("this", "L"+bindingClassName+";", null, l0, endLabel, 0);\r
+                       mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);\r
+                       mv.visitLocalVariable("index", "I", null, l0, endLabel, 2);\r
+                       mv.visitLocalVariable("value", "Ljava/lang/Object;", null, l0, endLabel, 3);\r
+                       //mv.visitLocalVariable("x", "L"+className+";", null, l1, endLabel, 4);\r
+                       mv.visitMaxs(3, 5);\r
+                       mv.visitEnd();                  \r
+               }\r
+               \r
+               // IsImmutable\r
+               {\r
+                       mv = cv.visitMethod(ACC_PUBLIC, "isImmutable", "()Z", null, null);\r
+                       mv.visitCode();\r
+                       Label l0 = new Label();\r
+                       mv.visitLabel(l0);\r
+                       mv.visitInsn(ICONST_0);\r
+                       mv.visitInsn(IRETURN);\r
+                       Label l1 = new Label();\r
+                       mv.visitLabel(l1);\r
+                       mv.visitLocalVariable("this", "L"+className+";", null, l0, l1, 0);\r
+                       mv.visitMaxs(1, 1);\r
+                       mv.visitEnd();\r
+               }\r
+\r
+               // IsInstance\r
+               {\r
+                       mv = cv.visitMethod(ACC_PUBLIC, "isInstance", "(Ljava/lang/Object;)Z", null, null);\r
+                       mv.visitCode();\r
+                       Label l0 = new Label();\r
+                       mv.visitLabel(l0);\r
+                       mv.visitVarInsn(ALOAD, 1);\r
+                       mv.visitTypeInsn(INSTANCEOF, className);\r
+                       mv.visitInsn(IRETURN);\r
+                       Label l1 = new Label();\r
+                       mv.visitLabel(l1);\r
+                       mv.visitLocalVariable("this", "L"+className+";", null, l0, l1, 0);\r
+                       mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l1, 1);\r
+                       mv.visitMaxs(1, 2);\r
+                       mv.visitEnd();\r
+               }\r
+\r
+               // SetComponents\r
+               {                       \r
+                       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
+                       mv.visitCode();\r
+                       Label l0 = new Label();\r
+                       mv.visitLabel(l0);\r
+                       mv.visitVarInsn(ALOAD, 1);\r
+                       mv.visitTypeInsn(CHECKCAST, className);\r
+                       mv.visitVarInsn(ASTORE, 3);\r
+                       Label firstLabel = l0;\r
+                       \r
+                       for (int i=0; i<count; i++) {\r
+                               Label label = new Label();\r
+                               if (firstLabel==l0) firstLabel = label;\r
+                               Field field = ci.fields[i];\r
+                               String fieldName = field.getName();\r
+                               Class<?> fieldClass = ci.fields[i].getType();\r
+                               Class<?> boxClass = getBoxClass(fieldClass);\r
+                               String typeDescriptor = toTypeDescriptor( fieldClass );\r
+                               String boxTypeDescriptor = toTypeDescriptor( boxClass );\r
+\r
+                               Method setter = ci.setters[i];\r
+                               Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;\r
+                               boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;\r
+                               \r
+                               mv.visitLabel(label);\r
+                               mv.visitVarInsn(ALOAD, 3);\r
+                               mv.visitVarInsn(ALOAD, 2);\r
+                               if (i<6) {\r
+                                       mv.visitInsn(ICONST_0 + i);\r
+                               } else {\r
+                                       mv.visitIntInsn(BIPUSH, i);                                             \r
+                               }\r
+                               mv.visitInsn(AALOAD);\r
+                               mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));\r
+                                                       \r
+                               if (useSetter) {\r
+                                       unbox(mv, setterClass);\r
+                                       mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");\r
+                               } else {\r
+                                       unbox(mv, fieldClass);\r
+                                       mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);\r
+                               }\r
+                               \r
+                       }\r
+                       Label l17 = new Label();\r
+                       mv.visitLabel(l17);\r
+                       mv.visitInsn(RETURN);\r
+                       Label endLabel = new Label();\r
+                       mv.visitLabel(endLabel);\r
+                       mv.visitLocalVariable("this", "L"+className+";", null, l0, endLabel, 0);\r
+                       mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);\r
+                       mv.visitLocalVariable("value", "[Ljava/lang/Object;", null, l0, endLabel, 2);\r
+                       //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, firstLabel, endLabel, 3);\r
+                       mv.visitMaxs(3, 4);\r
+                       mv.visitEnd();\r
+               }\r
+               \r
+               // Add primitive setters\r
+               {\r
+                       addGetSetPrimitive(ci, cv, "Boolean", "Z", bindingClassName);\r
+                       addGetSetPrimitive(ci, cv, "Byte", "B", bindingClassName);\r
+                       addGetSetPrimitive(ci, cv, "Int", "I", bindingClassName);\r
+                       addGetSetPrimitive(ci, cv, "Long", "J", bindingClassName);\r
+                       addGetSetPrimitive(ci, cv, "Float", "F", bindingClassName);\r
+                       addGetSetPrimitive(ci, cv, "Double", "D", bindingClassName);\r
+               }\r
+               \r
+               cv.visitEnd();\r
+               return cw.toByteArray();\r
+       }\r
+       \r
+       private void addGetSetPrimitive(ClassInfo ci, ClassVisitor cv, String setterName, String signature, String bindingClassName)\r
+       {\r
+           String className = ci.clazz.getName().replaceAll("\\.", "/");\r
+           \r
+           Label firstLabel = new Label();\r
+           Label secondLabel = new Label();\r
+           Label errorLabel = new Label();\r
+           Label exitLabel = new Label();\r
+           Label lastLabel = new Label();\r
+           \r
+           boolean oneByte = !signature.equals("J") && !signature.equals("D");\r
+           \r
+           int c = 0;\r
+           for (Field f : ci.fields) {\r
+               if ( toTypeDescriptor(getPrimitiveClass(f.getType())).equals( signature ) ) c++;                                \r
+           }\r
+           \r
+           int[] indices = new int[ c ];\r
+           Label[] caseLabel = new Label[ c ];\r
+\r
+           c = 0;\r
+           for (int i=0; i<ci.fields.length; i++) \r
+           {\r
+               Class<?> fieldClass = ci.fields[i].getType();\r
+               fieldClass = getPrimitiveClass(fieldClass);\r
+               String s = toTypeDescriptor(fieldClass);\r
+               if ( !s.equals( signature ) ) continue;\r
+               \r
+               indices[c] = i;\r
+               caseLabel[c] = new Label();\r
+               c++;\r
+           }\r
+                   \r
+           //////////////////\r
+           /// Setter\r
+           ///\r
+           MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "set"+setterName, "(Ljava/lang/Object;I"+signature+")V", null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+           mv.visitCode();\r
+           mv.visitLabel(firstLabel);\r
+           mv.visitVarInsn(ALOAD, 1);\r
+           mv.visitTypeInsn(CHECKCAST, className);\r
+           mv.visitVarInsn(ASTORE, oneByte?4:5);\r
+\r
+           mv.visitLabel(secondLabel);\r
+           mv.visitVarInsn(ILOAD, 2);\r
+\r
+           // switch\r
+           mv.visitLookupSwitchInsn(errorLabel, indices, caseLabel);\r
+\r
+           // case 1:\r
+           if ( c>0 ) {\r
+                   for (int i=0; i<c; i++) {\r
+                       int index = indices[i];\r
+                   Method setter = ci.setters[index];\r
+                   Field field = ci.fields[index];\r
+                   Class<?> fieldClass = field.getType();\r
+                   Class<?> setterClass = setter!=null?setter.getParameterTypes()[0]:null;\r
+                   boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter!=null;\r
+                   String typeDescriptor = toTypeDescriptor( useSetter ? setterClass : fieldClass );\r
+                       \r
+                   mv.visitLabel(caseLabel[i]);\r
+                   if ( i == 0 ) {\r
+                       mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {className}, 0, null);\r
+                   } else {\r
+                       mv.visitFrame(Opcodes.F_SAME, 0, new Object[] {className}, 0, null);\r
+                   }\r
+                   if ( signature.equals("F") ) {\r
+                           mv.visitVarInsn(ALOAD, 4);\r
+                           mv.visitVarInsn(FLOAD, 3);\r
+                   } else if ( signature.equals("D") ) {\r
+                           mv.visitVarInsn(ALOAD, 5);\r
+                           mv.visitVarInsn(DLOAD, 3);\r
+                   } else if ( signature.equals("J") ) {\r
+                           mv.visitVarInsn(ALOAD, 5);\r
+                           mv.visitVarInsn(LLOAD, 3);\r
+                   } else {\r
+                           mv.visitVarInsn(ALOAD, 4);\r
+                           mv.visitVarInsn(ILOAD, 3);\r
+                   }\r
+                   \r
+                   if ( useSetter ) {\r
+                       boxTo(mv, setterClass);\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "("+typeDescriptor+")V");\r
+                   } else {\r
+                       boxTo(mv, fieldClass);\r
+                       mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);\r
+                   }\r
+                   mv.visitJumpInsn(GOTO, exitLabel);\r
+                   }\r
+           } else {\r
+               mv.visitInsn(POP);              \r
+           }\r
+\r
+           // default: (error)\r
+           /*\r
+           mv.visitLabel(errorLabel);\r
+           mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+           mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
+           mv.visitInsn(DUP);\r
+           mv.visitLdcInsn("Field is not "+setterName);\r
+           mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
+           mv.visitInsn(ATHROW);\r
+           */\r
+           \r
+           // default: setComponent\r
+           mv.visitLabel(errorLabel);\r
+           mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+           mv.visitVarInsn(ALOAD, 0);\r
+           mv.visitVarInsn(ALOAD, 1);\r
+           mv.visitVarInsn(ILOAD, 2);\r
+           mv.visitVarInsn(ALOAD, 0);\r
+           mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");\r
+           mv.visitVarInsn(ILOAD, 2);\r
+           mv.visitInsn(AALOAD);\r
+           if ( signature.equals("F") ) {\r
+               mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/FloatBinding");\r
+                   mv.visitVarInsn(FLOAD, 3);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/FloatBinding", "create", "(F)Ljava/lang/Object;");\r
+           } else if ( signature.equals("D") ) {\r
+               mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/DoubleBinding");\r
+                   mv.visitVarInsn(DLOAD, 3);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/DoubleBinding", "create", "(D)Ljava/lang/Object;");\r
+           } else if ( signature.equals("J") ) {\r
+               mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/LongBinding");\r
+                   mv.visitVarInsn(LLOAD, 3);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/LongBinding", "create", "(J)Ljava/lang/Object;");\r
+           } else if ( signature.equals("Z") ){\r
+               mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/BooleanBinding");\r
+                   mv.visitVarInsn(ILOAD, 3);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/BooleanBinding", "create", "(Z)Ljava/lang/Object;");\r
+           } else if ( signature.equals("I") ){\r
+               mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/IntBinding");\r
+                   mv.visitVarInsn(ILOAD, 3);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/IntBinding", "create", "(I)Ljava/lang/Object;");\r
+           } else if ( signature.equals("B") ){\r
+               mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/ByteBinding");\r
+                   mv.visitVarInsn(ILOAD, 3);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/ByteBinding", "create", "(B)Ljava/lang/Object;");\r
+           }       \r
+           mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponent", "(Ljava/lang/Object;ILjava/lang/Object;)V");\r
+\r
+           // return\r
+           mv.visitLabel(exitLabel);\r
+           mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+           mv.visitInsn(RETURN);\r
+\r
+           // Something at the end\r
+           mv.visitLabel(lastLabel);\r
+//         mv.visitLocalVariable("this", "L"+bindingClassName+";", null, firstLabel, lastLabel, 0);\r
+//         mv.visitLocalVariable("r", "Ljava/lang/Object;", null, firstLabel, lastLabel, 1);\r
+//         mv.visitLocalVariable("index", "I", null, firstLabel, lastLabel, 2);\r
+//         mv.visitLocalVariable("z", signature, null, firstLabel, lastLabel, 3);\r
+//         mv.visitLocalVariable("x", "L"+className+";", null, secondLabel, lastLabel, 4);\r
+           mv.visitMaxs(oneByte?5:6, oneByte?5:6);\r
+           mv.visitEnd();\r
+           \r
+           \r
+           //////////////////\r
+           /// Getter\r
+           ///\r
+           firstLabel = new Label();\r
+           secondLabel = new Label();\r
+           errorLabel = new Label();\r
+           exitLabel = new Label();\r
+           lastLabel = new Label();\r
+           for (int i=0; i<c; i++) caseLabel[i] = new Label();\r
+           mv = cv.visitMethod(ACC_PUBLIC, "get"+setterName, "(Ljava/lang/Object;I)"+signature, null, new String[] { "org/simantics/databoard/binding/error/BindingException" });\r
+           mv.visitCode();\r
+           mv.visitLabel(firstLabel);\r
+           mv.visitVarInsn(ALOAD, 1);\r
+           mv.visitTypeInsn(CHECKCAST, className);\r
+           mv.visitVarInsn(ASTORE, 3);\r
+\r
+           mv.visitLabel(secondLabel);\r
+           mv.visitVarInsn(ILOAD, 2);\r
+\r
+           // switch\r
+           if ( c>0 ) {\r
+                   mv.visitLookupSwitchInsn(errorLabel, indices, caseLabel);\r
+       \r
+                   // case i:\r
+                   for (int i=0; i<c; i++) {\r
+                       int index = indices[i];\r
+                   Method getter = ci.getters[index];\r
+                   Field field = ci.fields[index];\r
+                   Class<?> fieldClass = field.getType();\r
+                   Class<?> getterClass = getter!=null?getter.getReturnType():null;\r
+                   boolean useGetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && getter!=null;\r
+                   String typeDescriptor = toTypeDescriptor( useGetter ? getterClass : fieldClass );\r
+                       \r
+                   mv.visitLabel(caseLabel[i]);\r
+                   if ( i == 0 ) {\r
+                       mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {className}, 0, null);\r
+                   } else {\r
+                       mv.visitFrame(Opcodes.F_SAME, 0, new Object[] {className}, 0, null);\r
+                   }\r
+       \r
+                   mv.visitVarInsn(ALOAD, 3);\r
+                   \r
+                   if ( useGetter ) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, className, getter.getName(), "()"+typeDescriptor);\r
+                       unboxFrom(mv, getterClass);\r
+                   } else {\r
+                       mv.visitFieldInsn(GETFIELD, className, field.getName(), typeDescriptor);\r
+                       unboxFrom(mv, fieldClass);\r
+                   }\r
+                   \r
+                   if ( signature.equals("F") ) {\r
+                           mv.visitInsn(FRETURN);\r
+                   } else if ( signature.equals("D") ) {\r
+                           mv.visitInsn(DRETURN);\r
+                   } else if ( signature.equals("J") ) {\r
+                           mv.visitInsn(LRETURN);\r
+                   } else {\r
+                           mv.visitInsn(IRETURN);\r
+                   }\r
+                   }\r
+           } else {\r
+               mv.visitInsn(POP);              \r
+           }\r
+\r
+           // default: (error)\r
+           /*\r
+           mv.visitLabel(errorLabel);\r
+           mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+           mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");\r
+           mv.visitInsn(DUP);\r
+           mv.visitLdcInsn("Field is not "+setterName);\r
+           mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>", "(Ljava/lang/String;)V");\r
+           mv.visitInsn(ATHROW);\r
+           */\r
+           \r
+           // default:\r
+           mv.visitLabel(errorLabel);\r
+           mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
+           mv.visitVarInsn(ALOAD, 0);\r
+           mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings", "[Lorg/simantics/databoard/binding/Binding;");\r
+           mv.visitVarInsn(ILOAD, 2);\r
+           mv.visitInsn(AALOAD);\r
+           if ( signature.equals("Z") ) {\r
+                   mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/BooleanBinding");\r
+                   mv.visitVarInsn(ALOAD, 0);\r
+                   mv.visitVarInsn(ALOAD, 1);\r
+                   mv.visitVarInsn(ILOAD, 2);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/BooleanBinding", "getValue_", "(Ljava/lang/Object;)Z");\r
+                   mv.visitInsn(IRETURN);\r
+           } else if ( signature.equals("B") ) {\r
+                   mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/ByteBinding");\r
+                   mv.visitVarInsn(ALOAD, 0);\r
+                   mv.visitVarInsn(ALOAD, 1);\r
+                   mv.visitVarInsn(ILOAD, 2);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/ByteBinding", "getValue_", "(Ljava/lang/Object;)B");\r
+                   mv.visitInsn(IRETURN);\r
+           } else if ( signature.equals("I") ) {\r
+                   mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/IntBinding");\r
+                   mv.visitVarInsn(ALOAD, 0);\r
+                   mv.visitVarInsn(ALOAD, 1);\r
+                   mv.visitVarInsn(ILOAD, 2);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/IntBinding", "getValue_", "(Ljava/lang/Object;)I");\r
+                   mv.visitInsn(IRETURN);\r
+           } else if ( signature.equals("J") ) {\r
+                   mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/LongBinding");\r
+                   mv.visitVarInsn(ALOAD, 0);\r
+                   mv.visitVarInsn(ALOAD, 1);\r
+                   mv.visitVarInsn(ILOAD, 2);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/LongBinding", "getValue_", "(Ljava/lang/Object;)J");\r
+                   mv.visitInsn(LRETURN);\r
+           } else if ( signature.equals("F") ) {\r
+                   mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/FloatBinding");\r
+                   mv.visitVarInsn(ALOAD, 0);\r
+                   mv.visitVarInsn(ALOAD, 1);\r
+                   mv.visitVarInsn(ILOAD, 2);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/FloatBinding", "getValue_", "(Ljava/lang/Object;)F");\r
+                   mv.visitInsn(FRETURN);\r
+           } else if ( signature.equals("D") ) {\r
+                   mv.visitTypeInsn(CHECKCAST, "org/simantics/databoard/binding/DoubleBinding");\r
+                   mv.visitVarInsn(ALOAD, 0);\r
+                   mv.visitVarInsn(ALOAD, 1);\r
+                   mv.visitVarInsn(ILOAD, 2);\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;");\r
+                   mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/DoubleBinding", "getValue_", "(Ljava/lang/Object;)D");\r
+                   mv.visitInsn(DRETURN);\r
+           }       \r
+\r
+           // Something at the end\r
+           mv.visitLabel(lastLabel);\r
+//         mv.visitLocalVariable("this", "Lorg/simantics/databoard/binding/reflection/MyBinding;", null, firstLabel, lastLabel, 0);\r
+//         mv.visitLocalVariable("r", "Ljava/lang/Object;", null, firstLabel, lastLabel, 1);\r
+//         mv.visitLocalVariable("index", "I", null, firstLabel, lastLabel, 2);\r
+//         mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, secondLabel, lastLabel, 3);\r
+           mv.visitMaxs(4, 4);\r
+           mv.visitEnd();          \r
+           \r
+       }\r
+\r
+\r
+       public static Label[] createFieldLabels(ClassInfo ci) \r
+       {\r
+               Label caseLabels[] = new Label[ ci.fields.length ];\r
+               for (int i=0; i<ci.fields.length; i++) caseLabels[i] = new Label();\r
+               return caseLabels;\r
+       }\r
+       \r
+       public static String toTypeDescriptor(Class<?> clazz) {\r
+               if (clazz==void.class) return "V";\r
+               if (clazz==boolean.class) return "Z";\r
+               if (clazz==char.class) return "C";\r
+               if (clazz==byte.class) return "B";\r
+               if (clazz==short.class) return "S";\r
+               if (clazz==int.class) return "I";\r
+               if (clazz==float.class) return "F";\r
+               if (clazz==long.class) return "J";\r
+               if (clazz==double.class) return "D";\r
+               if (clazz.isArray()) return clazz.getName().replaceAll("\\.", "/");             \r
+               return "L"+clazz.getName().replaceAll("\\.", "/")+";";\r
+       }\r
+       \r
+       /**\r
+        * Get respective boxed class\r
+        * @param clazz\r
+        * @return box-class\r
+        */\r
+       public static Class<?> getBoxClass(Class<?> clazz) {\r
+               if (clazz==void.class) return null;\r
+               if (clazz==boolean.class) return Boolean.class;\r
+               if (clazz==char.class) return Character.class;\r
+               if (clazz==byte.class) return Byte.class;\r
+               if (clazz==short.class) return Short.class;\r
+               if (clazz==int.class) return Integer.class;\r
+               if (clazz==float.class) return Float.class;\r
+               if (clazz==long.class) return Long.class;\r
+               if (clazz==double.class) return Double.class;\r
+               return clazz;\r
+       }\r
+       \r
+       /**\r
+        * Get respective primitive class\r
+        * @param clazz\r
+        * @return primitive-class\r
+        */\r
+       public static Class<?> getPrimitiveClass(Class<?> clazz) {\r
+           if (clazz==Boolean.class) return boolean.class;\r
+           if (clazz==Character.class) return char.class;\r
+           if (clazz==Byte.class) return byte.class;\r
+           if (clazz==Short.class) return short.class;\r
+           if (clazz==Integer.class) return int.class;\r
+           if (clazz==Float.class) return float.class;\r
+           if (clazz==Long.class) return long.class;\r
+           if (clazz==Double.class) return double.class;\r
+           return clazz;\r
+       }          \r
+       \r
+       public static boolean isPrimitive(Class<?> clazz) {\r
+               return clazz==boolean.class || clazz==char.class || clazz==byte.class ||\r
+                               clazz==short.class || clazz==int.class || clazz==float.class ||\r
+                               clazz==long.class || clazz==double.class;\r
+       }\r
+       \r
+       public static void unbox(MethodVisitor mv, Class<?> clazz) {\r
+               if (clazz==boolean.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");\r
+               } else if (clazz==char.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); // C?\r
+               } else if (clazz==byte.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");\r
+               } else if (clazz==short.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");\r
+               } else if (clazz==int.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");\r
+               } else if (clazz==float.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");\r
+               } else if (clazz==long.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");\r
+               } else if (clazz==double.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");\r
+               }               \r
+       }\r
+\r
+       public static void box(MethodVisitor mv, Class<?> clazz) {\r
+               if (clazz==boolean.class) {\r
+                       mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");                     \r
+               } else if (clazz==char.class) {\r
+                       mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");                         \r
+               } else if (clazz==byte.class) {\r
+                       mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");                   \r
+               } else if (clazz==short.class) {\r
+                       mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");                         \r
+               } else if (clazz==int.class) {\r
+                       mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");                     \r
+               } else if (clazz==float.class) {\r
+                       mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");                         \r
+               } else if (clazz==long.class) {\r
+                       mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");                   \r
+               } else if (clazz==double.class) {\r
+                       mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");                       \r
+               }               \r
+       }\r
+       \r
+    public static void boxTo(MethodVisitor mv, Class<?> clazz) {\r
+        if (clazz==Boolean.class) {\r
+            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");         \r
+        } else if (clazz==Character.class) {\r
+            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");             \r
+        } else if (clazz==Byte.class) {\r
+            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");           \r
+        } else if (clazz==Short.class) {\r
+            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");             \r
+        } else if (clazz==Integer.class) {\r
+            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");             \r
+        } else if (clazz==Float.class) {\r
+            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");             \r
+        } else if (clazz==Long.class) {\r
+            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");           \r
+        } else if (clazz==Double.class) {\r
+            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");           \r
+        }       \r
+    }\r
+    \r
+    public static void unboxFrom(MethodVisitor mv, Class<?> clazz) {\r
+               if (clazz==Boolean.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");\r
+               } else if (clazz==Character.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); // C?\r
+               } else if (clazz==Byte.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");\r
+               } else if (clazz==Short.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");\r
+               } else if (clazz==Integer.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");\r
+               } else if (clazz==Float.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");\r
+               } else if (clazz==Long.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");\r
+               } else if (clazz==Double.class) {\r
+                       mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");\r
+               }               \r
+    }  \r
+    \r
+       \r
+       public static String toClassCanonicalName(Class<?> clazz)\r
+       {\r
+               return clazz.getName().replaceAll("\\.", "/");\r
+       }\r
+\r
+       \r
+       \r
+}\r