]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/classfactory/AsmTypeClassFactory.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / classfactory / AsmTypeClassFactory.java
index d37e38afdeb9d98bbbfacca039db005f69bcced3..88fa01f8051f3e2acb744e2069be9c33e136a2b4 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.classfactory;\r
-\r
-import java.lang.annotation.Annotation;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-import java.util.regex.Matcher;\r
-import java.util.regex.Pattern;\r
-\r
-import org.objectweb.asm.AnnotationVisitor;\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.annotations.Arguments;\r
-import org.simantics.databoard.annotations.Identifier;\r
-import org.simantics.databoard.annotations.Length;\r
-import org.simantics.databoard.annotations.MIMEType;\r
-import org.simantics.databoard.annotations.Name;\r
-import org.simantics.databoard.annotations.Optional;\r
-import org.simantics.databoard.annotations.Range;\r
-import org.simantics.databoard.annotations.Referable;\r
-import org.simantics.databoard.annotations.Union;\r
-import org.simantics.databoard.annotations.Unit;\r
-import org.simantics.databoard.binding.error.BindingConstructionException;\r
-import org.simantics.databoard.binding.reflection.AsmBindingClassLoader;\r
-import org.simantics.databoard.binding.reflection.BindingRequest;\r
-import org.simantics.databoard.type.Component;\r
-import org.simantics.databoard.type.Datatype;\r
-import org.simantics.databoard.type.OptionalType;\r
-import org.simantics.databoard.type.RecordType;\r
-import org.simantics.databoard.type.UnionType;\r
-import org.simantics.databoard.util.Bean;\r
-\r
-/**\r
- * This class loader constructs record-like classes of RecordTypes, and\r
- * Enums / other classes of UnionTypes.\r
- */\r
-public class AsmTypeClassFactory extends ClassLoader implements Opcodes, TypeClassSubFactory {\r
-       \r
-       // if true, the record classes are Beans.\r
-       boolean makeBean = true;\r
-       TypeClassFactory classFactory;\r
-       \r
-       Map<String, Datatype> signatureCache = new HashMap<String, Datatype>();\r
-       \r
-       public AsmTypeClassFactory(TypeClassFactory classFactory) {\r
-               super( AsmTypeClassFactory.class.getClassLoader() );\r
-               this.classFactory = classFactory;\r
-       }\r
-\r
-       /**\r
-        * If true, the manufactured classes inherit Bean.\r
-        * @param makeBean\r
-        */\r
-       public void setBeanMaker(boolean makeBean) {\r
-               this.makeBean = makeBean;\r
-       }\r
-\r
-       @Override\r
-       public BindingRequest construct(TypeClassFactory mainFactory, Datatype type) \r
-       throws BindingConstructionException\r
-       {                                               \r
-               if ( type instanceof RecordType ) {\r
-                       RecordType rt = (RecordType) type;\r
-                       \r
-                       SignatureVisitor sv = new SignatureVisitor();\r
-                       type.accept( sv, null );\r
-                       String sig = sv.sb.toString()+"_"+Integer.toHexString( sv.hashcode );\r
-                       \r
-                       String className = "org.simantics.databoard.RecordType_"+sig;\r
-                       String classSig = "Lorg/simantics/databoard/RecordType_"+sig+";";\r
-                       BindingRequest br = new BindingRequest(this, className, classSig, classSig);\r
-                       signatureCache.put(className, rt);\r
-                       return br;\r
-               }\r
-               \r
-               if ( type instanceof UnionType ) {\r
-                       UnionType ut = (UnionType) type;\r
-                       SignatureVisitor sv = new SignatureVisitor();\r
-                       type.accept( sv, null );\r
-                       String sig = sv.sb.toString()+"_"+Integer.toHexString( sv.hashcode );\r
-                       if (ut.isEnumeration()) {\r
-                               String className = "org.simantics.databoard.EnumType_"+sig;\r
-                               String classSig = "Lorg/simantics/databoard/EnumType_"+sig+";";\r
-                               BindingRequest br = new BindingRequest(this, className, classSig, classSig);\r
-                               signatureCache.put(className, ut);\r
-                               return br;\r
-                       } else {\r
-                               String className = "org.simantics.databoard.UnionType_"+sig;\r
-                               String classSig = "Lorg/simantics/databoard/UnionType_"+sig+";";\r
-                               BindingRequest br = new BindingRequest(this, className, classSig, classSig);\r
-                               signatureCache.put(className, ut);\r
-                               return br;\r
-                       }               \r
-               }\r
-               \r
-               return null;\r
-       }\r
-\r
-       @Override\r
-       protected synchronized Class<?> findClass(String className)\r
-       throws ClassNotFoundException \r
-       {\r
-               Datatype type = signatureCache.get(className);\r
-               if ( type == null ) {\r
-                       BindingRequest br = classFactory.getRepository().getRequest(className);\r
-                       if (br!=null && br.getClazz()!=null) return br.getClazz();\r
-                       return Class.forName(className);\r
-               }\r
-\r
-               try {\r
-                       if ( type instanceof RecordType ) {\r
-                               RecordType rt = (RecordType) type;\r
-                               return createRecordClass( rt );\r
-                       }\r
-                       \r
-                       if ( type instanceof UnionType ) {\r
-                               UnionType ut = (UnionType) type;\r
-                               if (ut.isEnumeration()) {\r
-                                       return createEnumClass( ut );\r
-                               } else {\r
-                                       return createUnionClass( ut );\r
-                               }               \r
-                       }\r
-                       throw new ClassNotFoundException(className);\r
-                       \r
-               } catch ( BindingConstructionException bce ) {\r
-                       throw new ClassNotFoundException(className, bce);\r
-               }\r
-       }\r
-       \r
-       \r
-       public Class<?> createRecordClass( RecordType type ) throws BindingConstructionException\r
-       {\r
-               ClassWriter cw = new ClassWriter(0);\r
-               AnnotationVisitor av0;\r
-\r
-               // Create class name\r
-               SignatureVisitor sv = new SignatureVisitor();\r
-               type.accept( sv, null );\r
-               String sig = sv.sb.toString()+"_"+Integer.toHexString( sv.hashcode );\r
-               \r
-               String hash = Integer.toHexString( type.hashCode() );\r
-               String className = "org.simantics.databoard.RecordType_"+sig;\r
-               String classSig = "org/simantics/databoard/RecordType_"+sig;\r
-               Class<?> superClass = makeBean ? Bean.class : Object.class;\r
-               String superType = AsmBindingClassLoader.toClassCanonicalName( superClass );\r
-               \r
-               cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, classSig, null, superType, null);\r
-               \r
-               if ( type.isReferable() ) {\r
-                       av0 = cw.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Referable.class) , true);\r
-                       av0.visitEnd();                 \r
-               }\r
-\r
-               for (int i=0; i<type.getComponentCount(); i++)\r
-               {\r
-                       Component c = type.getComponent(i);\r
-                       Datatype fieldType = c.type;\r
-                       boolean isOptional = fieldType instanceof OptionalType;\r
-                       boolean isIdentifier = type.isIdentifier(i);\r
-                       if ( isOptional ) {\r
-                               fieldType = ((OptionalType) fieldType).componentType;\r
-                       }\r
-//                     boolean isArray = fieldType instanceof ArrayType;\r
-//                     if ( isArray ) {\r
-//                             fieldType = ((ArrayType) fieldType).componentType;\r
-//                     }\r
-                       String fieldName = toJavaFieldName( c.name );\r
-                       BindingRequest br = classFactory.getClass( fieldType );\r
-                       \r
-                       \r
-                       FieldVisitor fv = cw.visitField(\r
-                                       ACC_PUBLIC, \r
-                                       fieldName, \r
-                                       br.signature,\r
-                                       br.descriptor.equals(br.signature)?null:br.descriptor, \r
-                                       null);\r
-                       \r
-                       // Visit annotations\r
-                       if ( br.annotations!=null && br.annotations.length>0 ) {\r
-                               for (Annotation a : br.annotations) {\r
-                                       \r
-                                       if ( a instanceof Arguments ) {\r
-                                               Arguments arg = (Arguments) a;\r
-                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Arguments.class) , true);\r
-                                               AnnotationVisitor av1 = av0.visitArray("value");\r
-                                               for ( Class<?> clzz : arg.value() ) {\r
-                                                       av1.visit(null, Type.getType( AsmBindingClassLoader.toTypeDescriptor( clzz ) ));\r
-                                               }\r
-                                               av1.visitEnd();\r
-                                               av0.visitEnd();\r
-                                       }\r
-                                       \r
-                                       isIdentifier |= a instanceof Identifier;\r
-                                       \r
-                                       if ( a instanceof Length ) {\r
-                                               Length arg = (Length) a;\r
-                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Length.class) , true);\r
-                                               AnnotationVisitor av1 = av0.visitArray("value");\r
-                                               for ( String s : arg.value()) av1.visit(null, s);\r
-                                               av1.visitEnd();\r
-                                               av0.visitEnd();\r
-                                       }\r
-                                       \r
-                                       if ( a instanceof MIMEType ) {\r
-                                               MIMEType arg = (MIMEType) a;\r
-                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(MIMEType.class), true);\r
-                                               av0.visit("value", arg.value());\r
-                                               av0.visitEnd();\r
-                                       }\r
-                                       \r
-                                       if ( a instanceof Name ) {\r
-                                               Name arg = (Name) a;\r
-                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Name.class), true);\r
-                                               av0.visit("value", arg.value());\r
-                                               av0.visitEnd();\r
-                                       }\r
-                                       \r
-                                       isOptional |= a instanceof Optional;\r
-\r
-                                       if ( a instanceof org.simantics.databoard.annotations.Pattern ) {\r
-                                               org.simantics.databoard.annotations.Pattern arg = (org.simantics.databoard.annotations.Pattern) a;\r
-                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(org.simantics.databoard.annotations.Pattern.class), true);\r
-                                               av0.visit("value", arg.value());\r
-                                               av0.visitEnd();\r
-                                       }\r
-                                       \r
-                                       if ( a instanceof Range ) {\r
-                                               Range arg = (Range) a;\r
-                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Range.class), true);\r
-                                               av0.visit("value", arg.value());\r
-                                               av0.visitEnd();\r
-                                       }\r
-                                       \r
-                                       if ( a instanceof Unit ) {\r
-                                               Unit arg = (Unit) a;\r
-                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Unit.class), true);                                            \r
-                                               av0.visit("value", arg.value());\r
-                                               av0.visitEnd();\r
-                                       }\r
-                               }\r
-                       }\r
-                       \r
-                       if ( isIdentifier ) {\r
-                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Identifier.class), true);\r
-                               av0.visitEnd();\r
-                       } \r
-                       if ( isOptional ) {\r
-                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Optional.class), true);\r
-                               av0.visitEnd();\r
-                       } \r
-                       \r
-                       fv.visitEnd();                  \r
-               }\r
-               \r
-               // Constructor\r
-               {\r
-                       MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);\r
-                       mv.visitCode();\r
-                       Label l0 = new Label();\r
-                       \r
-                       // super()\r
-                       if (!makeBean) \r
-                       {\r
-                               mv.visitLabel(l0);\r
-                               mv.visitLineNumber(20, l0);\r
-                               mv.visitVarInsn(ALOAD, 0);\r
-                               mv.visitMethodInsn(INVOKESPECIAL, superType, "<init>", "()V");\r
-                       } else {                                        \r
-                               // super( getStaticBinding() )\r
-                               mv.visitLabel(l0);\r
-                               mv.visitVarInsn(ALOAD, 0);\r
-                               mv.visitMethodInsn(INVOKESTATIC, classSig, "getStaticBinding", "()Lorg/simantics/databoard/binding/Binding;");\r
-                               mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/util/Bean", "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");\r
-                       }\r
-                       \r
-                       mv.visitInsn(RETURN);                                           \r
-                       Label l1 = new Label();\r
-                       mv.visitLabel(l1);\r
-                       mv.visitLocalVariable("this", "L"+classSig+";", null, l0, l1, 0);\r
-                       if (!makeBean) {\r
-                               mv.visitMaxs(1, 1);\r
-                       } else {\r
-                               mv.visitMaxs(2, 1);\r
-                       }\r
-                       mv.visitEnd();\r
-               }\r
-\r
-               // BINDING\r
-               {\r
-                       FieldVisitor fv = cw.visitField(ACC_STATIC, "BINDING", "Lorg/simantics/databoard/binding/Binding;", null, null);\r
-                       fv.visitEnd();\r
-                       \r
-                       MethodVisitor mv = cw.visitMethod(ACC_STATIC, "getStaticBinding", "()Lorg/simantics/databoard/binding/Binding;", null, null);\r
-                       mv.visitCode();\r
-                       Label l0 = new Label();\r
-                       mv.visitLabel(l0);\r
-                       mv.visitFieldInsn(GETSTATIC, classSig, "BINDING", "Lorg/simantics/databoard/binding/Binding;");\r
-                       Label l1 = new Label();\r
-                       mv.visitJumpInsn(IFNONNULL, l1);\r
-                       mv.visitLdcInsn(Type.getType("L"+classSig+";"));\r
-                       mv.visitMethodInsn(INVOKESTATIC, "org/simantics/databoard/Bindings", "getBindingUnchecked", "(Ljava/lang/Class;)Lorg/simantics/databoard/binding/Binding;");\r
-                       mv.visitFieldInsn(PUTSTATIC, classSig, "BINDING", "Lorg/simantics/databoard/binding/Binding;");\r
-                       mv.visitLabel(l1);\r
-                       mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\r
-                       mv.visitFieldInsn(GETSTATIC, classSig, "BINDING", "Lorg/simantics/databoard/binding/Binding;");\r
-                       mv.visitInsn(ARETURN);\r
-                       mv.visitMaxs(1, 0);\r
-                       mv.visitEnd();                                          \r
-               }\r
-               \r
-               cw.visitEnd();\r
-               byte[] data = cw.toByteArray();\r
-               Class<?> clazz = defineClass( className, data, 0, data.length );\r
-               BindingRequest br = new BindingRequest(clazz);          \r
-               return clazz;\r
-       }\r
-       \r
-       private static final Pattern validJavaName = Pattern.compile("[a-zA-Z][\\w]*");\r
-       \r
-       private static String toJavaFieldName( String name )\r
-       {\r
-               if ( name.equals("") ) return "_";\r
-               Matcher m = validJavaName.matcher(name);\r
-               if ( m.matches() ) return name;\r
-               StringBuilder sb = new StringBuilder(name.length());\r
-               \r
-               char fc = name.charAt( 0 );\r
-               for (int i=0; i<name.length(); i++) {\r
-                       char c = name.charAt(i);\r
-                       boolean vc;\r
-                       if ( i == 0 ) {\r
-                               vc = (fc>='a'&&fc<'z')||(fc>='A'&&fc<'Z');\r
-                       } else {\r
-                               vc = (c>='a'&&c<'z')||(c>='A'&&c<'Z')||(c=='_')||(c>='0'&&fc<='9');\r
-                       }\r
-                       if ( vc ) sb.append('_'); else sb.append(c);\r
-               }               \r
-               return sb.toString();\r
-       }\r
-       \r
-       public Class<?> createEnumClass( UnionType ut )\r
-       {\r
-               return null;\r
-       }\r
-       \r
-       public Class<?> createUnionClass( UnionType ut ) throws BindingConstructionException\r
-       {\r
-               ClassWriter cw = new ClassWriter(0);\r
-\r
-               // Create class name\r
-               SignatureVisitor sv = new SignatureVisitor();\r
-               ut.accept( sv, null );\r
-               String sig = sv.sb.toString()+"_"+Integer.toHexString( sv.hashcode );\r
-               \r
-               String hash = Integer.toHexString( ut.hashCode() );\r
-               String className = "org.simantics.databoard.UnionType_"+sig;\r
-               String classSig = "org/simantics/databoard/UnionType_"+sig;\r
-               Class<?> superClass = Object.class;\r
-               String superType = AsmBindingClassLoader.toClassCanonicalName( superClass );\r
-               \r
-               cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, classSig, null, superType, null);\r
-               \r
-               AnnotationVisitor av0 = cw.visitAnnotation(AsmBindingClassLoader.toTypeDescriptor(Union.class), true);\r
-               AnnotationVisitor av1 = av0.visitArray("value");\r
-               for (Component c : ut.components) {\r
-                       BindingRequest br = classFactory.getClass(c.type);\r
-                       av1.visit(null, Type.getType(br.descriptor));\r
-               }\r
-               av1.visitEnd();\r
-               av0.visitEnd();\r
-               \r
-               // Constructor\r
-               {\r
-                       MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);\r
-                       mv.visitCode();\r
-                       Label l0 = new Label();\r
-                       mv.visitLabel(l0);\r
-                       mv.visitLineNumber(20, l0);\r
-                       mv.visitVarInsn(ALOAD, 0);\r
-                       mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");\r
-                       mv.visitInsn(RETURN);\r
-                       Label l1 = new Label();\r
-                       mv.visitLabel(l1);\r
-                       mv.visitLocalVariable("this", "L"+classSig+";", null, l0, l1, 0);\r
-                       mv.visitMaxs(1, 1);\r
-                       mv.visitEnd();\r
-               }               \r
-               \r
-               cw.visitEnd();\r
-               byte[] data = cw.toByteArray();\r
-               return defineClass( className, data, 0, data.length );\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.classfactory;
+
+import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.objectweb.asm.AnnotationVisitor;
+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.annotations.Arguments;
+import org.simantics.databoard.annotations.Identifier;
+import org.simantics.databoard.annotations.Length;
+import org.simantics.databoard.annotations.MIMEType;
+import org.simantics.databoard.annotations.Name;
+import org.simantics.databoard.annotations.Optional;
+import org.simantics.databoard.annotations.Range;
+import org.simantics.databoard.annotations.Referable;
+import org.simantics.databoard.annotations.Union;
+import org.simantics.databoard.annotations.Unit;
+import org.simantics.databoard.binding.error.BindingConstructionException;
+import org.simantics.databoard.binding.reflection.AsmBindingClassLoader;
+import org.simantics.databoard.binding.reflection.BindingRequest;
+import org.simantics.databoard.type.Component;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.type.OptionalType;
+import org.simantics.databoard.type.RecordType;
+import org.simantics.databoard.type.UnionType;
+import org.simantics.databoard.util.Bean;
+
+/**
+ * This class loader constructs record-like classes of RecordTypes, and
+ * Enums / other classes of UnionTypes.
+ */
+public class AsmTypeClassFactory extends ClassLoader implements Opcodes, TypeClassSubFactory {
+       
+       // if true, the record classes are Beans.
+       boolean makeBean = true;
+       TypeClassFactory classFactory;
+       
+       Map<String, Datatype> signatureCache = new HashMap<String, Datatype>();
+       
+       public AsmTypeClassFactory(TypeClassFactory classFactory) {
+               super( AsmTypeClassFactory.class.getClassLoader() );
+               this.classFactory = classFactory;
+       }
+
+       /**
+        * If true, the manufactured classes inherit Bean.
+        * @param makeBean
+        */
+       public void setBeanMaker(boolean makeBean) {
+               this.makeBean = makeBean;
+       }
+
+       @Override
+       public BindingRequest construct(TypeClassFactory mainFactory, Datatype type) 
+       throws BindingConstructionException
+       {                                               
+               if ( type instanceof RecordType ) {
+                       RecordType rt = (RecordType) type;
+                       
+                       SignatureVisitor sv = new SignatureVisitor();
+                       type.accept( sv, null );
+                       String sig = sv.sb.toString()+"_"+Integer.toHexString( sv.hashcode );
+                       
+                       String className = "org.simantics.databoard.RecordType_"+sig;
+                       String classSig = "Lorg/simantics/databoard/RecordType_"+sig+";";
+                       BindingRequest br = new BindingRequest(this, className, classSig, classSig);
+                       signatureCache.put(className, rt);
+                       return br;
+               }
+               
+               if ( type instanceof UnionType ) {
+                       UnionType ut = (UnionType) type;
+                       SignatureVisitor sv = new SignatureVisitor();
+                       type.accept( sv, null );
+                       String sig = sv.sb.toString()+"_"+Integer.toHexString( sv.hashcode );
+                       if (ut.isEnumeration()) {
+                               String className = "org.simantics.databoard.EnumType_"+sig;
+                               String classSig = "Lorg/simantics/databoard/EnumType_"+sig+";";
+                               BindingRequest br = new BindingRequest(this, className, classSig, classSig);
+                               signatureCache.put(className, ut);
+                               return br;
+                       } else {
+                               String className = "org.simantics.databoard.UnionType_"+sig;
+                               String classSig = "Lorg/simantics/databoard/UnionType_"+sig+";";
+                               BindingRequest br = new BindingRequest(this, className, classSig, classSig);
+                               signatureCache.put(className, ut);
+                               return br;
+                       }               
+               }
+               
+               return null;
+       }
+
+       @Override
+       protected synchronized Class<?> findClass(String className)
+       throws ClassNotFoundException 
+       {
+               Datatype type = signatureCache.get(className);
+               if ( type == null ) {
+                       BindingRequest br = classFactory.getRepository().getRequest(className);
+                       if (br!=null && br.getClazz()!=null) return br.getClazz();
+                       return Class.forName(className);
+               }
+
+               try {
+                       if ( type instanceof RecordType ) {
+                               RecordType rt = (RecordType) type;
+                               return createRecordClass( rt );
+                       }
+                       
+                       if ( type instanceof UnionType ) {
+                               UnionType ut = (UnionType) type;
+                               if (ut.isEnumeration()) {
+                                       return createEnumClass( ut );
+                               } else {
+                                       return createUnionClass( ut );
+                               }               
+                       }
+                       throw new ClassNotFoundException(className);
+                       
+               } catch ( BindingConstructionException bce ) {
+                       throw new ClassNotFoundException(className, bce);
+               }
+       }
+       
+       
+       public Class<?> createRecordClass( RecordType type ) throws BindingConstructionException
+       {
+               ClassWriter cw = new ClassWriter(0);
+               AnnotationVisitor av0;
+
+               // Create class name
+               SignatureVisitor sv = new SignatureVisitor();
+               type.accept( sv, null );
+               String sig = sv.sb.toString()+"_"+Integer.toHexString( sv.hashcode );
+               
+               String hash = Integer.toHexString( type.hashCode() );
+               String className = "org.simantics.databoard.RecordType_"+sig;
+               String classSig = "org/simantics/databoard/RecordType_"+sig;
+               Class<?> superClass = makeBean ? Bean.class : Object.class;
+               String superType = AsmBindingClassLoader.toClassCanonicalName( superClass );
+               
+               cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, classSig, null, superType, null);
+               
+               if ( type.isReferable() ) {
+                       av0 = cw.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Referable.class) , true);
+                       av0.visitEnd();                 
+               }
+
+               for (int i=0; i<type.getComponentCount(); i++)
+               {
+                       Component c = type.getComponent(i);
+                       Datatype fieldType = c.type;
+                       boolean isOptional = fieldType instanceof OptionalType;
+                       boolean isIdentifier = type.isIdentifier(i);
+                       if ( isOptional ) {
+                               fieldType = ((OptionalType) fieldType).componentType;
+                       }
+//                     boolean isArray = fieldType instanceof ArrayType;
+//                     if ( isArray ) {
+//                             fieldType = ((ArrayType) fieldType).componentType;
+//                     }
+                       String fieldName = toJavaFieldName( c.name );
+                       BindingRequest br = classFactory.getClass( fieldType );
+                       
+                       
+                       FieldVisitor fv = cw.visitField(
+                                       ACC_PUBLIC, 
+                                       fieldName, 
+                                       br.signature,
+                                       br.descriptor.equals(br.signature)?null:br.descriptor, 
+                                       null);
+                       
+                       // Visit annotations
+                       if ( br.annotations!=null && br.annotations.length>0 ) {
+                               for (Annotation a : br.annotations) {
+                                       
+                                       if ( a instanceof Arguments ) {
+                                               Arguments arg = (Arguments) a;
+                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Arguments.class) , true);
+                                               AnnotationVisitor av1 = av0.visitArray("value");
+                                               for ( Class<?> clzz : arg.value() ) {
+                                                       av1.visit(null, Type.getType( AsmBindingClassLoader.toTypeDescriptor( clzz ) ));
+                                               }
+                                               av1.visitEnd();
+                                               av0.visitEnd();
+                                       }
+                                       
+                                       isIdentifier |= a instanceof Identifier;
+                                       
+                                       if ( a instanceof Length ) {
+                                               Length arg = (Length) a;
+                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Length.class) , true);
+                                               AnnotationVisitor av1 = av0.visitArray("value");
+                                               for ( String s : arg.value()) av1.visit(null, s);
+                                               av1.visitEnd();
+                                               av0.visitEnd();
+                                       }
+                                       
+                                       if ( a instanceof MIMEType ) {
+                                               MIMEType arg = (MIMEType) a;
+                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(MIMEType.class), true);
+                                               av0.visit("value", arg.value());
+                                               av0.visitEnd();
+                                       }
+                                       
+                                       if ( a instanceof Name ) {
+                                               Name arg = (Name) a;
+                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Name.class), true);
+                                               av0.visit("value", arg.value());
+                                               av0.visitEnd();
+                                       }
+                                       
+                                       isOptional |= a instanceof Optional;
+
+                                       if ( a instanceof org.simantics.databoard.annotations.Pattern ) {
+                                               org.simantics.databoard.annotations.Pattern arg = (org.simantics.databoard.annotations.Pattern) a;
+                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(org.simantics.databoard.annotations.Pattern.class), true);
+                                               av0.visit("value", arg.value());
+                                               av0.visitEnd();
+                                       }
+                                       
+                                       if ( a instanceof Range ) {
+                                               Range arg = (Range) a;
+                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Range.class), true);
+                                               av0.visit("value", arg.value());
+                                               av0.visitEnd();
+                                       }
+                                       
+                                       if ( a instanceof Unit ) {
+                                               Unit arg = (Unit) a;
+                                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Unit.class), true);                                            
+                                               av0.visit("value", arg.value());
+                                               av0.visitEnd();
+                                       }
+                               }
+                       }
+                       
+                       if ( isIdentifier ) {
+                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Identifier.class), true);
+                               av0.visitEnd();
+                       } 
+                       if ( isOptional ) {
+                               av0 = fv.visitAnnotation( AsmBindingClassLoader.toTypeDescriptor(Optional.class), true);
+                               av0.visitEnd();
+                       } 
+                       
+                       fv.visitEnd();                  
+               }
+               
+               // Constructor
+               {
+                       MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+                       mv.visitCode();
+                       Label l0 = new Label();
+                       
+                       // super()
+                       if (!makeBean) 
+                       {
+                               mv.visitLabel(l0);
+                               mv.visitLineNumber(20, l0);
+                               mv.visitVarInsn(ALOAD, 0);
+                               mv.visitMethodInsn(INVOKESPECIAL, superType, "<init>", "()V");
+                       } else {                                        
+                               // super( getStaticBinding() )
+                               mv.visitLabel(l0);
+                               mv.visitVarInsn(ALOAD, 0);
+                               mv.visitMethodInsn(INVOKESTATIC, classSig, "getStaticBinding", "()Lorg/simantics/databoard/binding/Binding;");
+                               mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/util/Bean", "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");
+                       }
+                       
+                       mv.visitInsn(RETURN);                                           
+                       Label l1 = new Label();
+                       mv.visitLabel(l1);
+                       mv.visitLocalVariable("this", "L"+classSig+";", null, l0, l1, 0);
+                       if (!makeBean) {
+                               mv.visitMaxs(1, 1);
+                       } else {
+                               mv.visitMaxs(2, 1);
+                       }
+                       mv.visitEnd();
+               }
+
+               // BINDING
+               {
+                       FieldVisitor fv = cw.visitField(ACC_STATIC, "BINDING", "Lorg/simantics/databoard/binding/Binding;", null, null);
+                       fv.visitEnd();
+                       
+                       MethodVisitor mv = cw.visitMethod(ACC_STATIC, "getStaticBinding", "()Lorg/simantics/databoard/binding/Binding;", null, null);
+                       mv.visitCode();
+                       Label l0 = new Label();
+                       mv.visitLabel(l0);
+                       mv.visitFieldInsn(GETSTATIC, classSig, "BINDING", "Lorg/simantics/databoard/binding/Binding;");
+                       Label l1 = new Label();
+                       mv.visitJumpInsn(IFNONNULL, l1);
+                       mv.visitLdcInsn(Type.getType("L"+classSig+";"));
+                       mv.visitMethodInsn(INVOKESTATIC, "org/simantics/databoard/Bindings", "getBindingUnchecked", "(Ljava/lang/Class;)Lorg/simantics/databoard/binding/Binding;");
+                       mv.visitFieldInsn(PUTSTATIC, classSig, "BINDING", "Lorg/simantics/databoard/binding/Binding;");
+                       mv.visitLabel(l1);
+                       mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+                       mv.visitFieldInsn(GETSTATIC, classSig, "BINDING", "Lorg/simantics/databoard/binding/Binding;");
+                       mv.visitInsn(ARETURN);
+                       mv.visitMaxs(1, 0);
+                       mv.visitEnd();                                          
+               }
+               
+               cw.visitEnd();
+               byte[] data = cw.toByteArray();
+               Class<?> clazz = defineClass( className, data, 0, data.length );
+               BindingRequest br = new BindingRequest(clazz);          
+               return clazz;
+       }
+       
+       private static final Pattern validJavaName = Pattern.compile("[a-zA-Z][\\w]*");
+       
+       private static String toJavaFieldName( String name )
+       {
+               if ( name.equals("") ) return "_";
+               Matcher m = validJavaName.matcher(name);
+               if ( m.matches() ) return name;
+               StringBuilder sb = new StringBuilder(name.length());
+               
+               char fc = name.charAt( 0 );
+               for (int i=0; i<name.length(); i++) {
+                       char c = name.charAt(i);
+                       boolean vc;
+                       if ( i == 0 ) {
+                               vc = (fc>='a'&&fc<'z')||(fc>='A'&&fc<'Z');
+                       } else {
+                               vc = (c>='a'&&c<'z')||(c>='A'&&c<'Z')||(c=='_')||(c>='0'&&fc<='9');
+                       }
+                       if ( vc ) sb.append('_'); else sb.append(c);
+               }               
+               return sb.toString();
+       }
+       
+       public Class<?> createEnumClass( UnionType ut )
+       {
+               return null;
+       }
+       
+       public Class<?> createUnionClass( UnionType ut ) throws BindingConstructionException
+       {
+               ClassWriter cw = new ClassWriter(0);
+
+               // Create class name
+               SignatureVisitor sv = new SignatureVisitor();
+               ut.accept( sv, null );
+               String sig = sv.sb.toString()+"_"+Integer.toHexString( sv.hashcode );
+               
+               String hash = Integer.toHexString( ut.hashCode() );
+               String className = "org.simantics.databoard.UnionType_"+sig;
+               String classSig = "org/simantics/databoard/UnionType_"+sig;
+               Class<?> superClass = Object.class;
+               String superType = AsmBindingClassLoader.toClassCanonicalName( superClass );
+               
+               cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, classSig, null, superType, null);
+               
+               AnnotationVisitor av0 = cw.visitAnnotation(AsmBindingClassLoader.toTypeDescriptor(Union.class), true);
+               AnnotationVisitor av1 = av0.visitArray("value");
+               for (Component c : ut.components) {
+                       BindingRequest br = classFactory.getClass(c.type);
+                       av1.visit(null, Type.getType(br.descriptor));
+               }
+               av1.visitEnd();
+               av0.visitEnd();
+               
+               // Constructor
+               {
+                       MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+                       mv.visitCode();
+                       Label l0 = new Label();
+                       mv.visitLabel(l0);
+                       mv.visitLineNumber(20, l0);
+                       mv.visitVarInsn(ALOAD, 0);
+                       mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
+                       mv.visitInsn(RETURN);
+                       Label l1 = new Label();
+                       mv.visitLabel(l1);
+                       mv.visitLocalVariable("this", "L"+classSig+";", null, l0, l1, 0);
+                       mv.visitMaxs(1, 1);
+                       mv.visitEnd();
+               }               
+               
+               cw.visitEnd();
+               byte[] data = cw.toByteArray();
+               return defineClass( className, data, 0, data.length );
+       }       
+       
+}