X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Fbinding%2Fclassfactory%2FAsmTypeClassFactory.java;h=88fa01f8051f3e2acb744e2069be9c33e136a2b4;hp=d37e38afdeb9d98bbbfacca039db005f69bcced3;hb=refs%2Fchanges%2F38%2F238%2F2;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/classfactory/AsmTypeClassFactory.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/classfactory/AsmTypeClassFactory.java index d37e38afd..88fa01f80 100644 --- a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/classfactory/AsmTypeClassFactory.java +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/classfactory/AsmTypeClassFactory.java @@ -1,409 +1,409 @@ -/******************************************************************************* - * 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 signatureCache = new HashMap(); - - 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; i0 ) { - 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, "", "()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, "", "()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", "", "(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='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, "", "()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", "", "()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 ); - } - -} +/******************************************************************************* + * 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 signatureCache = new HashMap(); + + 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; i0 ) { + 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, "", "()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, "", "()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", "", "(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='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, "", "()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", "", "()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 ); + } + +}