001package ball.http.annotation.processing; 002/*- 003 * ########################################################################## 004 * Web API Client (HTTP) Utilities 005 * $Id: ProtocolJSR311AnnotationProcessor.java 5877 2020-05-04 22:00:56Z ball $ 006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-http/trunk/src/main/java/ball/http/annotation/processing/ProtocolJSR311AnnotationProcessor.java $ 007 * %% 008 * Copyright (C) 2016 - 2020 Allen D. Ball 009 * %% 010 * Licensed under the Apache License, Version 2.0 (the "License"); 011 * you may not use this file except in compliance with the License. 012 * You may obtain a copy of the License at 013 * 014 * http://www.apache.org/licenses/LICENSE-2.0 015 * 016 * Unless required by applicable law or agreed to in writing, software 017 * distributed under the License is distributed on an "AS IS" BASIS, 018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 019 * See the License for the specific language governing permissions and 020 * limitations under the License. 021 * ########################################################################## 022 */ 023import ball.annotation.ServiceProviderFor; 024import ball.annotation.processing.AnnotatedProcessor; 025import ball.annotation.processing.For; 026import ball.http.annotation.Protocol; 027import java.lang.annotation.Annotation; 028import java.util.Set; 029import javax.annotation.processing.Processor; 030import javax.annotation.processing.RoundEnvironment; 031import javax.lang.model.element.AnnotationMirror; 032import javax.lang.model.element.AnnotationValue; 033import javax.lang.model.element.Element; 034import javax.lang.model.element.ExecutableElement; 035import javax.lang.model.element.TypeElement; 036import javax.ws.rs.DELETE; 037import javax.ws.rs.GET; 038import javax.ws.rs.HEAD; 039import javax.ws.rs.OPTIONS; 040import javax.ws.rs.PATCH; 041import javax.ws.rs.POST; 042import javax.ws.rs.PUT; 043import lombok.NoArgsConstructor; 044import lombok.ToString; 045 046import static java.util.stream.Collectors.toSet; 047import static javax.tools.Diagnostic.Kind.ERROR; 048import static lombok.AccessLevel.PROTECTED; 049 050/** 051 * Abstract base class for {@link javax.ws.rs JSR 311} {@link Annotation} 052 * {@link Processor} for {@link Protocol} interface methods. 053 * 054 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 055 * @version $Revision: 5877 $ 056 */ 057@NoArgsConstructor(access = PROTECTED) 058public abstract class ProtocolJSR311AnnotationProcessor 059 extends AnnotatedProcessor { 060 @Override 061 public void process(RoundEnvironment roundEnv, 062 TypeElement annotation, Element element) { 063 super.process(roundEnv, annotation, element); 064 065 switch (element.getKind()) { 066 case METHOD: 067 TypeElement type = (TypeElement) element.getEnclosingElement(); 068 069 switch (type.getKind()) { 070 case INTERFACE: 071 if (type.getAnnotation(Protocol.class) != null) { 072 check(annotation, type, (ExecutableElement) element); 073 } 074 break; 075 076 default: 077 break; 078 } 079 break; 080 } 081 } 082 083 /** 084 * Method to check an annotated interface method. 085 * 086 * @param annotation The annotation being processed. 087 * @param type The interface containing the method. 088 * @param method The annotated method. 089 */ 090 protected abstract void check(TypeElement annotation, 091 TypeElement type, ExecutableElement method); 092 093 /** 094 * {@link javax.ws.rs JSR 311} method {@link Annotation} 095 * {@link Processor}. 096 */ 097 @ServiceProviderFor({ Processor.class }) 098 @For({ 099 DELETE.class, GET.class, HEAD.class, OPTIONS.class, 100 PATCH.class, POST.class, PUT.class 101 }) 102 @NoArgsConstructor @ToString 103 public static class Method extends ProtocolJSR311AnnotationProcessor { 104 @Override 105 protected void check(TypeElement annotation, 106 TypeElement type, ExecutableElement method) { 107 Set<Class<? extends Annotation>> set = 108 getSupportedAnnotationTypeList().stream() 109 .filter(t -> method.getAnnotation(t) != null) 110 .collect(toSet()); 111 112 switch (set.size()) { 113 case 0: 114 throw new IllegalStateException(); 115 /* 116 * break; 117 */ 118 case 1: 119 AnnotationMirror mirror = 120 getAnnotationMirror(method, annotation); 121 AnnotationValue value = getAnnotationValue(mirror, "value"); 122 break; 123 124 default: 125 print(ERROR, method, 126 "%s may only be annotated with one of %s", 127 method.getKind(), 128 set.stream() 129 .map(t -> "@" + t.getSimpleName()) 130 .collect(toSet())); 131 break; 132 } 133 } 134 } 135}