public TypeSpec generateMessageImpl()

in modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/messages/MessageImplGenerator.java [100:264]


    public TypeSpec generateMessageImpl(MessageClass message, TypeSpec builderInterface) {
        ClassName messageImplClassName = message.implClassName();

        processingEnv.getMessager()
                .printMessage(Diagnostic.Kind.NOTE, "Generating " + messageImplClassName);

        List<ExecutableElement> getters = message.getters();

        var fields = new ArrayList<FieldSpec>(getters.size());
        var methodImpls = new ArrayList<MethodSpec>(getters.size());

        var notNullFieldNames = new HashSet<String>();
        var marshallableFieldNames = new HashSet<String>();

        // create a field and a getter implementation for every getter in the message interface
        for (ExecutableElement getter : getters) {
            TypeMirror getterType = getter.getReturnType();
            TypeName getterReturnType = TypeName.get(getterType);

            String getterName = getter.getSimpleName().toString();

            boolean isMarshallable = getter.getAnnotation(Marshallable.class) != null;

            if (isMarshallable && !marshallableTypesBlackList.canBeMarshallable(getterType)) {
                String error = String.format(
                        "\"%s\" field is marked as @Marshallable but this type is either directly supported by native serialization "
                                + "or is prohibited by a blacklist, remove this annotation from the field",
                        getterName
                );

                throw new ProcessingException(error, null, getter);
            }

            FieldSpec.Builder fieldBuilder = FieldSpec.builder(getterReturnType, getterName)
                    .addAnnotation(IgniteToStringInclude.class)
                    .addModifiers(Modifier.PRIVATE);

            boolean generateSetter = getter.getAnnotation(WithSetter.class) != null;

            if (!isMarshallable && !generateSetter) {
                fieldBuilder.addModifiers(Modifier.FINAL);
            }

            if (requiresNotNullCheck(getter)) {
                notNullFieldNames.add(getterName);
            }

            FieldSpec field = fieldBuilder.build();
            fields.add(field);

            if (isMarshallable) {
                marshallableFieldNames.add(getterName);

                String name = getByteArrayFieldName(getterName);
                FieldSpec marshallableFieldArray = FieldSpec.builder(BYTE_ARRAY_TYPE, name)
                        .addModifiers(Modifier.PRIVATE)
                        .build();

                fields.add(marshallableFieldArray);

                MethodSpec baGetterImpl = MethodSpec.methodBuilder(name)
                        .returns(BYTE_ARRAY_TYPE)
                        .addStatement("return $N", marshallableFieldArray)
                        .build();

                methodImpls.add(baGetterImpl);
            }

            if (generateSetter) {
                MethodSpec setterImpl = MethodSpec.methodBuilder(getterName)
                        .returns(TypeName.VOID)
                        .addModifiers(Modifier.PUBLIC)
                        .addParameter(getterReturnType, getterName)
                        .addAnnotation(Override.class)
                        .addStatement("this.$L = $L", getterName, getterName)
                        .build();

                methodImpls.add(setterImpl);
            }

            MethodSpec getterImpl = MethodSpec.overriding(getter)
                    .addStatement("return $N", field)
                    .build();

            methodImpls.add(getterImpl);
        }

        TypeSpec.Builder messageImpl = TypeSpec.classBuilder(messageImplClassName)
                .addModifiers(Modifier.PUBLIC)
                .addSuperinterface(message.className())
                .addFields(fields)
                .addMethods(methodImpls)
                .addMethod(constructor(fields, notNullFieldNames, marshallableFieldNames));

        // group type constant and getter
        FieldSpec groupTypeField = FieldSpec.builder(short.class, "GROUP_TYPE")
                .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
                .initializer("$L", messageGroup.groupType())
                .build();

        messageImpl.addField(groupTypeField);

        MethodSpec groupTypeMethod = MethodSpec.methodBuilder("groupType")
                .addAnnotation(Override.class)
                .addModifiers(Modifier.PUBLIC)
                .returns(short.class)
                .addStatement("return $N", groupTypeField)
                .build();

        messageImpl.addMethod(groupTypeMethod);

        // TODO: https://issues.apache.org/jira/browse/IGNITE-17591
        MethodSpec toStringMethod = MethodSpec.methodBuilder("toString")
                .addAnnotation(Override.class)
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return $T.toString($T.class, this)", S.class, messageImplClassName)
                .build();

        messageImpl.addMethod(toStringMethod);

        // message type constant and getter
        FieldSpec messageTypeField = FieldSpec.builder(short.class, "TYPE")
                .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
                .initializer("$L", message.messageType())
                .build();

        messageImpl.addField(messageTypeField);

        MethodSpec messageTypeMethod = MethodSpec.methodBuilder("messageType")
                .addAnnotation(Override.class)
                .addModifiers(Modifier.PUBLIC)
                .returns(short.class)
                .addStatement("return $N", messageTypeField)
                .build();

        messageImpl.addMethod(messageTypeMethod);

        // equals and hashCode
        generateEqualsAndHashCode(messageImpl, message);

        var builderName = ClassName.get(message.packageName(), builderInterface.name);

        // nested builder interface and static factory method
        TypeSpec builder = generateBuilderImpl(message, messageImplClassName, builderName, notNullFieldNames, marshallableFieldNames);

        messageImpl.addType(builder);

        MethodSpec builderMethod = MethodSpec.methodBuilder("builder")
                .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                .returns(builderName)
                .addStatement("return new $N()", builder)
                .build();

        messageImpl.addMethod(builderMethod);

        generatePrepareMarshal(messageImpl, message);
        generateUnmarshalMethod(messageImpl, message);

        messageImpl
                .addOriginatingElement(message.element())
                .addOriginatingElement(messageGroup.element());

        return messageImpl.build();
    }