This is an automated email from the ASF dual-hosted git repository.

tkalkirill pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new e1dca925ef IGNITE-22651 Add @Nullable for NetworkMessage fields for 
generated classes (#4037)
e1dca925ef is described below

commit e1dca925efefac68f919bf578f119a2ab3cd9fb6
Author: Kirill Tkalenko <[email protected]>
AuthorDate: Wed Jul 3 15:31:28 2024 +0300

    IGNITE-22651 Add @Nullable for NetworkMessage fields for generated classes 
(#4037)
---
 .../network/processor/MessageGeneratorUtils.java   | 75 ++++++++++++++++++++++
 .../messages/MessageBuilderGenerator.java          | 67 +++++++++++++------
 .../processor/messages/MessageImplGenerator.java   | 45 ++++---------
 .../MessageDeserializerGenerator.java              |  4 +-
 .../serialization/MessageReaderMethodResolver.java |  4 +-
 .../serialization/MessageWriterMethodResolver.java |  4 +-
 6 files changed, 138 insertions(+), 61 deletions(-)

diff --git 
a/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/MessageGeneratorUtils.java
 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/MessageGeneratorUtils.java
new file mode 100644
index 0000000000..2da7486b8b
--- /dev/null
+++ 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/MessageGeneratorUtils.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.network.processor;
+
+import com.squareup.javapoet.AnnotationSpec;
+import com.squareup.javapoet.ArrayTypeName;
+import com.squareup.javapoet.TypeName;
+import java.util.List;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import org.apache.ignite.internal.network.NetworkMessage;
+import org.jetbrains.annotations.Nullable;
+
+/** Сlass that contains useful constants and methods when generating classes 
for {@link NetworkMessage}. */
+public class MessageGeneratorUtils {
+    /** {@link Nullable} spec. */
+    public static final AnnotationSpec NULLABLE_ANNOTATION_SPEC = 
AnnotationSpec.builder(Nullable.class).build();
+
+    /** Type name of the {@code byte[]}. */
+    public static final TypeName BYTE_ARRAY_TYPE = 
ArrayTypeName.of(TypeName.BYTE);
+
+    /** Type name of the {@code byte @Nullable []}. */
+    public static final TypeName NULLABLE_BYTE_ARRAY_TYPE = 
ArrayTypeName.of(TypeName.BYTE).annotated(NULLABLE_ANNOTATION_SPEC);
+
+    /** Returns {@link true} if the method return value is marked with {@link 
Nullable}. */
+    public static boolean methodReturnsNullableValue(ExecutableElement el) {
+        TypeMirror returnType = el.getReturnType();
+
+        TypeKind kind = returnType.getKind();
+
+        if (kind == TypeKind.ARRAY) {
+            List<? extends AnnotationMirror> annotations = 
returnType.getAnnotationMirrors();
+
+            for (AnnotationMirror annotation : annotations) {
+                DeclaredType annotationType = annotation.getAnnotationType();
+
+                if 
(Nullable.class.getName().equals(annotationType.toString())) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        return el.getAnnotation(Nullable.class) != null;
+    }
+
+    /** Returns {@link true} if the method return primitive value. */
+    public static boolean methodReturnsPrimitive(ExecutableElement el) {
+        return el.getReturnType().getKind().isPrimitive();
+    }
+
+    /** Adds postfix "ByteArray". */
+    public static String addByteArrayPostfix(String s) {
+        return s + "ByteArray";
+    }
+}
diff --git 
a/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/messages/MessageBuilderGenerator.java
 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/messages/MessageBuilderGenerator.java
index f214f3c45a..d1d2e07059 100644
--- 
a/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/messages/MessageBuilderGenerator.java
+++ 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/messages/MessageBuilderGenerator.java
@@ -17,8 +17,12 @@
 
 package org.apache.ignite.internal.network.processor.messages;
 
-import static 
org.apache.ignite.internal.network.processor.messages.MessageImplGenerator.BYTE_ARRAY_TYPE;
-import static 
org.apache.ignite.internal.network.processor.messages.MessageImplGenerator.getByteArrayFieldName;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.BYTE_ARRAY_TYPE;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.NULLABLE_ANNOTATION_SPEC;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.NULLABLE_BYTE_ARRAY_TYPE;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.addByteArrayPostfix;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.methodReturnsNullableValue;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.methodReturnsPrimitive;
 
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.MethodSpec;
@@ -29,7 +33,6 @@ import java.util.List;
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.Modifier;
-import javax.lang.model.type.TypeMirror;
 import javax.tools.Diagnostic;
 import org.apache.ignite.internal.network.annotations.Marshallable;
 import org.apache.ignite.internal.network.processor.MessageClass;
@@ -75,33 +78,42 @@ public class MessageBuilderGenerator {
 
         return TypeSpec.interfaceBuilder(builderName)
                 .addModifiers(Modifier.PUBLIC)
-                .addMethods(generateGettersAndSetters(message, 
message.getters()))
-                .addMethods(generateByteArrayGettersAndSetters(message, 
message.getters()))
+                .addMethods(generateGettersAndSetters(message))
+                .addMethods(generateByteArrayGettersAndSetters(message))
                 .addMethod(buildMethod)
                 .addOriginatingElement(message.element())
                 .addOriginatingElement(messageGroup.element())
                 .build();
     }
 
-    private List<MethodSpec> generateGettersAndSetters(MessageClass message, 
List<ExecutableElement> fields) {
-        List<MethodSpec> methods = new ArrayList<>();
+    private static List<MethodSpec> generateGettersAndSetters(MessageClass 
message) {
+        var methods = new ArrayList<MethodSpec>();
 
-        for (ExecutableElement field : fields) {
-            String fieldName = field.getSimpleName().toString();
+        for (ExecutableElement networkMessageGetter : message.getters()) {
+            String fieldName = networkMessageGetter.getSimpleName().toString();
 
-            TypeMirror type = field.getReturnType();
+            TypeName returnTypeName = 
TypeName.get(networkMessageGetter.getReturnType());
+
+            if 
(methodReturnsNotPrimitiveButNullableValue(networkMessageGetter)) {
+                // Allows us to generate (for example):
+                // TestMessageBuilder value(@Nullable String value);
+                // @Nullable String value();
+                // TestMessageBuilder values(String @Nullable [] value);
+                // String @Nullable [] values();
+                returnTypeName = 
returnTypeName.annotated(NULLABLE_ANNOTATION_SPEC);
+            }
 
             // generate a setter for each getter in the original interface
             MethodSpec setterSpec = MethodSpec.methodBuilder(fieldName)
                     .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
-                    .addParameter(TypeName.get(type), fieldName)
+                    .addParameter(returnTypeName, fieldName)
                     .returns(message.builderClassName())
                     .build();
 
             // generate a getter for each getter in the original interface
             MethodSpec getterSpec = MethodSpec.methodBuilder(fieldName)
                     .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
-                    .returns(TypeName.get(type))
+                    .returns(returnTypeName)
                     .build();
 
             methods.add(setterSpec);
@@ -111,22 +123,31 @@ public class MessageBuilderGenerator {
         return methods;
     }
 
-    private List<MethodSpec> generateByteArrayGettersAndSetters(MessageClass 
message, List<ExecutableElement> fields) {
-        List<MethodSpec> methods = new ArrayList<>();
+    private static List<MethodSpec> 
generateByteArrayGettersAndSetters(MessageClass message) {
+        var methods = new ArrayList<MethodSpec>();
+
+        for (ExecutableElement networkMessageGetter : message.getters()) {
+            if (networkMessageGetter.getAnnotation(Marshallable.class) != 
null) {
+                String fieldName = 
networkMessageGetter.getSimpleName().toString();
 
-        for (ExecutableElement field : fields) {
-            if (field.getAnnotation(Marshallable.class) != null) {
-                String fieldName = field.getSimpleName().toString();
+                TypeName getterAndSetterTypeName = BYTE_ARRAY_TYPE;
 
-                MethodSpec baSetter = 
MethodSpec.methodBuilder(getByteArrayFieldName(fieldName))
+                if 
(methodReturnsNotPrimitiveButNullableValue(networkMessageGetter)) {
+                    // Allows us to generate (for example):
+                    // TestMessageBuilder valueByteArray(byte @Nullable [] 
value);
+                    // byte @Nullable [] valueByteArray();
+                    getterAndSetterTypeName = NULLABLE_BYTE_ARRAY_TYPE;
+                }
+
+                MethodSpec baSetter = 
MethodSpec.methodBuilder(addByteArrayPostfix(fieldName))
                         .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
-                        .addParameter(BYTE_ARRAY_TYPE, 
getByteArrayFieldName(fieldName))
+                        .addParameter(getterAndSetterTypeName, 
addByteArrayPostfix(fieldName))
                         .returns(message.builderClassName())
                         .build();
 
-                MethodSpec baGetter = 
MethodSpec.methodBuilder(getByteArrayFieldName(fieldName))
+                MethodSpec baGetter = 
MethodSpec.methodBuilder(addByteArrayPostfix(fieldName))
                         .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
-                        .returns(BYTE_ARRAY_TYPE)
+                        .returns(getterAndSetterTypeName)
                         .build();
 
                 methods.add(baSetter);
@@ -136,4 +157,8 @@ public class MessageBuilderGenerator {
 
         return methods;
     }
+
+    private static boolean 
methodReturnsNotPrimitiveButNullableValue(ExecutableElement method) {
+        return !methodReturnsPrimitive(method) && 
methodReturnsNullableValue(method);
+    }
 }
diff --git 
a/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/messages/MessageImplGenerator.java
 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/messages/MessageImplGenerator.java
index 3c17b3806a..3d836a96f7 100644
--- 
a/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/messages/MessageImplGenerator.java
+++ 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/messages/MessageImplGenerator.java
@@ -17,8 +17,12 @@
 
 package org.apache.ignite.internal.network.processor.messages;
 
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.BYTE_ARRAY_TYPE;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.addByteArrayPostfix;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.methodReturnsNullableValue;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.methodReturnsPrimitive;
+
 import com.squareup.javapoet.AnnotationSpec;
-import com.squareup.javapoet.ArrayTypeName;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.FieldSpec;
@@ -41,7 +45,6 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.Modifier;
 import javax.lang.model.type.ArrayType;
@@ -60,16 +63,12 @@ import 
org.apache.ignite.internal.network.serialization.MessageSerializer;
 import org.apache.ignite.internal.tostring.IgniteToStringExclude;
 import org.apache.ignite.internal.tostring.IgniteToStringInclude;
 import org.apache.ignite.internal.tostring.S;
-import org.jetbrains.annotations.Nullable;
 
 /**
  * Class for generating implementations of the {@link NetworkMessage} 
interfaces and their builders, generated by a {@link
  * MessageBuilderGenerator}.
  */
 public class MessageImplGenerator {
-    /** Type name of the {@code byte[]}. */
-    static final ArrayTypeName BYTE_ARRAY_TYPE = 
ArrayTypeName.of(TypeName.BYTE);
-
     /** Processing environment. */
     private final ProcessingEnvironment processingEnv;
 
@@ -164,7 +163,7 @@ public class MessageImplGenerator {
             if (isMarshallable) {
                 marshallableFieldNames.add(getterName);
 
-                String name = getByteArrayFieldName(getterName);
+                String name = addByteArrayPostfix(getterName);
                 FieldSpec marshallableFieldArray = 
FieldSpec.builder(BYTE_ARRAY_TYPE, name)
                         .addModifiers(Modifier.PRIVATE)
                         .build();
@@ -360,7 +359,7 @@ public class MessageImplGenerator {
             if (executableElement.getAnnotation(Marshallable.class) != null) {
                 isNeeded = true;
 
-                String baName = getByteArrayFieldName(objectName);
+                String baName = addByteArrayPostfix(objectName);
                 String moName = baName + "mo";
                 prepareMarshal.addStatement("$T $N = marshaller.marshal($N)", 
marshalledObjectClass, moName, objectName);
                 
prepareMarshal.addStatement("usedDescriptors.addAll($N.usedDescriptorIds())", 
moName);
@@ -422,7 +421,7 @@ public class MessageImplGenerator {
             if (executableElement.getAnnotation(Marshallable.class) != null) {
                 isNeeded = true;
 
-                String baName = getByteArrayFieldName(objectName);
+                String baName = addByteArrayPostfix(objectName);
                 unmarshal.addStatement("$N = marshaller.unmarshal($N, 
descriptorsObj)", objectName, baName);
                 unmarshal.addStatement("$N = null", baName);
             } else {
@@ -670,7 +669,7 @@ public class MessageImplGenerator {
 
             if (notNullFieldNames.contains(fieldName) && 
marshallableFieldNames.contains(fieldName)) {
                 CodeBlock nullCheck = CodeBlock.builder()
-                        .beginControlFlow("if ($L == null && $L == null)", 
fieldName, getByteArrayFieldName(fieldName))
+                        .beginControlFlow("if ($L == null && $L == null)", 
fieldName, addByteArrayPostfix(fieldName))
                         .addStatement("throw new $T($S)", 
NullPointerException.class, fieldName + " is not marked @Nullable")
                         .endControlFlow()
                         .build();
@@ -737,7 +736,7 @@ public class MessageImplGenerator {
             getters.add(getter);
 
             if (isMarshallable) {
-                String name = getByteArrayFieldName(getterName);
+                String name = addByteArrayPostfix(getterName);
                 FieldSpec baField = FieldSpec.builder(BYTE_ARRAY_TYPE, name)
                         .addModifiers(Modifier.PRIVATE)
                         .build();
@@ -809,29 +808,7 @@ public class MessageImplGenerator {
     }
 
     private static boolean requiresNotNullCheck(ExecutableElement el) {
-        TypeMirror returnType = el.getReturnType();
-
-        TypeKind kind = returnType.getKind();
-
-        if (kind == TypeKind.ARRAY) {
-            List<? extends AnnotationMirror> annotations = 
returnType.getAnnotationMirrors();
-
-            for (AnnotationMirror annotation : annotations) {
-                DeclaredType annotationType = annotation.getAnnotationType();
-
-                if 
(Nullable.class.getName().equals(annotationType.toString())) {
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        return !kind.isPrimitive() && el.getAnnotation(Nullable.class) == null;
-    }
-
-    public static String getByteArrayFieldName(String objectName) {
-        return objectName + "ByteArray";
+        return !methodReturnsPrimitive(el) && !methodReturnsNullableValue(el);
     }
 
     /** Types that may hold network message. */
diff --git 
a/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageDeserializerGenerator.java
 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageDeserializerGenerator.java
index 7c0c06c401..777d981d81 100644
--- 
a/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageDeserializerGenerator.java
+++ 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageDeserializerGenerator.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.internal.network.processor.serialization;
 
 import static java.util.stream.Collectors.toList;
-import static 
org.apache.ignite.internal.network.processor.messages.MessageImplGenerator.getByteArrayFieldName;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.addByteArrayPostfix;
 
 import com.squareup.javapoet.ArrayTypeName;
 import com.squareup.javapoet.ClassName;
@@ -139,7 +139,7 @@ public class MessageDeserializerGenerator {
                 String name = getter.getSimpleName().toString();
 
                 if (getter.getAnnotation(Marshallable.class) != null) {
-                    name = getByteArrayFieldName(name);
+                    name = addByteArrayPostfix(name);
                 }
 
                 method
diff --git 
a/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageReaderMethodResolver.java
 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageReaderMethodResolver.java
index e6a51b63bd..2e439b76a2 100644
--- 
a/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageReaderMethodResolver.java
+++ 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageReaderMethodResolver.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.network.processor.serialization;
 
-import static 
org.apache.ignite.internal.network.processor.messages.MessageImplGenerator.getByteArrayFieldName;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.addByteArrayPostfix;
 
 import com.squareup.javapoet.CodeBlock;
 import java.util.List;
@@ -62,7 +62,7 @@ class MessageReaderMethodResolver {
         String parameterName = getter.getSimpleName().toString();
 
         if (getter.getAnnotation(Marshallable.class) != null) {
-            parameterName = getByteArrayFieldName(parameterName);
+            parameterName = addByteArrayPostfix(parameterName);
             return CodeBlock.builder()
                     .add("readByteArray($S)", parameterName)
                     .build();
diff --git 
a/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageWriterMethodResolver.java
 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageWriterMethodResolver.java
index 7a872d4b48..36e3fddcab 100644
--- 
a/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageWriterMethodResolver.java
+++ 
b/modules/network-annotation-processor/src/main/java/org/apache/ignite/internal/network/processor/serialization/MessageWriterMethodResolver.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.network.processor.serialization;
 
-import static 
org.apache.ignite.internal.network.processor.messages.MessageImplGenerator.getByteArrayFieldName;
+import static 
org.apache.ignite.internal.network.processor.MessageGeneratorUtils.addByteArrayPostfix;
 
 import com.squareup.javapoet.CodeBlock;
 import java.util.Collection;
@@ -75,7 +75,7 @@ class MessageWriterMethodResolver {
         String parameterName = getter.getSimpleName().toString();
 
         if (getter.getAnnotation(Marshallable.class) != null) {
-            parameterName = getByteArrayFieldName(parameterName);
+            parameterName = addByteArrayPostfix(parameterName);
             return CodeBlock.builder()
                     .add("writeByteArray($S, message.$L())", parameterName, 
parameterName)
                     .build();

Reply via email to