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

com.jacobmountain.graphql.client.GraphQLClientProcessor Maven / Gradle / Ivy

package com.jacobmountain.graphql.client;

import com.google.auto.service.AutoService;
import com.jacobmountain.graphql.client.annotations.GraphQLClient;
import com.jacobmountain.graphql.client.exceptions.SchemaNotFoundException;
import com.jacobmountain.graphql.client.utils.Schema;
import com.jacobmountain.graphql.client.utils.StringUtils;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Set;
import java.util.function.Consumer;

@Slf4j
@AutoService(Processor.class)
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("com.jacobmountain.graphql.client.*")
public class GraphQLClientProcessor extends AbstractProcessor {

    private Filer filer;

    private Messager messager;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        this.filer = processingEnv.getFiler();
        this.messager = processingEnv.getMessager();
    }

    private Path root;

    @Override
    @SneakyThrows
    public boolean process(Set annotations, RoundEnvironment roundEnv) {
        Set elements = roundEnv.getElementsAnnotatedWith(GraphQLClient.class);
        for (Element el : elements) {
            if (!(el.getKind() == ElementKind.CLASS || el.getKind() == ElementKind.INTERFACE)) {
                messager.printMessage(Diagnostic.Kind.ERROR, "Can't be applied to class");
                return true;
            }
        }
        return elements.stream()
                .map(el -> (TypeElement) el)
                .map(Input::new)
                .peek(this.generateJavaDataClasses())
                .peek(this::generateClientImplementation)
                .count() > 0;
    }

    private Consumer generateJavaDataClasses() {
        return input -> {
            log.info("Generating java classes from GraphQL schema");
            DTOGenerator dtoGenerator = new DTOGenerator(input.getDtoPackage(), new FileWriter(this.filer), input.getTypeMapper());
            dtoGenerator.generate(input.getSchema().types().values());
            dtoGenerator.generateArgumentDTOs(input.element);
        };
    }

    private void generateClientImplementation(Input client) {
        GraphQLClient annotation = client.getAnnotation();
        log.info("Generating java implementation of {}", client.element.getSimpleName());
        new ClientGenerator(this.filer, client.getTypeMapper(), client.getPackage(), client.getDtoPackage(), client.getSchema(), annotation.reactive())
                .generate(client.element, annotation.implSuffix());
    }

    @SneakyThrows
    private Path getRoot() {
        if (root == null) {
            FileObject resource = filer.createResource(StandardLocation.CLASS_OUTPUT, "", "tmp", (Element[]) null);
            root = Paths.get(resource.toUri()).getParent().getParent().getParent().getParent().getParent();
            resource.delete();
        }
        return root;
    }

    @Value
    @AllArgsConstructor
    private class Input {

        TypeElement element;

        GraphQLClient getAnnotation() {
            return element.getAnnotation(GraphQLClient.class);
        }

        TypeMapper getTypeMapper() {
            return new TypeMapper(getDtoPackage(), getAnnotation().mapping());
        }

        String getDtoPackage() {
            return String.join(".", Arrays.asList(
                    getPackage(),
                    getAnnotation().dtoPackage()
            ));
        }

        String getPackage() {
            return processingEnv.getElementUtils().getPackageOf(element).toString();
        }

        Schema getSchema() {
            String value = getAnnotation().schema();
            File file = getSchemaFile();
            try {
                if (StringUtils.hasLength(value)) {
                    log.info("Reading schema {}", file);
                    return new Schema(getSchemaFile());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            throw new SchemaNotFoundException(file.getPath());
        }

        File getSchemaFile() {
            return getRoot().resolve(getAnnotation().schema())
                    .toAbsolutePath()
                    .toFile();
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy