All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.auties.protobuf.serialization.generator.clazz.ProtobufSpecVisitor Maven / Gradle / Ivy

package it.auties.protobuf.serialization.generator.clazz;

import it.auties.protobuf.model.ProtobufWireType;
import it.auties.protobuf.serialization.generator.method.ProtobufDeserializationMethodGenerator;
import it.auties.protobuf.serialization.generator.method.ProtobufDeserializationMethodOverloadGenerator;
import it.auties.protobuf.serialization.generator.method.ProtobufSerializationMethodGenerator;
import it.auties.protobuf.serialization.generator.method.ProtobufSizeMethodGenerator;
import it.auties.protobuf.serialization.model.object.ProtobufObjectElement;
import it.auties.protobuf.serialization.model.property.ProtobufPropertyElement;
import it.auties.protobuf.serialization.support.JavaWriter;
import it.auties.protobuf.stream.ProtobufInputStream;
import it.auties.protobuf.stream.ProtobufOutputStream;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.PackageElement;
import java.io.IOException;
import java.util.*;

public class ProtobufSpecVisitor {
    private final ProcessingEnvironment processingEnv;

    public ProtobufSpecVisitor(ProcessingEnvironment processingEnv) {
        this.processingEnv = processingEnv;
    }

    public void createClass(ProtobufObjectElement result, PackageElement packageName) throws IOException {
        // Names
        var simpleGeneratedClassName = result.getGeneratedClassNameBySuffix("Spec");
        var qualifiedGeneratedClassName = packageName != null ? packageName + "." + simpleGeneratedClassName : simpleGeneratedClassName;
        var sourceFile = processingEnv.getFiler().createSourceFile(qualifiedGeneratedClassName);

        // Declare a new compilation unit
        try (var compilationUnitWriter = new JavaWriter.CompilationUnit(sourceFile.openWriter())) {
            // If a package is available, write it in the compilation unit
            if(packageName != null) {
                compilationUnitWriter.printPackageDeclaration(packageName.getQualifiedName().toString());
            }

            // Declare the imports needed for everything to work
            var imports = getSpecImports(result);
            imports.forEach(compilationUnitWriter::printImportDeclaration);

            // Separate imports from classes
            compilationUnitWriter.printSeparator();

            // Declare the spec class
            try(var classWriter = compilationUnitWriter.printClassDeclaration(simpleGeneratedClassName)) {
                // Write the serializer
                var serializationVisitor = new ProtobufSerializationMethodGenerator(result);
                serializationVisitor.generate(classWriter);

                // Write the deserializer
                var deserializationOverloadVisitor = new ProtobufDeserializationMethodOverloadGenerator(result);
                deserializationOverloadVisitor.generate(classWriter);

                // Write the deserializer
                var deserializationVisitor = new ProtobufDeserializationMethodGenerator(result);
                deserializationVisitor.generate(classWriter);


                // Write the size calculator
                var sizeVisitor = new ProtobufSizeMethodGenerator(result);
                sizeVisitor.generate(classWriter);
            }
        }
    }

    // Get the imports to include in the compilation unit
    private List getSpecImports(ProtobufObjectElement message) {
        if(message.isEnum()) {
            return List.of(
                    message.element().getQualifiedName().toString(),
                    Arrays.class.getName(),
                    Optional.class.getName(),
                    ProtobufOutputStream.class.getName()
            );
        }

        var imports = new ArrayList();
        imports.add(message.element().getQualifiedName().toString());
        imports.add(ProtobufInputStream.class.getName());
        imports.add(ProtobufOutputStream.class.getName());
        imports.add(ProtobufWireType.class.getName());
        if (message.properties().stream().anyMatch(ProtobufPropertyElement::required)) {
            imports.add(Objects.class.getName());
        }

        return Collections.unmodifiableList(imports);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy