private ClassDefinition createNodeClass()

in modules/configuration/src/main/java/org/apache/ignite/internal/configuration/asm/InnerNodeAsmGenerator.java [280:457]


    private ClassDefinition createNodeClass() {
        SchemaClassesInfo schemaClassInfo = cgen.schemaInfo(schemaClass);

        // Node class definition.
        innerNodeClassDef = new ClassDefinition(
                EnumSet.of(PUBLIC, FINAL),
                internalName(schemaClassInfo.nodeClassName),
                type(InnerNode.class),
                nodeClassInterfaces(schemaClass, internalExtensions)
        );

        // Spec fields.
        Map<Class<?>, FieldDefinition> specFields = new HashMap<>();

        int i = 0;

        for (Class<?> clazz : concat(List.of(schemaClass), internalExtensions, polymorphicExtensions)) {
            specFields.put(clazz, innerNodeClassDef.declareField(EnumSet.of(PRIVATE, FINAL), "_spec" + i++, clazz));
        }

        // Define the rest of the fields.
        Map<String, FieldDefinition> fieldDefs = new HashMap<>();

        // To store the id of the polymorphic configuration instance.
        FieldDefinition polymorphicTypeIdFieldDef = null;

        // Field with @InjectedName.
        FieldDefinition injectedNameFieldDef = null;

        for (Field schemaField : concat(schemaFields, internalFields, polymorphicFields)) {
            FieldDefinition fieldDef = addInnerNodeField(schemaField);

            fieldDefs.put(fieldDef.getName(), fieldDef);

            if (isPolymorphicId(schemaField)) {
                polymorphicTypeIdFieldDef = fieldDef;
            } else if (isInjectedName(schemaField)) {
                injectedNameFieldDef = fieldDef;
            }
        }

        MethodDefinition classInitializer = innerNodeClassDef.getClassInitializer();
        fieldToFieldDefinitionMap.forEach((k, v) -> {
            // Get declared field.
            BytecodeExpression getDeclaredFieldExp = constantClass(k.getDeclaringClass())
                    .invoke(GET_DECLARED_FIELD_MTD, constantString(k.getName()));
            classInitializer.getBody().append(BytecodeExpressions.setStatic(v, getDeclaredFieldExp));
        });

        // org.apache.ignite.internal.configuration.tree.InnerNode#schemaType
        addNodeSchemaTypeMethod(polymorphicTypeIdFieldDef);

        FieldDefinition internalSchemaTypesFieldDef = null;

        if (!internalExtensions.isEmpty()) {
            internalSchemaTypesFieldDef = innerNodeClassDef.declareField(
                    EnumSet.of(PRIVATE, FINAL),
                    "_" + INTERNAL_SCHEMA_TYPES_MTD.getName(),
                    Class[].class
            );
        }

        // Constructor.
        addNodeConstructor(
                specFields,
                fieldDefs,
                internalSchemaTypesFieldDef
        );

        // Add view method for internal id.
        if (internalIdField != null) {
            addNodeInternalIdMethod();
        }

        // VIEW and CHANGE methods.
        for (Field schemaField : concat(schemaFields, internalFields)) {
            String fieldName = schemaField.getName();

            FieldDefinition fieldDef = fieldDefs.get(fieldName);

            addNodeViewMethod(
                    innerNodeClassDef,
                    schemaField,
                    viewMtd -> getThisFieldCode(viewMtd, fieldDef),
                    null
            );

            // Read only.
            if (isPolymorphicId(schemaField) || isInjectedName(schemaField)) {
                continue;
            }

            // Add change methods.
            List<MethodDefinition> changeMethods = addNodeChangeMethod(
                    innerNodeClassDef,
                    schemaField,
                    changeMtd -> getThisFieldCode(changeMtd, fieldDef),
                    (changeMtd, newValue) -> setThisFieldCode(changeMtd, newValue, fieldDef),
                    null
            );

            // Only first element requires a bridge. Please refer to "addNodeChangeMethod" for explanation.
            addNodeChangeBridgeMethod(innerNodeClassDef, changeClassName(schemaField.getDeclaringClass()), changeMethods.get(0));
        }

        Map<Class<?>, List<Field>> polymorphicFieldsByExtension = Map.of();

        MethodDefinition changePolymorphicTypeIdMtd = null;

        if (!polymorphicExtensions.isEmpty()) {
            assert polymorphicTypeIdFieldDef != null : schemaClass.getName();

            addNodeSpecificNodeMethod(polymorphicTypeIdFieldDef);

            changePolymorphicTypeIdMtd = addNodeChangePolymorphicTypeIdMethod(fieldDefs, polymorphicTypeIdFieldDef);

            addNodeConvertMethods(changePolymorphicTypeIdMtd);

            polymorphicFieldsByExtension = new LinkedHashMap<>();

            for (Class<?> polymorphicExtension : polymorphicExtensions) {
                polymorphicFieldsByExtension.put(
                        polymorphicExtension,
                        polymorphicFields.stream()
                                .filter(f -> polymorphicExtension.equals(f.getDeclaringClass()))
                                .collect(toList())
                );
            }
        }

        // traverseChildren
        addNodeTraverseChildrenMethod(
                fieldDefs,
                polymorphicFieldsByExtension,
                polymorphicTypeIdFieldDef
        );

        // traverseChild
        addNodeTraverseChildMethod(
                fieldDefs,
                polymorphicFieldsByExtension,
                polymorphicTypeIdFieldDef
        );

        // construct
        addNodeConstructMethod(
                fieldDefs,
                polymorphicFieldsByExtension,
                polymorphicTypeIdFieldDef,
                changePolymorphicTypeIdMtd
        );

        // constructDefault
        addNodeConstructDefaultMethod(
                specFields,
                fieldDefs,
                polymorphicFieldsByExtension,
                polymorphicTypeIdFieldDef
        );

        if (injectedNameFieldDef != null) {
            addInjectedNameFieldMethods(injectedNameFieldDef);
        }

        if (polymorphicTypeIdFieldDef != null) {
            addIsPolymorphicMethod();
        }

        if (internalSchemaTypesFieldDef != null) {
            addInternalSchemaTypesMethod(internalSchemaTypesFieldDef);
        }

        if (schemaClass.getSuperclass().isAnnotationPresent(AbstractConfiguration.class)) {
            addIsExtendAbstractConfigurationMethod();
        }

        return innerNodeClassDef;
    }