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

com.github.dynodao.processor.DynoDaoProcessor Maven / Gradle / Ivy

package com.github.dynodao.processor;

import com.github.dynodao.annotation.DynoDaoSchema;
import com.github.dynodao.processor.context.ProcessorContext;
import com.github.dynodao.processor.context.ProcessorMessager;
import com.github.dynodao.processor.schema.DynamoSchema;
import com.github.dynodao.processor.schema.DynamoSchemaParser;
import com.github.dynodao.processor.schema.index.DynamoIndex;
import com.github.dynodao.processor.serialize.SerializerTypeSpec;
import com.github.dynodao.processor.serialize.SerializerTypeSpecFactory;
import com.github.dynodao.processor.stage.KeyLengthType;
import com.github.dynodao.processor.stage.Stage;
import com.github.dynodao.processor.stage.StageTypeSpec;
import com.github.dynodao.processor.stage.StageTypeSpecFactory;
import com.google.auto.service.AutoService;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.inject.Inject;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import static java.util.stream.Collectors.toSet;

/**
 * The annotation processor for {@link DynoDaoSchema}.
 */
@AutoService(Processor.class)
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("com.github.dynodao.annotation.DynoDaoSchema")
public class DynoDaoProcessor extends AbstractProcessor {

    @Inject ProcessorContext processorContext;
    @Inject ProcessorMessager processorMessager;
    @Inject DynamoSchemaParser dynamoSchemaParser;
    @Inject SerializerTypeSpecFactory serializerTypeSpecFactory;
    @Inject StageTypeSpecFactory stageTypeSpecFactory;
    @Inject TypeSpecWriter typeSpecWriter;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        DaggerObjectGraph.builder()
                .contextModule(new ContextModule(new ProcessorContext(processingEnv)))
                .build().inject(this);
    }

    @Override
    public boolean process(Set annotations, RoundEnvironment roundEnv) {
        processorContext.newRound(roundEnv);
        if (!roundEnv.processingOver()) {
            Set elementsToProcess = findElementsToProcess(annotations);
            processElements(elementsToProcess);
            processorMessager.emitMessages();
        }
        return false;
    }

    private Set findElementsToProcess(Set annotations) {
        return annotations.stream()
                .map(processorContext.getRoundEnvironment()::getElementsAnnotatedWith)
                .flatMap(Set::stream)
                .filter(element -> element.getKind().equals(ElementKind.CLASS))
                .map(element -> (TypeElement) element)
                .collect(toSet());
    }

    private void processElements(Set elements) {
        for (TypeElement documentElement : elements) {
            try {
                processDocumentElement(documentElement);
            } catch (RuntimeException e) {
                processorMessager.submitError("DynoDaoProcessor had uncaught exception: %s\n"
                        + "DynoDao tries to continue processing even when it enters an error state in an effort to report all errors, check for others!", e.getMessage());
                e.printStackTrace();
            }
        }
    }

    private void processDocumentElement(TypeElement documentElement) {
        DynamoSchema schema = dynamoSchemaParser.parse(documentElement);
        SerializerTypeSpec serializer = serializerTypeSpecFactory.build(schema);

        List builtTypes = new ArrayList<>();
        builtTypes.add(serializer);

        Stage stagedBuilder = new Stage(schema, serializer);
        for (DynamoIndex index : schema.getIndexes()) {
            KeyLengthType keyLengthType = KeyLengthType.lengthOf(index);

            Optional indexRangeKeyPojo = getIndexRangeKeyStage(schema, serializer, index, keyLengthType);
            StageTypeSpec indexHashKeyPojo = getIndexHashKeyStage(schema, serializer, index, indexRangeKeyPojo);
            StageTypeSpec indexPojo = getIndexStage(schema, serializer, index, indexHashKeyPojo);

            stagedBuilder.addUser(indexPojo);

            indexRangeKeyPojo.ifPresent(builtTypes::add);
            builtTypes.add(indexHashKeyPojo);
            builtTypes.add(indexPojo);
        }
        builtTypes.add(toTypeSpec(stagedBuilder));
        typeSpecWriter.writeAll(builtTypes);
    }

    private Optional getIndexRangeKeyStage(DynamoSchema schema, SerializerTypeSpec serializer, DynamoIndex index, KeyLengthType keyLengthType) {
        if (keyLengthType.equals(KeyLengthType.RANGE)) {
            Stage pojo = new Stage(schema, serializer)
                    .withIndex(index, keyLengthType);
            return Optional.of(toTypeSpec(pojo));
        } else {
            return Optional.empty();
        }
    }

    private StageTypeSpec getIndexHashKeyStage(DynamoSchema schema, SerializerTypeSpec serializer, DynamoIndex index, Optional indexRangeKeyStage) {
        Stage pojo = new Stage(schema, serializer)
                .withIndex(index, KeyLengthType.HASH);
        indexRangeKeyStage.ifPresent(pojo::addWither);
        return toTypeSpec(pojo);
    }

    private StageTypeSpec getIndexStage(DynamoSchema schema, SerializerTypeSpec serializer, DynamoIndex index, StageTypeSpec indexHashKeyStage) {
        Stage pojo = new Stage(schema, serializer)
                .withIndex(index, KeyLengthType.NONE)
                .addWither(indexHashKeyStage);
        return toTypeSpec(pojo);
    }

    private StageTypeSpec toTypeSpec(Stage pojo) {
        return stageTypeSpecFactory.build(pojo);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy