package org.rakam.server.http; import org.rakam.server.http.annotations.JsonRequest; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeKind; import javax.tools.Diagnostic; import javax.ws.rs.Path; import java.util.Set; import static java.lang.String.format; @SupportedAnnotationTypes( {"org.rakam.server.Service", "org.rakam.server.annotations.JsonRequest"} ) public class HttpServiceProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> typeElements, RoundEnvironment roundEnvironment) { final ProcessingEnvironment env = super.processingEnv; Messager messager = env.getMessager(); Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Service.class); for (Element element : elements) { Path annotation = element.getAnnotation(Path.class); if(annotation == null) { messager.printMessage(Diagnostic.Kind.ERROR, format("%s class extends HttpService but doesn't have javax.ws.rs.Path annotation. " + "HttpService subclasses must have it in order to define their scope.", element.toString())); } } Set<? extends Element> jsonMethods = roundEnvironment.getElementsAnnotatedWith(JsonRequest.class); for (Element element : jsonMethods) { Path annotation = element.getAnnotation(Path.class); if(annotation == null) { messager.printMessage(Diagnostic.Kind.ERROR, format("%s class has %s but %s annotation but doesn't have %s annotation", element.toString(), JsonRequest.class.getCanonicalName(), Path.class.getCanonicalName())); } // we know that JsonRequest can only be used in method declarations so the Type must be ExecutableElement if(((ExecutableElement) element.asType()).getReturnType().getKind() == TypeKind.VOID) { messager.printMessage(Diagnostic.Kind.ERROR, format("%s method can't have void return type because it has %s annotation", element.toString(), JsonRequest.class.getCanonicalName())); } if(((ExecutableElement) element.asType()).getParameters().size() != 1) { messager.printMessage(Diagnostic.Kind.ERROR, format("%s method must have exactly one parameter because it has %s annotation", element.toString(), JsonRequest.class.getCanonicalName())); } } return true; } @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } }