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