sergey-chugunov-1985 commented on code in PR #12652:
URL: https://github.com/apache/ignite/pull/12652#discussion_r2741534936


##########
modules/codegen2/src/main/java/org/apache/ignite/internal/idto/IDTOSerializerGenerator.java:
##########
@@ -0,0 +1,385 @@
+/*
+ * 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.idto;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.function.Function;
+import javax.annotation.processing.FilerException;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
+import javax.tools.JavaFileObject;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgniteBiTuple;
+
+import static org.apache.ignite.internal.MessageSerializerGenerator.NL;
+import static org.apache.ignite.internal.MessageSerializerGenerator.TAB;
+import static org.apache.ignite.internal.MessageSerializerGenerator.enumType;
+import static 
org.apache.ignite.internal.MessageSerializerGenerator.identicalFileIsAlreadyGenerated;
+
+/**
+ * Generates serializer class for given {@code IgniteDataTransferObject} 
extension.
+ * The generated serializer follows the naming convention:
+ * {@code org.apache.ignite.internal.codegen.[IDTOClassName]Serializer}.
+ */
+public class IDTOSerializerGenerator {
+    /** Serializer interface. */
+    public static final String DTO_SERDES_INTERFACE = 
"org.apache.ignite.internal.dto.IgniteDataTransferObjectSerializer";
+
+    /** Class javadoc */
+    static final String CLS_JAVADOC = "/** " + NL +
+        " * This class is generated automatically." + NL +
+        " *" + NL +
+        " * @see org.apache.ignite.internal.dto.IgniteDataTransferObject" + NL 
+
+        " */";
+
+    /** Type name to write/read code for the type. */
+    private static final Map<String, IgniteBiTuple<String, String>> 
TYPE_SERDES = new HashMap<>();
+
+    {
+        TYPE_SERDES.put(boolean.class.getName(), 
F.t("out.writeBoolean(obj.${f});", "obj.${f} = in.readBoolean();"));
+        TYPE_SERDES.put(byte.class.getName(), F.t("out.write(obj.${f});", 
"obj.${f} = in.read();"));
+        TYPE_SERDES.put(short.class.getName(), 
F.t("out.writeShort(obj.${f});", "obj.${f} = in.readShort();"));
+        TYPE_SERDES.put(int.class.getName(), F.t("out.writeInt(obj.${f});", 
"obj.${f} = in.readInt();"));
+        TYPE_SERDES.put(long.class.getName(), F.t("out.writeLong(obj.${f});", 
"obj.${f} = in.readLong();"));
+        TYPE_SERDES.put(float.class.getName(), 
F.t("out.writeFloat(obj.${f});", "obj.${f} = in.readFloat();"));
+        TYPE_SERDES.put(double.class.getName(), 
F.t("out.writeDouble(obj.${f});", "obj.${f} = in.readDouble();"));
+
+        IgniteBiTuple<String, String> objSerdes = 
F.t("out.writeObject(obj.${f});", "obj.${f} = (${c})in.readObject();");
+
+        TYPE_SERDES.put(Boolean.class.getName(), objSerdes);
+        TYPE_SERDES.put(Byte.class.getName(), objSerdes);
+        TYPE_SERDES.put(Short.class.getName(), objSerdes);
+        TYPE_SERDES.put(Integer.class.getName(), objSerdes);
+        TYPE_SERDES.put(Long.class.getName(), objSerdes);
+        TYPE_SERDES.put(Float.class.getName(), objSerdes);
+        TYPE_SERDES.put(Double.class.getName(), objSerdes);
+
+        TYPE_SERDES.put(String.class.getName(), F.t("U.writeString(out, 
obj.${f});", "obj.${f} = U.readString(in);"));
+        TYPE_SERDES.put(UUID.class.getName(), F.t("U.writeUuid(out, 
obj.${f});", "obj.${f} = U.readUuid(in);"));
+        TYPE_SERDES.put("org.apache.ignite.lang.IgniteUuid", 
F.t("U.writeIgniteUuid(out, obj.${f});", "obj.${f} = U.readIgniteUuid(in);"));
+        
TYPE_SERDES.put("org.apache.ignite.internal.processors.cache.version.GridCacheVersion",
 objSerdes);
+
+        TYPE_SERDES.put(Map.class.getName(), F.t("U.writeMap(out, obj.${f});", 
"obj.${f} = U.readMap(in);"));
+    }
+
+    /** Write/Read code for enum. */
+    private static final IgniteBiTuple<String, String> ENUM_SERDES =
+        F.t("U.writeEnum(out, obj.${f});", "obj.${f} = U.readEnum(in, 
${c}.class);");
+
+    /** Write/Read code for array. */
+    private static final IgniteBiTuple<String, String> OBJ_ARRAY_SERDES =
+        F.t("U.writeArray(out, obj.${f});", "obj.${f} = U.readArray(in, 
${c}.class);");
+
+    /** Type name to write/read code for the array of type. */
+    private static final Map<String, IgniteBiTuple<String, String>> 
ARRAY_TYPE_SERDES = new HashMap<>();
+
+    {
+        ARRAY_TYPE_SERDES.put(byte.class.getName(), F.t("U.writeByteArray(out, 
obj.${f});", "obj.${f} = U.readByteArray(in);"));
+        ARRAY_TYPE_SERDES.put(int.class.getName(), F.t("U.writeIntArray(out, 
obj.${f});", "obj.${f} = U.readIntArray(in);"));
+        ARRAY_TYPE_SERDES.put(long.class.getName(), F.t("U.writeLongArray(out, 
obj.${f});", "obj.${f} = U.readLongArray(in);"));
+        ARRAY_TYPE_SERDES.put(String.class.getName(), OBJ_ARRAY_SERDES);
+        ARRAY_TYPE_SERDES.put(UUID.class.getName(), OBJ_ARRAY_SERDES);
+    }
+
+    /** Environment. */
+    private final ProcessingEnvironment env;
+
+    /** Type to generated serializer for. */
+    private final TypeElement type;
+
+    /** Serializer imports. */
+    private final Set<String> imports = new HashSet<>();
+
+    /**
+     * @param env Environment.
+     * @param type Type to generate serializer for.
+     */
+    public IDTOSerializerGenerator(ProcessingEnvironment env, TypeElement 
type) {
+        this.env = env;
+        this.type = type;
+    }
+
+    /** @return Fully qualified name for generated class. */
+    public String serializerFQN() {
+        TypeElement topLevelCls = type;
+
+        while (topLevelCls.getNestingKind() != NestingKind.TOP_LEVEL)
+            topLevelCls = (TypeElement)topLevelCls.getEnclosingElement();
+
+        PackageElement pkg = (PackageElement)topLevelCls.getEnclosingElement();
+
+        return pkg.getQualifiedName().toString() + "." + serializerName();
+    }
+
+    /**
+     * @return {@code True} if generation succeed.
+     * @throws Exception in case of error.
+     */
+    public boolean generate() throws Exception {
+        String fqnClsName = serializerFQN();
+        String serCode = generateSerializerCode();
+
+        try {
+            JavaFileObject file = env.getFiler().createSourceFile(fqnClsName);
+
+            try (Writer writer = file.openWriter()) {
+                writer.append(serCode);
+                writer.flush();
+            }
+
+            return true;
+        }
+        catch (FilerException e) {
+            // IntelliJ IDEA parses Ignite's pom.xml and configures itself to 
use this annotation processor on each Run.
+            // During a Run, it invokes the processor and may fail when 
attempting to generate sources that already exist.
+            // There is no a setting to disable this invocation. The IntelliJ 
community suggests a workaround — delegating
+            // all Run commands to Maven. However, this significantly slows 
down test startup time.
+            // This hack checks whether the content of a generating file is 
identical to already existed file, and skips
+            // handling this class if it is.
+            if (!identicalFileIsAlreadyGenerated(env, serCode, fqnClsName)) {
+                env.getMessager().printMessage(
+                    Diagnostic.Kind.ERROR,
+                    fqnClsName + " is already generated. Try 'mvn clean 
install' to fix the issue.");
+
+                throw e;
+            }
+
+            return false;
+        }
+    }
+
+    /** @return Code for the calss implementing {@code 
org.apache.ignite.internal.dto.IgniteDataTransferObjectSerializer}. */
+    private String generateSerializerCode() throws IOException {
+        
imports.add("org.apache.ignite.internal.dto.IgniteDataTransferObjectSerializer");

Review Comment:
   ```suggestion
           imports.add(DTO_SERDES_INTERFACE);
   ```



##########
modules/codegen2/src/main/java/org/apache/ignite/internal/idto/IgniteDataTransferObjectProcessor.java:
##########
@@ -0,0 +1,390 @@
+/*
+ * 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.idto;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.FilerException;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
+import javax.tools.JavaFileObject;
+
+import static org.apache.ignite.internal.MessageSerializerGenerator.NL;
+import static org.apache.ignite.internal.MessageSerializerGenerator.TAB;
+import static 
org.apache.ignite.internal.MessageSerializerGenerator.identicalFileIsAlreadyGenerated;
+import static 
org.apache.ignite.internal.idto.IDTOSerializerGenerator.CLS_JAVADOC;
+import static 
org.apache.ignite.internal.idto.IDTOSerializerGenerator.DTO_SERDES_INTERFACE;
+import static 
org.apache.ignite.internal.idto.IDTOSerializerGenerator.simpleName;
+
+/**
+ * Generates implementations of {@code IgniteDataTransferObjectSerializer} for 
all supported classes.
+ * Generates factory {@code IDTOSerializerFactory} to get instance of 
serializer for given class.
+ * See, {@code IgniteDataTransferObject#writeExternal(ObjectOutput)} and 
{@code IgniteDataTransferObject#writeExternal(ObjectInput)} to get
+ * insight of using serializers.
+ */
+@SupportedAnnotationTypes("org.apache.ignite.internal.management.api.Argument")
+@SupportedSourceVersion(SourceVersion.RELEASE_11)
+public class IgniteDataTransferObjectProcessor extends AbstractProcessor {
+    /** Package for serializers. */
+    private static final String FACTORY_PKG_NAME = 
"org.apache.ignite.internal.codegen.idto";
+
+    /** Base class that every dto must extends. */
+    private static final String DTO_CLASS = 
"org.apache.ignite.internal.dto.IgniteDataTransferObject";
+
+    /**
+     * Annotation used in management commands.
+     * For now, we restrict set of generated serdes to all management commands 
argument classes.
+     * Because, they strictly follows Ignite codestyle convention.
+     * Providing support of all other inheritor of {@code 
IgniteDataTransferObject} is matter of following improvements.
+     */
+    private static final String ARG_ANNOTATION = 
"org.apache.ignite.internal.management.api.Argument";
+
+    /** Factory class name. */
+    public static final String FACTORY_CLASS = "IDTOSerializerFactory";
+
+    /** Generated classes. */
+    private final Map<TypeElement, String> genSerDes = new HashMap<>();
+
+    /**
+     * Processes all classes extending the {@code IgniteDataTransferObject} 
and generates corresponding serializer code.
+     */
+    @Override public boolean process(Set<? extends TypeElement> annotations, 
RoundEnvironment roundEnv) {
+        if (roundEnv.errorRaised())
+            return true;
+
+        genSerDes.clear();
+
+        roundEnv.getRootElements().forEach(this::generateSingle);
+
+        // IDE recompile only modified classes. Don't want to touch factory in 
the case no matching classes was recompiled.
+        if (genSerDes.isEmpty())
+            return true;
+
+        generateFactory(genSerDes);
+
+        return true;
+    }
+
+    /**
+     * @param el Element to generate code for.
+     */
+    private void generateSingle(Element el) {
+        if (el.getKind() != ElementKind.CLASS)
+            return;
+
+        TypeMirror dtoCls = 
processingEnv.getElementUtils().getTypeElement(DTO_CLASS).asType();
+        TypeMirror argAnnotation = 
processingEnv.getElementUtils().getTypeElement(ARG_ANNOTATION).asType();
+
+        TypeElement clazz = (TypeElement)el;
+
+        // Generate code for inner classes.
+        clazz.getEnclosedElements().forEach(this::generateSingle);
+
+        if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), dtoCls))
+            return;
+
+        if (clazz.getModifiers().contains(Modifier.ABSTRACT))
+            return;
+
+        if (!clazz.getModifiers().contains(Modifier.PUBLIC))
+            return;
+
+        if (clazz.getNestingKind() != NestingKind.TOP_LEVEL && 
clazz.getNestingKind() != NestingKind.MEMBER)
+            return;
+
+        if (!hasArgumentFields(clazz, argAnnotation))
+            return;
+
+        try {
+            IDTOSerializerGenerator gen = new 
IDTOSerializerGenerator(processingEnv, clazz);
+
+            if (gen.generate())
+                genSerDes.put(clazz, gen.serializerFQN());
+        }
+        catch (Exception e) {
+            processingEnv.getMessager().printMessage(
+                Diagnostic.Kind.ERROR,
+                "Failed to generate a dto serializer:" + e.getMessage(),
+                clazz
+            );
+        }
+    }
+
+    /**
+     * Generates and writes factory.
+     * @param genSerDes Generated serdes classes.
+     */
+    private void generateFactory(Map<TypeElement, String> genSerDes) {
+        try {
+            String factoryFQN = FACTORY_PKG_NAME + "." + FACTORY_CLASS;
+            String factoryCode = factoryCode(genSerDes);
+
+            try {
+                JavaFileObject file = 
processingEnv.getFiler().createSourceFile(factoryFQN);
+
+                try (Writer writer = file.openWriter()) {
+                    writer.append(factoryCode);
+                    writer.flush();
+                }
+            }
+            catch (FilerException e) {
+                // IntelliJ IDEA parses Ignite's pom.xml and configures itself 
to use this annotation processor on each Run.
+                // During a Run, it invokes the processor and may fail when 
attempting to generate sources that already exist.
+                // There is no a setting to disable this invocation. The 
IntelliJ community suggests a workaround — delegating
+                // all Run commands to Maven. However, this significantly 
slows down test startup time.
+                // This hack checks whether the content of a generating file 
is identical to already existed file, and skips
+                // handling this class if it is.
+                if (!identicalFileIsAlreadyGenerated(processingEnv, 
factoryCode, FACTORY_PKG_NAME + "." + FACTORY_CLASS)) {
+                    processingEnv.getMessager().printMessage(
+                        Diagnostic.Kind.ERROR,
+                        FACTORY_CLASS + " is already generated. Try 'mvn clean 
install' to fix the issue.");
+
+                    throw e;
+                }
+            }
+        }
+        catch (Exception e) {
+            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
"Failed to generate a dto factory:" + e.getMessage());

Review Comment:
   ```suggestion
               processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
"Failed to generate a dto factory: " + e.getMessage());
   ```



##########
modules/codegen2/src/main/java/org/apache/ignite/internal/idto/IgniteDataTransferObjectProcessor.java:
##########
@@ -0,0 +1,390 @@
+/*
+ * 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.idto;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.FilerException;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
+import javax.tools.JavaFileObject;
+
+import static org.apache.ignite.internal.MessageSerializerGenerator.NL;
+import static org.apache.ignite.internal.MessageSerializerGenerator.TAB;
+import static 
org.apache.ignite.internal.MessageSerializerGenerator.identicalFileIsAlreadyGenerated;
+import static 
org.apache.ignite.internal.idto.IDTOSerializerGenerator.CLS_JAVADOC;
+import static 
org.apache.ignite.internal.idto.IDTOSerializerGenerator.DTO_SERDES_INTERFACE;
+import static 
org.apache.ignite.internal.idto.IDTOSerializerGenerator.simpleName;
+
+/**
+ * Generates implementations of {@code IgniteDataTransferObjectSerializer} for 
all supported classes.
+ * Generates factory {@code IDTOSerializerFactory} to get instance of 
serializer for given class.
+ * See, {@code IgniteDataTransferObject#writeExternal(ObjectOutput)} and 
{@code IgniteDataTransferObject#writeExternal(ObjectInput)} to get
+ * insight of using serializers.
+ */
+@SupportedAnnotationTypes("org.apache.ignite.internal.management.api.Argument")
+@SupportedSourceVersion(SourceVersion.RELEASE_11)
+public class IgniteDataTransferObjectProcessor extends AbstractProcessor {
+    /** Package for serializers. */
+    private static final String FACTORY_PKG_NAME = 
"org.apache.ignite.internal.codegen.idto";
+
+    /** Base class that every dto must extends. */

Review Comment:
   ```suggestion
       /** Base class that every dto must extend. */
   ```



##########
modules/codegen2/src/main/java/org/apache/ignite/internal/idto/IDTOSerializerGenerator.java:
##########
@@ -0,0 +1,385 @@
+/*
+ * 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.idto;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.function.Function;
+import javax.annotation.processing.FilerException;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
+import javax.tools.JavaFileObject;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgniteBiTuple;
+
+import static org.apache.ignite.internal.MessageSerializerGenerator.NL;
+import static org.apache.ignite.internal.MessageSerializerGenerator.TAB;
+import static org.apache.ignite.internal.MessageSerializerGenerator.enumType;
+import static 
org.apache.ignite.internal.MessageSerializerGenerator.identicalFileIsAlreadyGenerated;
+
+/**
+ * Generates serializer class for given {@code IgniteDataTransferObject} 
extension.
+ * The generated serializer follows the naming convention:
+ * {@code org.apache.ignite.internal.codegen.[IDTOClassName]Serializer}.
+ */
+public class IDTOSerializerGenerator {
+    /** Serializer interface. */
+    public static final String DTO_SERDES_INTERFACE = 
"org.apache.ignite.internal.dto.IgniteDataTransferObjectSerializer";
+
+    /** Class javadoc */
+    static final String CLS_JAVADOC = "/** " + NL +
+        " * This class is generated automatically." + NL +
+        " *" + NL +
+        " * @see org.apache.ignite.internal.dto.IgniteDataTransferObject" + NL 
+
+        " */";
+
+    /** Type name to write/read code for the type. */
+    private static final Map<String, IgniteBiTuple<String, String>> 
TYPE_SERDES = new HashMap<>();
+
+    {
+        TYPE_SERDES.put(boolean.class.getName(), 
F.t("out.writeBoolean(obj.${f});", "obj.${f} = in.readBoolean();"));
+        TYPE_SERDES.put(byte.class.getName(), F.t("out.write(obj.${f});", 
"obj.${f} = in.read();"));
+        TYPE_SERDES.put(short.class.getName(), 
F.t("out.writeShort(obj.${f});", "obj.${f} = in.readShort();"));
+        TYPE_SERDES.put(int.class.getName(), F.t("out.writeInt(obj.${f});", 
"obj.${f} = in.readInt();"));
+        TYPE_SERDES.put(long.class.getName(), F.t("out.writeLong(obj.${f});", 
"obj.${f} = in.readLong();"));
+        TYPE_SERDES.put(float.class.getName(), 
F.t("out.writeFloat(obj.${f});", "obj.${f} = in.readFloat();"));
+        TYPE_SERDES.put(double.class.getName(), 
F.t("out.writeDouble(obj.${f});", "obj.${f} = in.readDouble();"));
+
+        IgniteBiTuple<String, String> objSerdes = 
F.t("out.writeObject(obj.${f});", "obj.${f} = (${c})in.readObject();");
+
+        TYPE_SERDES.put(Boolean.class.getName(), objSerdes);
+        TYPE_SERDES.put(Byte.class.getName(), objSerdes);
+        TYPE_SERDES.put(Short.class.getName(), objSerdes);
+        TYPE_SERDES.put(Integer.class.getName(), objSerdes);
+        TYPE_SERDES.put(Long.class.getName(), objSerdes);
+        TYPE_SERDES.put(Float.class.getName(), objSerdes);
+        TYPE_SERDES.put(Double.class.getName(), objSerdes);
+
+        TYPE_SERDES.put(String.class.getName(), F.t("U.writeString(out, 
obj.${f});", "obj.${f} = U.readString(in);"));
+        TYPE_SERDES.put(UUID.class.getName(), F.t("U.writeUuid(out, 
obj.${f});", "obj.${f} = U.readUuid(in);"));
+        TYPE_SERDES.put("org.apache.ignite.lang.IgniteUuid", 
F.t("U.writeIgniteUuid(out, obj.${f});", "obj.${f} = U.readIgniteUuid(in);"));
+        
TYPE_SERDES.put("org.apache.ignite.internal.processors.cache.version.GridCacheVersion",
 objSerdes);
+
+        TYPE_SERDES.put(Map.class.getName(), F.t("U.writeMap(out, obj.${f});", 
"obj.${f} = U.readMap(in);"));
+    }
+
+    /** Write/Read code for enum. */
+    private static final IgniteBiTuple<String, String> ENUM_SERDES =
+        F.t("U.writeEnum(out, obj.${f});", "obj.${f} = U.readEnum(in, 
${c}.class);");
+
+    /** Write/Read code for array. */
+    private static final IgniteBiTuple<String, String> OBJ_ARRAY_SERDES =
+        F.t("U.writeArray(out, obj.${f});", "obj.${f} = U.readArray(in, 
${c}.class);");
+
+    /** Type name to write/read code for the array of type. */
+    private static final Map<String, IgniteBiTuple<String, String>> 
ARRAY_TYPE_SERDES = new HashMap<>();
+
+    {
+        ARRAY_TYPE_SERDES.put(byte.class.getName(), F.t("U.writeByteArray(out, 
obj.${f});", "obj.${f} = U.readByteArray(in);"));
+        ARRAY_TYPE_SERDES.put(int.class.getName(), F.t("U.writeIntArray(out, 
obj.${f});", "obj.${f} = U.readIntArray(in);"));
+        ARRAY_TYPE_SERDES.put(long.class.getName(), F.t("U.writeLongArray(out, 
obj.${f});", "obj.${f} = U.readLongArray(in);"));
+        ARRAY_TYPE_SERDES.put(String.class.getName(), OBJ_ARRAY_SERDES);
+        ARRAY_TYPE_SERDES.put(UUID.class.getName(), OBJ_ARRAY_SERDES);
+    }
+
+    /** Environment. */
+    private final ProcessingEnvironment env;
+
+    /** Type to generated serializer for. */
+    private final TypeElement type;
+
+    /** Serializer imports. */
+    private final Set<String> imports = new HashSet<>();
+
+    /**
+     * @param env Environment.
+     * @param type Type to generate serializer for.
+     */
+    public IDTOSerializerGenerator(ProcessingEnvironment env, TypeElement 
type) {
+        this.env = env;
+        this.type = type;
+    }
+
+    /** @return Fully qualified name for generated class. */
+    public String serializerFQN() {
+        TypeElement topLevelCls = type;
+
+        while (topLevelCls.getNestingKind() != NestingKind.TOP_LEVEL)
+            topLevelCls = (TypeElement)topLevelCls.getEnclosingElement();
+
+        PackageElement pkg = (PackageElement)topLevelCls.getEnclosingElement();
+
+        return pkg.getQualifiedName().toString() + "." + serializerName();
+    }
+
+    /**
+     * @return {@code True} if generation succeed.
+     * @throws Exception in case of error.
+     */
+    public boolean generate() throws Exception {
+        String fqnClsName = serializerFQN();
+        String serCode = generateSerializerCode();
+
+        try {
+            JavaFileObject file = env.getFiler().createSourceFile(fqnClsName);
+
+            try (Writer writer = file.openWriter()) {
+                writer.append(serCode);
+                writer.flush();
+            }
+
+            return true;
+        }
+        catch (FilerException e) {
+            // IntelliJ IDEA parses Ignite's pom.xml and configures itself to 
use this annotation processor on each Run.
+            // During a Run, it invokes the processor and may fail when 
attempting to generate sources that already exist.
+            // There is no a setting to disable this invocation. The IntelliJ 
community suggests a workaround — delegating
+            // all Run commands to Maven. However, this significantly slows 
down test startup time.
+            // This hack checks whether the content of a generating file is 
identical to already existed file, and skips
+            // handling this class if it is.
+            if (!identicalFileIsAlreadyGenerated(env, serCode, fqnClsName)) {
+                env.getMessager().printMessage(
+                    Diagnostic.Kind.ERROR,
+                    fqnClsName + " is already generated. Try 'mvn clean 
install' to fix the issue.");
+
+                throw e;
+            }
+
+            return false;
+        }
+    }
+
+    /** @return Code for the calss implementing {@code 
org.apache.ignite.internal.dto.IgniteDataTransferObjectSerializer}. */
+    private String generateSerializerCode() throws IOException {
+        
imports.add("org.apache.ignite.internal.dto.IgniteDataTransferObjectSerializer");
+        imports.add(ObjectOutput.class.getName());
+        imports.add(ObjectInput.class.getName());
+        imports.add(IOException.class.getName());
+        imports.add("org.apache.ignite.internal.util.typedef.internal.U");
+
+        if (type.getNestingKind() != NestingKind.TOP_LEVEL)
+            imports.add(type.getQualifiedName().toString());
+
+        String simpleClsName = String.valueOf(type.getSimpleName());
+
+        List<VariableElement> flds = fields(type);
+
+        List<String> write = generateWrite(simpleClsName, flds);
+        List<String> read = generateRead(simpleClsName, flds);
+
+        try (Writer writer = new StringWriter()) {
+            writeClassHeader(writer, simpleClsName);
+
+            for (String line : write) {
+                writer.write(TAB);
+                writer.write(line);
+                writer.write(NL);
+            }
+
+            writer.write(NL);
+            for (String line : read) {
+                writer.write(TAB);
+                writer.write(line);
+                writer.write(NL);
+            }
+
+            writer.write("}");
+            writer.write(NL);
+
+            return writer.toString();
+        }
+    }
+
+    /**
+     * @param writer Writer to write class to.
+     * @param simpleClsName Class name
+     * @throws IOException

Review Comment:
   ```suggestion
        * @throws IOException  In case of error.
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/dto/IgniteDataTransferObjectSerializer.java:
##########
@@ -0,0 +1,45 @@
+/*
+ * 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.dto;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * @param <T>
+ */
+public interface IgniteDataTransferObjectSerializer<T> {
+    /**
+     *
+     * @param instance

Review Comment:
   ```suggestion
        * @param instance Instance of IgniteDataTransferObject to serialize.
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java:
##########
@@ -8241,4 +8243,31 @@ public void clearAllListener() {
                 listeners.clear();
         }
     }
+
+    /** */
+    public static final IgniteDataTransferObjectSerializer<?> EMPTY = new 
IgniteDataTransferObjectSerializer() {

Review Comment:
   ```suggestion
       public static final IgniteDataTransferObjectSerializer<?> 
EMPTY_DTO_SERIALIZER = new IgniteDataTransferObjectSerializer() {
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/dto/IgniteDataTransferObjectSerializer.java:
##########
@@ -0,0 +1,45 @@
+/*
+ * 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.dto;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * @param <T>
+ */
+public interface IgniteDataTransferObjectSerializer<T> {
+    /**
+     *
+     * @param instance
+     * @param out
+     * @throws IOException

Review Comment:
   ```suggestion
        * @throws IOException If write operation failed.
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/dto/IgniteDataTransferObjectSerializer.java:
##########
@@ -0,0 +1,45 @@
+/*
+ * 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.dto;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * @param <T>

Review Comment:
   ```suggestion
    * @param <T> Type of specific IgniteDataTransferObject this serializer 
works with.
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/dto/IgniteDataTransferObjectSerializer.java:
##########
@@ -0,0 +1,45 @@
+/*
+ * 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.dto;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * @param <T>
+ */
+public interface IgniteDataTransferObjectSerializer<T> {
+    /**
+     *
+     * @param instance
+     * @param out

Review Comment:
   ```suggestion
        * @param out Output stream to write object to.
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/dto/IgniteDataTransferObjectSerializer.java:
##########
@@ -0,0 +1,45 @@
+/*
+ * 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.dto;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * @param <T>
+ */
+public interface IgniteDataTransferObjectSerializer<T> {
+    /**
+     *
+     * @param instance
+     * @param out
+     * @throws IOException
+     */
+    void writeExternal(T instance, ObjectOutput out) throws IOException;
+
+    /**
+     *
+     * @param instance
+     * @param in

Review Comment:
   ```suggestion
        * @param in Input stream to read object from.
   ```



##########
modules/codegen2/src/main/java/org/apache/ignite/internal/idto/IgniteDataTransferObjectProcessor.java:
##########
@@ -0,0 +1,390 @@
+/*
+ * 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.idto;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.FilerException;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
+import javax.tools.JavaFileObject;
+
+import static org.apache.ignite.internal.MessageSerializerGenerator.NL;
+import static org.apache.ignite.internal.MessageSerializerGenerator.TAB;
+import static 
org.apache.ignite.internal.MessageSerializerGenerator.identicalFileIsAlreadyGenerated;
+import static 
org.apache.ignite.internal.idto.IDTOSerializerGenerator.CLS_JAVADOC;
+import static 
org.apache.ignite.internal.idto.IDTOSerializerGenerator.DTO_SERDES_INTERFACE;
+import static 
org.apache.ignite.internal.idto.IDTOSerializerGenerator.simpleName;
+
+/**
+ * Generates implementations of {@code IgniteDataTransferObjectSerializer} for 
all supported classes.
+ * Generates factory {@code IDTOSerializerFactory} to get instance of 
serializer for given class.
+ * See, {@code IgniteDataTransferObject#writeExternal(ObjectOutput)} and 
{@code IgniteDataTransferObject#writeExternal(ObjectInput)} to get
+ * insight of using serializers.
+ */
+@SupportedAnnotationTypes("org.apache.ignite.internal.management.api.Argument")
+@SupportedSourceVersion(SourceVersion.RELEASE_11)
+public class IgniteDataTransferObjectProcessor extends AbstractProcessor {
+    /** Package for serializers. */
+    private static final String FACTORY_PKG_NAME = 
"org.apache.ignite.internal.codegen.idto";
+
+    /** Base class that every dto must extends. */
+    private static final String DTO_CLASS = 
"org.apache.ignite.internal.dto.IgniteDataTransferObject";
+
+    /**
+     * Annotation used in management commands.
+     * For now, we restrict set of generated serdes to all management commands 
argument classes.
+     * Because, they strictly follows Ignite codestyle convention.
+     * Providing support of all other inheritor of {@code 
IgniteDataTransferObject} is matter of following improvements.
+     */
+    private static final String ARG_ANNOTATION = 
"org.apache.ignite.internal.management.api.Argument";
+
+    /** Factory class name. */
+    public static final String FACTORY_CLASS = "IDTOSerializerFactory";
+
+    /** Generated classes. */
+    private final Map<TypeElement, String> genSerDes = new HashMap<>();
+
+    /**
+     * Processes all classes extending the {@code IgniteDataTransferObject} 
and generates corresponding serializer code.
+     */
+    @Override public boolean process(Set<? extends TypeElement> annotations, 
RoundEnvironment roundEnv) {
+        if (roundEnv.errorRaised())
+            return true;
+
+        genSerDes.clear();
+
+        roundEnv.getRootElements().forEach(this::generateSingle);
+
+        // IDE recompile only modified classes. Don't want to touch factory in 
the case no matching classes was recompiled.
+        if (genSerDes.isEmpty())
+            return true;
+
+        generateFactory(genSerDes);
+
+        return true;
+    }
+
+    /**
+     * @param el Element to generate code for.
+     */
+    private void generateSingle(Element el) {
+        if (el.getKind() != ElementKind.CLASS)
+            return;
+
+        TypeMirror dtoCls = 
processingEnv.getElementUtils().getTypeElement(DTO_CLASS).asType();
+        TypeMirror argAnnotation = 
processingEnv.getElementUtils().getTypeElement(ARG_ANNOTATION).asType();
+
+        TypeElement clazz = (TypeElement)el;
+
+        // Generate code for inner classes.
+        clazz.getEnclosedElements().forEach(this::generateSingle);
+
+        if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), dtoCls))
+            return;
+
+        if (clazz.getModifiers().contains(Modifier.ABSTRACT))
+            return;
+
+        if (!clazz.getModifiers().contains(Modifier.PUBLIC))
+            return;
+
+        if (clazz.getNestingKind() != NestingKind.TOP_LEVEL && 
clazz.getNestingKind() != NestingKind.MEMBER)
+            return;
+
+        if (!hasArgumentFields(clazz, argAnnotation))
+            return;
+
+        try {
+            IDTOSerializerGenerator gen = new 
IDTOSerializerGenerator(processingEnv, clazz);
+
+            if (gen.generate())
+                genSerDes.put(clazz, gen.serializerFQN());
+        }
+        catch (Exception e) {
+            processingEnv.getMessager().printMessage(
+                Diagnostic.Kind.ERROR,
+                "Failed to generate a dto serializer:" + e.getMessage(),
+                clazz
+            );
+        }
+    }
+
+    /**
+     * Generates and writes factory.
+     * @param genSerDes Generated serdes classes.
+     */
+    private void generateFactory(Map<TypeElement, String> genSerDes) {
+        try {
+            String factoryFQN = FACTORY_PKG_NAME + "." + FACTORY_CLASS;
+            String factoryCode = factoryCode(genSerDes);
+
+            try {
+                JavaFileObject file = 
processingEnv.getFiler().createSourceFile(factoryFQN);
+
+                try (Writer writer = file.openWriter()) {
+                    writer.append(factoryCode);
+                    writer.flush();
+                }
+            }
+            catch (FilerException e) {
+                // IntelliJ IDEA parses Ignite's pom.xml and configures itself 
to use this annotation processor on each Run.
+                // During a Run, it invokes the processor and may fail when 
attempting to generate sources that already exist.
+                // There is no a setting to disable this invocation. The 
IntelliJ community suggests a workaround — delegating
+                // all Run commands to Maven. However, this significantly 
slows down test startup time.
+                // This hack checks whether the content of a generating file 
is identical to already existed file, and skips
+                // handling this class if it is.
+                if (!identicalFileIsAlreadyGenerated(processingEnv, 
factoryCode, FACTORY_PKG_NAME + "." + FACTORY_CLASS)) {
+                    processingEnv.getMessager().printMessage(
+                        Diagnostic.Kind.ERROR,
+                        FACTORY_CLASS + " is already generated. Try 'mvn clean 
install' to fix the issue.");
+
+                    throw e;
+                }
+            }
+        }
+        catch (Exception e) {
+            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
"Failed to generate a dto factory:" + e.getMessage());
+        }
+    }
+
+    /**
+     * @param genSerDes Generated serdes classes.
+     * @return Factory code.
+     * @throws IOException In case of error.
+     */
+    private String factoryCode(Map<TypeElement, String> genSerDes) throws 
IOException {
+        try (Writer writer = new StringWriter()) {
+            writeClassHeader(writer, genSerDes);
+
+            writer.write(TAB);
+            writer.write("/** */");
+            writer.write(NL);
+            writer.write(TAB);
+            writer.write("private static final " + FACTORY_CLASS + " instance 
= new " + FACTORY_CLASS + "();");
+            writer.write(NL);
+            writer.write(NL);
+
+            writer.write(TAB);
+            writer.write("/** */");
+            writer.write(NL);
+            writer.write(TAB);
+            writer.write("private final Map<Class<? extends 
IgniteDataTransferObject>, " + simpleName(DTO_SERDES_INTERFACE) + "> serdes " +
+                "= new HashMap<>();");
+            writer.write(NL);
+            writer.write(NL);
+
+            constructor(writer, genSerDes);
+            writer.write(NL);
+
+            getInstance(writer);
+            writer.write(NL);
+
+            serializer(writer);
+
+            writer.write("}");
+            writer.write(NL);
+
+            return writer.toString();
+        }
+    }
+
+    /**
+     * Generates class header.
+     *
+     * @param writer Writer to write code to.
+     * @param dtoClss DTO classes to import.
+     * @throws IOException In case of error.
+     */
+    private void writeClassHeader(Writer writer, Map<TypeElement, String> 
dtoClss) throws IOException {
+        try (InputStream in = 
getClass().getClassLoader().getResourceAsStream("license.txt");
+             BufferedReader reader = new BufferedReader(new 
InputStreamReader(in))) {
+
+            PrintWriter out = new PrintWriter(writer);
+
+            String line;
+
+            while ((line = reader.readLine()) != null)
+                out.println(line);
+        }
+
+        writer.write(NL);
+        writer.write("package " + FACTORY_PKG_NAME + ";" + NL + NL);
+
+        for (Map.Entry<TypeElement, String> e : dtoClss.entrySet()) {
+            writer.write("import " + e.getKey().getQualifiedName() + ";" + NL);
+            writer.write("import " + e.getValue() + ";" + NL);
+        }
+
+        writer.write("import " + Map.class.getName() + ";" + NL);
+        writer.write("import " + HashMap.class.getName() + ";" + NL);
+        writer.write("import " + DTO_SERDES_INTERFACE + ";" + NL);
+        writer.write("import " + DTO_CLASS + ";" + NL);
+        writer.write("import 
org.apache.ignite.internal.util.typedef.internal.U;" + NL);
+
+        writer.write(NL);
+        writer.write(CLS_JAVADOC);
+        writer.write(NL);
+        writer.write("public class " + FACTORY_CLASS + " {" + NL);
+    }
+
+    /**
+     * Generates static {@code getInstance} method.
+     *
+     * @param writer Writer to write code to.
+     * @throws IOException In case of error.
+     */
+    private static void getInstance(Writer writer) throws IOException {
+        writer.write(TAB);
+        writer.write("/** */");
+        writer.write(NL);
+        writer.write(TAB);
+        writer.write("public static " + FACTORY_CLASS + " getInstance() {");
+        writer.write(NL);
+        writer.write(TAB);
+        writer.write(TAB);
+        writer.write("return instance;");
+        writer.write(NL);
+        writer.write(TAB);
+        writer.write("}");
+        writer.write(NL);
+    }
+
+    /**
+     * Generates private constructor.
+     *
+     * @param writer Writer to write code to.
+     * @param genSerDes Serdes to support in factory.
+     * @throws IOException In case of error.
+     */
+    private static void constructor(Writer writer, Map<TypeElement, String> 
genSerDes) throws IOException {
+        writer.write(TAB);
+        writer.write("/** */");
+        writer.write(NL);
+        writer.write(TAB);
+        writer.write("private " + FACTORY_CLASS + "() {");
+        writer.write(NL);
+
+        for (Map.Entry<TypeElement, String> e : genSerDes.entrySet()) {
+            writer.write(TAB);
+            writer.write(TAB);
+            writer.write("serdes.put(" + e.getKey().getSimpleName() + ".class, 
new " + simpleName(e.getValue()) + "());");
+            writer.write(NL);
+        }
+
+        writer.write(TAB);
+        writer.write("}");
+        writer.write(NL);
+    }
+
+    /**
+     * Generates method to get serializer from factory.
+     *
+     * @param writer Writer to write code to.
+     * @throws IOException In case of error.
+     */
+    private void serializer(Writer writer) throws IOException {
+        writer.write(TAB);
+        writer.write("/** */");
+        writer.write(NL);
+        writer.write(TAB);
+
+        String genericType = "<T extends " + simpleName(DTO_CLASS) + ">";
+
+        writer.write("public " + genericType + " " + 
simpleName(DTO_SERDES_INTERFACE) + "<T> serializer(Class<T> cls) {");
+        writer.write(NL);
+        writer.write(TAB);
+        writer.write(TAB);
+        writer.write("IgniteDataTransferObjectSerializer<T> res = 
(IgniteDataTransferObjectSerializer<T>)serdes.get(cls);");
+        writer.write(NL);
+        writer.write(NL);
+        writer.write(TAB);
+        writer.write(TAB);
+        writer.write("if (res == null) {");
+        writer.write(NL);
+        writer.write(TAB);
+        writer.write(TAB);
+        writer.write(TAB);
+        // IDE can invoke partial recompile during development.
+        // In this case there will be only part (one) of serdes in the map 
initially.
+        // We want to correctly initialize and trying to load serializer 
dynamically.

Review Comment:
   ```suggestion
           // We want to be able to load serializer dynamically if it is 
missing in the map but class file itself is presented in classpath.
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/dto/IgniteDataTransferObjectSerializer.java:
##########
@@ -0,0 +1,45 @@
+/*
+ * 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.dto;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * @param <T>
+ */
+public interface IgniteDataTransferObjectSerializer<T> {
+    /**
+     *
+     * @param instance
+     * @param out
+     * @throws IOException
+     */
+    void writeExternal(T instance, ObjectOutput out) throws IOException;
+
+    /**
+     *
+     * @param instance

Review Comment:
   ```suggestion
        * @param instance Instance of an IgniteDataTransferObject to read data 
to.
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/dto/IgniteDataTransferObjectSerializer.java:
##########
@@ -0,0 +1,45 @@
+/*
+ * 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.dto;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * @param <T>
+ */
+public interface IgniteDataTransferObjectSerializer<T> {
+    /**
+     *
+     * @param instance
+     * @param out
+     * @throws IOException
+     */
+    void writeExternal(T instance, ObjectOutput out) throws IOException;
+
+    /**
+     *
+     * @param instance
+     * @param in
+     * @return
+     * @throws IOException
+     * @throws ClassNotFoundException

Review Comment:
   ```suggestion
        * @throws ClassNotFoundException If class not found.
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/dto/IgniteDataTransferObjectSerializer.java:
##########
@@ -0,0 +1,45 @@
+/*
+ * 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.dto;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * @param <T>
+ */
+public interface IgniteDataTransferObjectSerializer<T> {
+    /**
+     *
+     * @param instance
+     * @param out
+     * @throws IOException
+     */
+    void writeExternal(T instance, ObjectOutput out) throws IOException;
+
+    /**
+     *
+     * @param instance
+     * @param in
+     * @return
+     * @throws IOException

Review Comment:
   ```suggestion
        * @throws IOException If read operation failed.
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to