public PlasticClassImpl()

in plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java [182:319]


    public PlasticClassImpl(ClassNode classNode, ClassNode implementationClassNode, PlasticClassPool pool, InheritanceData parentInheritanceData,
                            StaticContext parentStaticContext, boolean proxy)
    {
        this.classNode = classNode;
        this.pool = pool;
        this.proxy = proxy;
        this.implementationClassNode = implementationClassNode;

        staticContext = parentStaticContext.dupe();

        className = PlasticInternalUtils.toClassName(classNode.name);
        superClassName = PlasticInternalUtils.toClassName(classNode.superName);
        int lastIndexOfDot = className.lastIndexOf('.');

        String packageName = lastIndexOfDot > -1 ? className.substring(0, lastIndexOfDot) : "";

        fieldInstrumentations = new FieldInstrumentations(classNode.superName);

        annotationAccess = new DelegatingAnnotationAccess(pool.createAnnotationAccess(classNode.visibleAnnotations),
                pool.createAnnotationAccess(superClassName));

        this.parentInheritanceData = parentInheritanceData;

        inheritanceData = parentInheritanceData.createChild(packageName);

        for (String interfaceName : classNode.interfaces)
        {
            inheritanceData.addInterface(interfaceName);
        }

        methods = new ArrayList<>(classNode.methods.size());

        String invalidConstructorMessage = invalidConstructorMessage();

        for (MethodNode node : classNode.methods)
        {
            if (node.name.equals(CONSTRUCTOR_NAME))
            {
                if (node.desc.equals(NOTHING_TO_VOID))
                {
                    originalConstructor = node;
                    fieldTransformMethods.add(node);
                } else
                {
                    node.instructions.clear();

                    newBuilder(node).throwException(IllegalStateException.class, invalidConstructorMessage);
                }

                continue;
            }

            /*
             * Static methods are not visible to the main API methods, but they must still be transformed,
             * in case they directly access fields. In addition, track their names to avoid collisions.
             */
            if (Modifier.isStatic(node.access))
            {
                if (isInheritableMethod(node))
                {
                    inheritanceData.addMethod(node.name, node.desc, node.access == 0);
                }

                methodNames.add(node.name);

                fieldTransformMethods.add(node);

                continue;
            }

            if (!Modifier.isAbstract(node.access))
            {
                fieldTransformMethods.add(node);
            }

            PlasticMethodImpl pmi = new PlasticMethodImpl(this, node);

            methods.add(pmi);
            description2method.put(pmi.getDescription(), pmi);

            if (isInheritableMethod(node))
            {
                inheritanceData.addMethod(node.name, node.desc, node.access == 0);
            }

            methodNames.add(node.name);
        }

        methodNames.addAll(parentInheritanceData.methodNames());

        Collections.sort(methods);

        fields = new ArrayList<>(classNode.fields.size());

        for (FieldNode node : classNode.fields)
        {
            fieldNames.add(node.name);

            // Ignore static fields.

            if (Modifier.isStatic(node.access))
                continue;

            // When we instrument the field such that it must be private, we'll get an exception.

            fields.add(new PlasticFieldImpl(this, node));
        }

        Collections.sort(fields);

        // TODO: Make the output class's constructor protected, and create a shim class to instantiate it
        // efficiently (without reflection).
        newConstructor = new MethodNode(ACC_PUBLIC, CONSTRUCTOR_NAME, CONSTRUCTOR_DESC, null, null);
        constructorBuilder = newBuilder(newConstructor);

        // Start by calling the super-class no args constructor

        if (parentInheritanceData.isTransformed())
        {
            // If the parent is transformed, our first step is always to invoke its constructor.

            constructorBuilder.loadThis().loadArgument(0).loadArgument(1);
            constructorBuilder.invokeConstructor(superClassName, StaticContext.class.getName(),
                    InstanceContext.class.getName());
        } else
        {
            // Assumes the base class includes a visible constructor that takes no arguments.
            // TODO: Do a proper check for this case and throw a meaningful exception
            // if not present.

            constructorBuilder.loadThis().invokeConstructor(superClassName);
        }

        // During the transformation, we'll be adding code to the constructor to pull values
        // out of the static or instance context and assign them to fields.

        // Later on, we'll add the RETURN opcode
    }