/* * Copyright 2015 Workday, Inc. * Copyright 2016 Google, Inc. * * This software is available under the MIT license. * Please see the LICENSE.txt file in this project. */ package com.workday.postman.codegen; import com.workday.postman.annotations.NotParceled; import com.workday.postman.annotations.Parceled; import com.workday.postman.annotations.PostCreateChild; import com.workday.postman.parceler.Parceler; import com.workday.postman.util.CollectionUtils; import java.io.IOException; import java.lang.annotation.Annotation; import java.util.HashSet; import java.util.Locale; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Processor; import javax.annotation.processing.RoundEnvironment; 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; /** * The {@link Processor} that handles {@literal @}{@link Parceled} and {@literal @}{@link * NotParceled} annotations and generates implemenations of {@link Parceler}. * * @author nathan.taylor * @since 2013-9-25-14:58 */ public class PostmanProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { if (annotations == null || annotations.isEmpty()) { return false; } final Set<TypeElement> handledElements = new HashSet<>(); Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(Parceled.class); for (Element e : annotatedElements) { ElementKind kind = e.getKind(); if (kind == ElementKind.FIELD) { TypeElement parent = (TypeElement) e.getEnclosingElement(); handledElements.add(parent); } else if (kind == ElementKind.CLASS) { handledElements.add((TypeElement) e); } } checkIfParentsParceled(roundEnv, handledElements, NotParceled.class); checkIfParentsParceled(roundEnv, handledElements, PostCreateChild.class); for (TypeElement handledElement : handledElements) { ParcelerGenerator generator = new ParcelerGenerator(processingEnv, handledElement); try { generator.generateParceler(); } catch (IOException e) { processingEnv.getMessager() .printMessage(Diagnostic.Kind.ERROR, e.getMessage(), handledElement); } } return true; } private void checkIfParentsParceled(RoundEnvironment roundEnv, Set<TypeElement> handledElements, Class<? extends Annotation> annotationType) { Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotationType); for (Element e : annotatedElements) { TypeElement parent = (TypeElement) e.getEnclosingElement(); if (!handledElements.contains(parent)) { final String message = String.format(Locale.US, "You marked an element with @%s in a class " + "that has no @%s annotations. The " + "enclosing class will not be " + "parceled.", annotationType.getSimpleName(), Parceled.class.getSimpleName()); processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message, e); } } } @Override public Set<String> getSupportedAnnotationTypes() { return CollectionUtils.newHashSet(Parceled.class.getCanonicalName(), NotParceled.class.getCanonicalName(), PostCreateChild.class.getCanonicalName()); } @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } }