private void addConfigurationImplConstructor()

in modules/configuration/src/main/java/org/apache/ignite/internal/configuration/asm/ConfigurationImplAsmGenerator.java [328:513]


    private void addConfigurationImplConstructor(
            Map<String, FieldDefinition> fieldDefs,
            @Nullable FieldDefinition internalConfigTypesFieldDef
    ) {
        MethodDefinition ctor = cfgImplClassDef.declareConstructor(
                EnumSet.of(PUBLIC),
                arg("prefix", List.class),
                arg("key", String.class),
                arg("rootKey", RootKey.class),
                arg("changer", DynamicConfigurationChanger.class),
                arg("listenOnly", boolean.class)
        );

        Variable rootKeyVar = ctor.getScope().getVariable("rootKey");
        Variable changerVar = ctor.getScope().getVariable("changer");
        Variable listenOnlyVar = ctor.getScope().getVariable("listenOnly");

        SchemaClassesInfo schemaClassInfo = cgen.schemaInfo(schemaClass);

        Variable thisVar = ctor.getThis();

        BytecodeBlock ctorBody = ctor.getBody()
                .append(thisVar)
                .append(ctor.getScope().getVariable("prefix"))
                .append(ctor.getScope().getVariable("key"))
                .append(rootKeyVar)
                .append(changerVar)
                .append(listenOnlyVar)
                .invokeConstructor(DYNAMIC_CONFIGURATION_CTOR);

        BytecodeExpression thisKeysVar = thisVar.getField("keys", List.class);

        // Wrap object into list to reuse the loop below.
        List<Field> internalIdFieldAsList = internalIdField == null ? emptyList() : List.of(internalIdField);

        int newIdx = 0;
        for (Field schemaField : concat(schemaFields, internalFields, polymorphicFields, internalIdFieldAsList)) {
            String fieldName = schemaField.getName();

            BytecodeExpression newValue;

            if (isValue(schemaField) || isPolymorphicId(schemaField) || isInjectedName(schemaField) || isInternalId(schemaField)) {
                // A field with @InjectedName is special (auxiliary), it is not stored in storages as a regular field, and therefore there
                // is no direct access to it. It is stored in the InnerNode and does not participate in its traversal, so in order to get
                // it we need to get the InnerNode, and only then the value of this field.

                // newValue = new DynamicProperty(this.keys, fieldName, rootKey, changer, listenOnly, readOnly);
                newValue = newInstance(
                        DynamicProperty.class,
                        thisKeysVar,
                        constantString(isInjectedName(schemaField) ? InnerNode.INJECTED_NAME
                                : isInternalId(schemaField) ? InnerNode.INTERNAL_ID : schemaField.getName()),
                        rootKeyVar,
                        changerVar,
                        listenOnlyVar,
                        constantBoolean(isPolymorphicId(schemaField) || isInjectedName(schemaField) || isInternalId(schemaField))
                );
            } else {
                SchemaClassesInfo fieldInfo = cgen.schemaInfo(schemaField.getType());

                ParameterizedType cfgImplParameterizedType = typeFromJavaClassName(fieldInfo.cfgImplClassName);

                if (isConfigValue(schemaField)) {
                    // newValue = new MyConfigurationImpl(super.keys, fieldName, rootKey, changer, listenOnly);
                    newValue = newInstance(
                            cfgImplParameterizedType,
                            thisKeysVar,
                            constantString(fieldName),
                            rootKeyVar,
                            changerVar,
                            listenOnlyVar
                    );
                } else {
                    // We have to create method "$new$<idx>" to reference it in lambda expression. That's the way it
                    // works, it'll invoke constructor with all 5 arguments, not just 2 as in BiFunction.
                    MethodDefinition newMtd = cfgImplClassDef.declareMethod(
                            EnumSet.of(PRIVATE, STATIC, SYNTHETIC),
                            "$new$" + newIdx++,
                            typeFromJavaClassName(fieldInfo.cfgClassName),
                            arg("rootKey", RootKey.class),
                            arg("changer", DynamicConfigurationChanger.class),
                            arg("listenOnly", boolean.class),
                            arg("prefix", List.class),
                            arg("key", String.class)
                    );

                    // newValue = new NamedListConfiguration(this.keys, fieldName, rootKey, changer, listenOnly,
                    //      (p, k) -> new ValueConfigurationImpl(p, k, rootKey, changer, listenOnly),
                    //      (p, c) -> new ValueDirectProxy(p, c),
                    //      new ValueConfigurationImpl(this.keys, "any", rootKey, changer, true)
                    // );
                    newValue = newInstance(
                            NamedListConfiguration.class,
                            thisKeysVar,
                            constantString(fieldName),
                            rootKeyVar,
                            changerVar,
                            listenOnlyVar,
                            invokeDynamic(
                                    LAMBDA_METAFACTORY,
                                    asList(
                                            getMethodType(getType(Object.class), getType(Object.class), getType(Object.class)),
                                            new Handle(
                                                    Opcodes.H_INVOKESTATIC,
                                                    internalName(schemaClassInfo.cfgImplClassName),
                                                    newMtd.getName(),
                                                    newMtd.getMethodDescriptor(),
                                                    false
                                            ),
                                            getMethodType(
                                                    typeFromJavaClassName(fieldInfo.cfgClassName).getAsmType(),
                                                    getType(List.class),
                                                    getType(String.class)
                                            )
                                    ),
                                    "apply",
                                    BiFunction.class,
                                    rootKeyVar,
                                    changerVar,
                                    listenOnlyVar
                            ),
                            newDirectProxyLambda(fieldInfo),
                            newInstance(
                                    cfgImplParameterizedType,
                                    thisKeysVar,
                                    constantString("any"),
                                    rootKeyVar,
                                    changerVar,
                                    constantBoolean(true)
                            ).cast(ConfigurationProperty.class)
                    );

                    newMtd.getBody()
                            .append(newInstance(
                                    cfgImplParameterizedType,
                                    newMtd.getScope().getVariable("prefix"),
                                    newMtd.getScope().getVariable("key"),
                                    newMtd.getScope().getVariable("rootKey"),
                                    newMtd.getScope().getVariable("changer"),
                                    newMtd.getScope().getVariable("listenOnly")
                            ))
                            .retObject();
                }
            }

            FieldDefinition fieldDef = fieldDefs.get(fieldName(schemaField));

            // this.field = newValue;
            ctorBody.append(thisVar.setField(fieldDef, newValue));

            if (!isPolymorphicConfigInstance(schemaField.getDeclaringClass()) && !isInternalId(schemaField)) {
                // add(this.field);
                ctorBody.append(thisVar.invoke(DYNAMIC_CONFIGURATION_ADD_MTD, thisVar.getField(fieldDef)));
            }
        }

        if (internalConfigTypesFieldDef != null) {
            assert !internalExtensions.isEmpty() : cfgImplClassDef;

            // Class[] tmp;
            Variable tmpVar = ctor.getScope().createTempVariable(Class[].class);

            BytecodeBlock initInternalConfigTypesField = new BytecodeBlock();

            // tmp = new Class[size];
            initInternalConfigTypesField.append(tmpVar.set(newArray(type(Class[].class), internalExtensions.size())));

            int i = 0;

            for (Class<?> extension : internalExtensions) {
                // tmp[i] = InternalTableConfiguration.class;
                initInternalConfigTypesField.append(set(
                        tmpVar,
                        constantInt(i++),
                        constantClass(typeFromJavaClassName(configurationClassName(extension)))
                ));
            }

            // this._internalConfigTypes = tmp;
            initInternalConfigTypesField.append(setThisFieldCode(ctor, tmpVar, internalConfigTypesFieldDef));

            ctorBody.append(initInternalConfigTypesField);
        }

        ctorBody.ret();
    }