private void createConstructor()

in lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/BytecodeMarshallerGenerator.java [173:300]


    private void createConstructor( ClassWriter cw, String className, List<PropertyDescriptor> propertyDescriptors )
    {
        MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, "<init>", MARSHALLER_CONSTRUCTOR_SIGNATURE, null, null );
        mv.visitCode();

        // Load this
        mv.visitVarInsn( ALOAD, 0 );

        // Load first parameter type (Class)
        mv.visitVarInsn( ALOAD, 1 );

        // Load second parameter type (Map)
        mv.visitVarInsn( ALOAD, 2 );

        // Load third parameter type (ClassDescriptorAwaySerializer)
        mv.visitVarInsn( ALOAD, 3 );

        // Load fourth parameter type (ObjenesisSerializer)
        mv.visitVarInsn( ALOAD, 4 );

        // Call super(Class, Map)
        mv.visitMethodInsn( INVOKESPECIAL, SUPER_CLASS_INTERNAL_TYPE, "<init>", MARSHALLER_SUPER_CONSTRUCTOR_SIGNATURE );

        // Fill fields with marshallers
        for ( int i = 0; i < propertyDescriptors.size(); i++ )
        {
            PropertyDescriptor propertyDescriptor = propertyDescriptors.get( i );
            String fieldName = toFinalFieldName( "marshaller", propertyDescriptor );
            mv.visitVarInsn( ALOAD, 0 );
            mv.visitVarInsn( ALOAD, 0 );

            // Load property type
            mv.visitVarInsn( ALOAD, 5 );
            mv.visitIntInsn( BIPUSH, i );
            mv.visitMethodInsn( INVOKEINTERFACE, LIST_CLASS_INTERNAL_TYPE, "get", "(I)Ljava/lang/Object;" );

            // Store PropertyDescriptor
            mv.visitTypeInsn( CHECKCAST, PROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE );
            mv.visitFieldInsn( PUTFIELD, className, toFinalFieldName( "descriptor", propertyDescriptor ),
                               PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );

            if ( propertyDescriptor.getType().isArray()
                && !propertyDescriptor.getType().getComponentType().isPrimitive() )
            {
                Label labelNonNull = new Label();

                // Get type from PropertyAccessor
                mv.visitVarInsn( ALOAD, 0 );
                mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "descriptor", propertyDescriptor ),
                                   PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
                mv.visitMethodInsn( INVOKEINTERFACE, PROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE, "getType",
                                    "()Ljava/lang/Class;" );

                // Get array component type
                mv.visitMethodInsn( INVOKEVIRTUAL, CLASS_CLASS_INTERNAL_TYPE, "getComponentType",
                                    CLASS_GET_COMPONENT_TYPE );
                mv.visitVarInsn( ASTORE, 9 );

                // Generate cheating PropertyDescriptor for component type
                mv.visitVarInsn( ALOAD, 0 );
                mv.visitTypeInsn( NEW, CHEATINGPROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE );
                mv.visitInsn( DUP );
                mv.visitLdcInsn( propertyDescriptor.getPropertyName() + "Element" );
                mv.visitVarInsn( ALOAD, 9 );
                mv.visitInsn( ACONST_NULL );
                mv.visitMethodInsn( INVOKESPECIAL, CHEATINGPROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE, "<init>",
                                    CHEATINGPROPERTYDESCRIPTOR_CONSTRUCTOR );
                mv.visitFieldInsn( PUTFIELD, className, toFinalFieldName( "component", propertyDescriptor ),
                                   CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );

                // Search marshaller by using interal ones
                mv.visitVarInsn( ALOAD, 6 );
                mv.visitVarInsn( ALOAD, 9 );
                mv.visitInsn( ACONST_NULL );
                mv.visitMethodInsn( INVOKEINTERFACE, MARSHALLERSTRATEGY_CLASS_INTERNAL_TYPE, "getMarshaller",
                                    MARSHALLERSTRATEGY_GET_MARSHALLER_SIGNATURE );
                mv.visitVarInsn( ASTORE, 8 );
                mv.visitVarInsn( ALOAD, 8 );

                // Search marshaller for property type
                mv.visitJumpInsn( IFNONNULL, labelNonNull );
                mv.visitVarInsn( ALOAD, 0 );
                mv.visitVarInsn( ALOAD, 0 );
                mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "component", propertyDescriptor ),
                                   CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
                mv.visitMethodInsn( INVOKEVIRTUAL, SUPER_CLASS_INTERNAL_TYPE, "findMarshaller",
                                    MARSHALLER_FIND_MARSHALLER_SIGNATURE );
                mv.visitVarInsn( ASTORE, 8 );

                // Save marshaller to field
                mv.visitLabel( labelNonNull );
                mv.visitVarInsn( ALOAD, 0 );
                mv.visitVarInsn( ALOAD, 8 );
                mv.visitFieldInsn( PUTFIELD, className, toFinalFieldName( "marshaller", propertyDescriptor ),
                                   MARSHALLER_CLASS_DESCRIPTOR );
            }
            else
            {
                // Check if marshaller is defined
                mv.visitVarInsn( ALOAD, 0 );
                mv.visitVarInsn( ALOAD, 0 );
                mv.visitVarInsn( ALOAD, 0 );
                mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "descriptor", propertyDescriptor ),
                                   PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
                mv.visitMethodInsn( INVOKEVIRTUAL, SUPER_CLASS_INTERNAL_TYPE, "findMarshaller",
                                    MARSHALLER_FIND_MARSHALLER_SIGNATURE );
                mv.visitFieldInsn( PUTFIELD, className, fieldName, MARSHALLER_CLASS_DESCRIPTOR );
            }

            // Load this to method stack
            mv.visitVarInsn( ALOAD, 0 );
            mv.visitInsn( DUP );

            // Load property accessor
            mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "descriptor", propertyDescriptor ),
                               PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
            mv.visitMethodInsn( INVOKEINTERFACE, PROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE, "getPropertyAccessor",
                                PROPERTY_DESCRIPTOR_GET_PROPERTYACCESSOR_SIGNATURE );

            // Save PropertyAccessor to field
            mv.visitFieldInsn( PUTFIELD, className, toFinalFieldName( "accessor", propertyDescriptor ),
                               PROPERTYACCESSOR_CLASS_DESCRIPTOR );
        }

        mv.visitInsn( RETURN );
        mv.visitMaxs( -1, 12 );
        mv.visitEnd();
    }