From a2e34c959f031deef72e84d8f268ac1c54111e7e Mon Sep 17 00:00:00 2001 From: Olivier Girardot Date: Mon, 2 Mar 2015 15:13:06 +0100 Subject: [PATCH 1/8] Handle BeanParam annotations as added QueryParam(s) --- .../VariableElementToQueryParameter.java | 7 +-- .../jax_rs_linker/model/QueryParameter.java | 19 +++---- .../jax_rs_linker/parser/ElementParser.java | 54 ++++++++++++------- .../jax_rs_linker/writer/LinkerWriter.java | 11 ++-- .../LinkerAnnotationProcessorTest.java | 2 +- .../oss/jax_rs_linker/model/ApiQueryTest.java | 2 +- .../model/QueryParameterTest.java | 20 ++----- .../parser/ElementParserTest.java | 28 ++++++++++ .../jax_rs_linker/parser/ProductResource.java | 7 ++- .../writer/EnumConstantsTest.java | 1 - .../test/resources/BrandResourceLinker.java | 4 +- .../test/resources/DevNullResourceLinker.java | 4 +- .../src/test/resources/PersonResource.java | 5 +- .../test/resources/PersonResourceLinker.java | 28 +++++++--- .../test/resources/ProductResourceLinker.java | 4 +- 15 files changed, 110 insertions(+), 86 deletions(-) diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/functions/VariableElementToQueryParameter.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/functions/VariableElementToQueryParameter.java index 871294f..b750fce 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/functions/VariableElementToQueryParameter.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/functions/VariableElementToQueryParameter.java @@ -1,23 +1,20 @@ package fr.vidal.oss.jax_rs_linker.functions; import com.google.common.base.Function; -import fr.vidal.oss.jax_rs_linker.model.ClassName; import fr.vidal.oss.jax_rs_linker.model.QueryParameter; import javax.annotation.Nullable; import javax.lang.model.element.VariableElement; import javax.ws.rs.QueryParam; -public enum VariableElementToQueryParameter implements Function{ +public enum VariableElementToQueryParameter implements Function { INTO_QUERY_PARAMETER; @Nullable @Override public QueryParameter apply(VariableElement parameterElement) { - return new QueryParameter( - ClassName.valueOf(parameterElement.getEnclosingElement().getEnclosingElement().getSimpleName().toString()), - parameterElement.getAnnotation(QueryParam.class).value()); + return new QueryParameter(parameterElement.getAnnotation(QueryParam.class).value()); } } diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/QueryParameter.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/QueryParameter.java index 3ffd333..fb61e4d 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/QueryParameter.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/model/QueryParameter.java @@ -6,21 +6,15 @@ public class QueryParameter { private String name; - private ClassName className; - public QueryParameter(ClassName className, String name) { + public QueryParameter(String name) { this.name = name; - this.className = className; } public String getName() { return name; } - public ClassName getClassName() { - return className; - } - @Override public boolean equals(Object obj) { if (this == obj) { @@ -30,19 +24,18 @@ public boolean equals(Object obj) { return false; } final QueryParameter other = (QueryParameter) obj; - return Objects.equal(this.className, other.className) && Objects.equal(this.name, other.name); + return Objects.equal(this.name, other.name); } @Override public int hashCode() { - return Objects.hashCode(className, name); + return Objects.hashCode(name); } @Override public String toString() { - return "QueryParameter { " + - "name='" + name + "\'" + - ", className='" + className + - "' }"; + return "QueryParameter{" + + "name='" + name + '\'' + + '}'; } } diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java index e2f39ad..629cbb5 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java @@ -10,9 +10,12 @@ import javax.annotation.processing.Messager; import javax.lang.model.element.*; +import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Types; +import javax.ws.rs.BeanParam; import javax.ws.rs.QueryParam; import java.util.Collection; +import java.util.List; import static com.google.common.base.Optional.absent; import static com.google.common.base.Preconditions.checkArgument; @@ -23,7 +26,6 @@ import static fr.vidal.oss.jax_rs_linker.functions.VariableElementToQueryParameter.INTO_QUERY_PARAMETER; import static fr.vidal.oss.jax_rs_linker.predicates.AnnotationMirrorByNamePredicate.byName; import static fr.vidal.oss.jax_rs_linker.predicates.UnparseableValuePredicate.IS_UNPARSEABLE; - import static javax.tools.Diagnostic.Kind.ERROR; public class ElementParser { @@ -32,11 +34,13 @@ public class ElementParser { private final PathVisitor pathVisitor; private final ClassWorkLoad workLoad; private final HttpVerbVisitor httpVerbVisitor; + private final Types typeUtils; public ElementParser(Messager messager, Types typeUtils) { this.messager = messager; + this.typeUtils = typeUtils; this.pathVisitor = new PathVisitor(typeUtils); this.workLoad = ClassWorkLoad.init(); this.httpVerbVisitor = new HttpVerbVisitor(); @@ -91,21 +95,21 @@ private Optional link(ExecutableElement methodElement, boolean withSelf private Optional relatedResourceName(ExecutableElement methodElement) { return FluentIterable.from(methodElement.getAnnotationMirrors()) - .filter(byName("SubResource")) - .transform(TO_METHOD_VALUE_ENTRIES) - .transform(TO_STRING_VALUE) - .firstMatch(not(IS_UNPARSEABLE)); + .filter(byName("SubResource")) + .transform(TO_METHOD_VALUE_ENTRIES) + .transform(TO_STRING_VALUE) + .firstMatch(not(IS_UNPARSEABLE)); } private Mapping mapping(ExecutableElement methodElement, ApiLink link, HttpVerb httpVerb, String path) { return new Mapping( - javaLocation(methodElement), - api( - link, - httpVerb, - apiPath(methodElement, path), - apiQuery(methodElement.getParameters()) - ) + javaLocation(methodElement), + api( + link, + httpVerb, + apiPath(methodElement, path), + apiQuery(methodElement.getParameters()) + ) ); } @@ -127,23 +131,23 @@ private Optional trackMandatoryParsing(ApiLink link, Mapping m private JavaLocation javaLocation(ExecutableElement methodElement) { return new JavaLocation( - className(methodElement), - methodElement.getSimpleName().toString() + className(methodElement), + methodElement.getSimpleName().toString() ); } private Api api(ApiLink link, HttpVerb httpVerb, ApiPath apiPath, ApiQuery apiQuery) { return new Api( - httpVerb, - link, - apiPath, - apiQuery); + httpVerb, + link, + apiPath, + apiQuery); } private ApiPath apiPath(ExecutableElement methodElement, String path) { return new ApiPath( - path, - pathVisitor.visitPathParameters(methodElement) + path, + pathVisitor.visitPathParameters(methodElement) ); } @@ -154,6 +158,16 @@ private ApiQuery apiQuery(Collection parameters) { if (annotation != null) { queryParameters.add(INTO_QUERY_PARAMETER.apply(variableElement)); } + // handle bean params : + BeanParam beanParam = variableElement.getAnnotation(BeanParam.class); + if (beanParam != null) { + List constructorsIn = ElementFilter.constructorsIn(typeUtils.asElement(variableElement.asType()).getEnclosedElements()); + for (ExecutableElement ctor : constructorsIn) { + for (VariableElement ctorParameter : ctor.getParameters()) { + queryParameters.add(INTO_QUERY_PARAMETER.apply(ctorParameter)); + } + } + } } return new ApiQuery(queryParameters); } diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/writer/LinkerWriter.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/writer/LinkerWriter.java index a2dad12..878952a 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/writer/LinkerWriter.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/writer/LinkerWriter.java @@ -158,12 +158,11 @@ private String pathParametersAsList(Collection pathParameters) { private String queryParametersAsList(Collection queryParameters) { StringBuilder builder = new StringBuilder(); Iterator iterator = queryParameters.iterator(); - while(iterator.hasNext()) { + while (iterator.hasNext()) { QueryParameter parameter = iterator.next(); String separator = iterator.hasNext() ? "," : ""; builder.append(String.format( - "queryParameter(\"%s\", \"%s\")%s", - parameter.getClassName(), + "queryParameter(\"%s\")%s", parameter.getName(), separator )); @@ -194,15 +193,11 @@ private MethodSpec queryParameterMethod() { return MethodSpec.methodBuilder("queryParameter") .returns(QueryParameter.class) .addModifiers(PRIVATE, STATIC) - .addParameter( - ParameterSpec.builder(String.class, "type", FINAL).build()) .addParameter( ParameterSpec.builder(String.class, "name", FINAL).build()) .addStatement( - "return new $T($T.valueOf($L), $L)", + "return new $T($L)", QueryParameter.class, - ClassName.class, - "type", "name" ) .build(); diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/LinkerAnnotationProcessorTest.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/LinkerAnnotationProcessorTest.java index 5ccb08a..3b13124 100644 --- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/LinkerAnnotationProcessorTest.java +++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/LinkerAnnotationProcessorTest.java @@ -34,11 +34,11 @@ public void generates_graph_of_linkers() { .and() .generatesSources( forResource("ProductResourceLinker.java"), + forResource("PersonResourceLinker.java"), forResource("BrandResourceLinker.java"), forResource("ProductResourcePathParameters.java"), forResource("BrandResourcePathParameters.java"), forResource("PersonResourcePathParameters.java"), - forResource("PersonResourcePathParameters.java"), forResource("PersonResourceQueryParameters.java"), forResource("linkers/Linkers.java") ); diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/ApiQueryTest.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/ApiQueryTest.java index 34c9001..58d80a5 100644 --- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/ApiQueryTest.java +++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/ApiQueryTest.java @@ -23,7 +23,7 @@ public void equals_should_return_true_if_object_are_identical() { @Test public void toString_should_return_a_valid_string_representation() { - Collection queryParameters = newArrayList(new QueryParameter(ClassName.valueOf("fr.vidal.oss.Foo"),"Foo"),new QueryParameter(ClassName.valueOf("fr.vidal.oss.Bar"),"Bar") ); + Collection queryParameters = newArrayList(new QueryParameter("Foo"),new QueryParameter("Bar") ); ApiQuery apiQuery = new ApiQuery(queryParameters); assertThat(apiQuery.toString()).isEqualTo("ApiQuery{queryParameters=[FooBar]}"); diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/QueryParameterTest.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/QueryParameterTest.java index a412b34..b57e726 100644 --- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/QueryParameterTest.java +++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/model/QueryParameterTest.java @@ -8,7 +8,7 @@ public class QueryParameterTest { @Test public void equals_should_return_true_if_objects_are_identical() { - QueryParameter queryParameter = new QueryParameter(ClassName.valueOf("fr.vidal.oss.Foo"),"Foo"); + QueryParameter queryParameter = new QueryParameter("Foo"); QueryParameter queryParameter1 = queryParameter; assertThat(queryParameter).isEqualTo(queryParameter1); @@ -16,7 +16,7 @@ public void equals_should_return_true_if_objects_are_identical() { @Test public void equals_should_return_false_if_object_is_null() { - QueryParameter queryParameter = new QueryParameter(ClassName.valueOf("fr.vidal.oss.Foo"),"Foo"); + QueryParameter queryParameter = new QueryParameter("Foo"); QueryParameter queryParameter1 = null; assertThat(queryParameter).isNotEqualTo(queryParameter1); @@ -24,26 +24,16 @@ public void equals_should_return_false_if_object_is_null() { @Test public void equals_should_return_false_Objects_have_not_the_same_class() { - QueryParameter queryParameter = new QueryParameter(ClassName.valueOf("fr.vidal.oss.Foo"),"Foo"); + QueryParameter queryParameter = new QueryParameter("Foo"); String queryParameter1 = "baz"; assertThat(queryParameter).isNotEqualTo(queryParameter1); } - @Test - public void equals_should_return_false_Objects_are_not_deeply_identical() { - QueryParameter queryParameter = new QueryParameter(ClassName.valueOf("fr.vidal.oss.Foo"),"Foo"); - QueryParameter queryParameter1 = new QueryParameter(ClassName.valueOf("fr.vidal.oss.Foo"),"Bar"); - QueryParameter queryParameter2 = new QueryParameter(ClassName.valueOf("fr.vidal.oss.FooBaz"),"Foo"); - - assertThat(queryParameter).isNotEqualTo(queryParameter1); - assertThat(queryParameter).isNotEqualTo(queryParameter2); - } - @Test public void toString_should_return_a_valid_string() { - QueryParameter queryParameter = new QueryParameter(ClassName.valueOf("fr.vidal.oss.Foo"),"Foo"); + QueryParameter queryParameter = new QueryParameter("Foo"); - assertThat(queryParameter.toString()).isEqualTo("QueryParameter { name='Foo', className='fr.vidal.oss.Foo' }"); + assertThat(queryParameter.toString()).isEqualTo("QueryParameter{name='Foo'}"); } } diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java index 9218b39..7d8a3dc 100644 --- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java +++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java @@ -57,6 +57,34 @@ public void parses_method_to_mapping_representation() { .containsExactly(new PathParameter(ClassName.valueOf("int"), "id")); } + @Test + public void parses_method_to_mapping_representation_with_bean_param() { + ExecutableElement method = methodElements.of( + "fr.vidal.oss.jax_rs_linker.parser.ProductResource", + "productById" + ); + + Mapping mapping = parser.parse(method).get(); + + JavaLocation javaLocation = mapping.getJavaLocation(); + assertThat(javaLocation.getClassName().fullyQualifiedName()) + .isEqualTo("fr.vidal.oss.jax_rs_linker.parser.ProductResource"); + assertThat(javaLocation.getMethodName()) + .isEqualTo("productById"); + + Api api = mapping.getApi(); + assertThat(api.getApiPath().getPath()) + .isEqualTo("/api/product/{id}"); + assertThat(api.getApiPath().getPathParameters()) + .containsExactly(new PathParameter(ClassName.valueOf("int"), "id")); + assertThat(api.getApiQuery().getQueryParameters()) + .hasSize(2) + .containsExactly( + new QueryParameter("start-page"), + new QueryParameter("page-size") + ); + } + @Test public void fails_to_parse_because_of_absence_of_path() { ExecutableElement method = methodElements.of( diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ProductResource.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ProductResource.java index c3fa57d..e979bf5 100644 --- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ProductResource.java +++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ProductResource.java @@ -1,10 +1,9 @@ package fr.vidal.oss.jax_rs_linker.parser; import fr.vidal.oss.jax_rs_linker.api.Self; +import fr.vidal.oss.jax_rs_linker.api.SubResource; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; +import javax.ws.rs.*; @Path("/api/product") public class ProductResource { @@ -12,7 +11,7 @@ public class ProductResource { @GET @Path("/{id}") @Self - public String productById(@PathParam("id") int id) { + public String productById(@PathParam("id") int id, @BeanParam PagingTest paging) { return ""; } } diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/writer/EnumConstantsTest.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/writer/EnumConstantsTest.java index b27a8c8..a67a296 100644 --- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/writer/EnumConstantsTest.java +++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/writer/EnumConstantsTest.java @@ -1,6 +1,5 @@ package fr.vidal.oss.jax_rs_linker.writer; - import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; diff --git a/jax-rs-linker/src/test/resources/BrandResourceLinker.java b/jax-rs-linker/src/test/resources/BrandResourceLinker.java index 712e510..1b3990b 100644 --- a/jax-rs-linker/src/test/resources/BrandResourceLinker.java +++ b/jax-rs-linker/src/test/resources/BrandResourceLinker.java @@ -38,7 +38,7 @@ private static PathParameter pathParameter(final String type, final String name) return new PathParameter(ClassName.valueOf(type), name); } - private static QueryParameter queryParameter(final String type, final String name) { - return new QueryParameter(ClassName.valueOf(type), name); + private static QueryParameter queryParameter(final String name) { + return new QueryParameter(name); } } diff --git a/jax-rs-linker/src/test/resources/DevNullResourceLinker.java b/jax-rs-linker/src/test/resources/DevNullResourceLinker.java index b352416..37df10c 100644 --- a/jax-rs-linker/src/test/resources/DevNullResourceLinker.java +++ b/jax-rs-linker/src/test/resources/DevNullResourceLinker.java @@ -30,7 +30,7 @@ private static PathParameter pathParameter(final String type, final String name) return new PathParameter(ClassName.valueOf(type), name); } - private static QueryParameter queryParameter(final String type, final String name) { - return new QueryParameter(ClassName.valueOf(type), name); + private static QueryParameter queryParameter(final String name) { + return new QueryParameter(name); } } diff --git a/jax-rs-linker/src/test/resources/PersonResource.java b/jax-rs-linker/src/test/resources/PersonResource.java index 7d0a1e7..50d43e6 100644 --- a/jax-rs-linker/src/test/resources/PersonResource.java +++ b/jax-rs-linker/src/test/resources/PersonResource.java @@ -3,10 +3,7 @@ import fr.vidal.oss.jax_rs_linker.api.Self; import fr.vidal.oss.jax_rs_linker.api.SubResource; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; +import javax.ws.rs.*; @Path("/person") public class PersonResource { diff --git a/jax-rs-linker/src/test/resources/PersonResourceLinker.java b/jax-rs-linker/src/test/resources/PersonResourceLinker.java index 1d23bcc..fe823d7 100644 --- a/jax-rs-linker/src/test/resources/PersonResourceLinker.java +++ b/jax-rs-linker/src/test/resources/PersonResourceLinker.java @@ -1,26 +1,38 @@ - package fr.vidal.oss.jax_rs_linker.parser; -import fr.vidal.oss.jax_rs_linker.model.*; - +import fr.vidal.oss.jax_rs_linker.model.ClassName; +import fr.vidal.oss.jax_rs_linker.model.PathParameter; +import fr.vidal.oss.jax_rs_linker.model.QueryParameter; +import fr.vidal.oss.jax_rs_linker.model.TemplatedUrl; +import java.lang.String; import java.util.Arrays; import javax.annotation.Generated; @Generated("fr.vidal.oss.jax_rs_linker.LinkerAnnotationProcessor") -public class PersonResourceLinker { - +public final class PersonResourceLinker { private final String contextPath; public PersonResourceLinker() { this(""); } - public PersonResourceLinker(String contextPath) { + public PersonResourceLinker(final String contextPath) { this.contextPath = contextPath; } - public TemplatedUrl self() { - return new TemplatedUrl(contextPath, Arrays.asList(new PathParameter(ClassName.valueOf("int"), "id")), queryParameters); + public final TemplatedUrl self() { + return new TemplatedUrl(contextPath + "/person/{id}", Arrays.asList(pathParameter("int", "id")), Arrays.asList(queryParameter("alive-flag"))); + } + + public final TemplatedUrl relatedPersonResource() { + return new TemplatedUrl(contextPath + "/person/name/{firstName}", Arrays.asList(pathParameter("java.lang.String", "firstName")), Arrays.asList()); + } + + private static PathParameter pathParameter(final String type, final String name) { + return new PathParameter(ClassName.valueOf(type), name); } + private static QueryParameter queryParameter(final String name) { + return new QueryParameter(name); + } } diff --git a/jax-rs-linker/src/test/resources/ProductResourceLinker.java b/jax-rs-linker/src/test/resources/ProductResourceLinker.java index 923576a..c07bc10 100644 --- a/jax-rs-linker/src/test/resources/ProductResourceLinker.java +++ b/jax-rs-linker/src/test/resources/ProductResourceLinker.java @@ -34,7 +34,7 @@ private static PathParameter pathParameter(final String type, final String name) return new PathParameter(ClassName.valueOf(type), name); } - private static QueryParameter queryParameter(final String type, final String name) { - return new QueryParameter(ClassName.valueOf(type), name); + private static QueryParameter queryParameter(final String name) { + return new QueryParameter(name); } } From af67ed6a3a097e79674de8b227afab890486cde2 Mon Sep 17 00:00:00 2001 From: Olivier Girardot Date: Mon, 2 Mar 2015 16:18:15 +0100 Subject: [PATCH 2/8] Respect line size limit --- .../fr/vidal/oss/jax_rs_linker/parser/ElementParser.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java index 629cbb5..3d091b8 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java @@ -161,8 +161,9 @@ private ApiQuery apiQuery(Collection parameters) { // handle bean params : BeanParam beanParam = variableElement.getAnnotation(BeanParam.class); if (beanParam != null) { - List constructorsIn = ElementFilter.constructorsIn(typeUtils.asElement(variableElement.asType()).getEnclosedElements()); - for (ExecutableElement ctor : constructorsIn) { + Element beanParamTargetClass = typeUtils.asElement(variableElement.asType()); + List ctors = ElementFilter.constructorsIn(beanParamTargetClass.getEnclosedElements()); + for (ExecutableElement ctor : ctors) { for (VariableElement ctorParameter : ctor.getParameters()) { queryParameters.add(INTO_QUERY_PARAMETER.apply(ctorParameter)); } From c6fec15f1d74b977bf6fa435ae613ad2c12f8169 Mon Sep 17 00:00:00 2001 From: Olivier Girardot Date: Mon, 2 Mar 2015 17:39:19 +0100 Subject: [PATCH 3/8] Remove comment on bean param handling --- .../java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java | 1 - 1 file changed, 1 deletion(-) diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java index 3d091b8..858e704 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java @@ -158,7 +158,6 @@ private ApiQuery apiQuery(Collection parameters) { if (annotation != null) { queryParameters.add(INTO_QUERY_PARAMETER.apply(variableElement)); } - // handle bean params : BeanParam beanParam = variableElement.getAnnotation(BeanParam.class); if (beanParam != null) { Element beanParamTargetClass = typeUtils.asElement(variableElement.asType()); From 519d140f38c4a123ee3c0ab1f6715a1b742d42dc Mon Sep 17 00:00:00 2001 From: Olivier Girardot Date: Mon, 2 Mar 2015 17:55:39 +0100 Subject: [PATCH 4/8] Add fields and setter handling of query param annotation for BeanParams --- ...eter.java => ElementToQueryParameter.java} | 5 +++-- .../jax_rs_linker/parser/ElementParser.java | 20 ++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) rename jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/functions/{VariableElementToQueryParameter.java => ElementToQueryParameter.java} (69%) diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/functions/VariableElementToQueryParameter.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/functions/ElementToQueryParameter.java similarity index 69% rename from jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/functions/VariableElementToQueryParameter.java rename to jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/functions/ElementToQueryParameter.java index b750fce..f3a55e4 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/functions/VariableElementToQueryParameter.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/functions/ElementToQueryParameter.java @@ -4,16 +4,17 @@ import fr.vidal.oss.jax_rs_linker.model.QueryParameter; import javax.annotation.Nullable; +import javax.lang.model.element.Element; import javax.lang.model.element.VariableElement; import javax.ws.rs.QueryParam; -public enum VariableElementToQueryParameter implements Function { +public enum ElementToQueryParameter implements Function { INTO_QUERY_PARAMETER; @Nullable @Override - public QueryParameter apply(VariableElement parameterElement) { + public QueryParameter apply(Element parameterElement) { return new QueryParameter(parameterElement.getAnnotation(QueryParam.class).value()); } diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java index 858e704..49b51a1 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java @@ -23,7 +23,7 @@ import static com.google.common.collect.Lists.newArrayList; import static fr.vidal.oss.jax_rs_linker.functions.AnnotationMirrorToMethodValueEntryFunction.TO_METHOD_VALUE_ENTRIES; import static fr.vidal.oss.jax_rs_linker.functions.EntriesToStringValueFunction.TO_STRING_VALUE; -import static fr.vidal.oss.jax_rs_linker.functions.VariableElementToQueryParameter.INTO_QUERY_PARAMETER; +import static fr.vidal.oss.jax_rs_linker.functions.ElementToQueryParameter.INTO_QUERY_PARAMETER; import static fr.vidal.oss.jax_rs_linker.predicates.AnnotationMirrorByNamePredicate.byName; import static fr.vidal.oss.jax_rs_linker.predicates.UnparseableValuePredicate.IS_UNPARSEABLE; import static javax.tools.Diagnostic.Kind.ERROR; @@ -161,12 +161,26 @@ private ApiQuery apiQuery(Collection parameters) { BeanParam beanParam = variableElement.getAnnotation(BeanParam.class); if (beanParam != null) { Element beanParamTargetClass = typeUtils.asElement(variableElement.asType()); - List ctors = ElementFilter.constructorsIn(beanParamTargetClass.getEnclosedElements()); - for (ExecutableElement ctor : ctors) { + List enclosedElements = beanParamTargetClass.getEnclosedElements(); + for (ExecutableElement ctor : ElementFilter.constructorsIn(enclosedElements)) { for (VariableElement ctorParameter : ctor.getParameters()) { queryParameters.add(INTO_QUERY_PARAMETER.apply(ctorParameter)); } } + + for (VariableElement field : ElementFilter.fieldsIn(enclosedElements)) { + QueryParam queryParam = field.getAnnotation(QueryParam.class); + if (queryParam != null) { + queryParameters.add(INTO_QUERY_PARAMETER.apply(field)); + } + } + + for (ExecutableElement method : ElementFilter.methodsIn(enclosedElements)) { + QueryParam queryParam = method.getAnnotation(QueryParam.class); + if (queryParam != null) { + queryParameters.add(INTO_QUERY_PARAMETER.apply(method)); + } + } } } return new ApiQuery(queryParameters); From 8a4b224b4cf5c93340e1c474b18848d713362cc5 Mon Sep 17 00:00:00 2001 From: Olivier Girardot Date: Tue, 3 Mar 2015 10:23:07 +0100 Subject: [PATCH 5/8] add method and fields scanning for query param in BeanParam handling --- .../jax_rs_linker/parser/ElementParser.java | 20 +++++++++++-------- .../parser/ElementParserTest.java | 6 ++++-- .../oss/jax_rs_linker/parser/PagingTest.java | 13 ++++++++++++ 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java index 49b51a1..c09789b 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java @@ -164,21 +164,17 @@ private ApiQuery apiQuery(Collection parameters) { List enclosedElements = beanParamTargetClass.getEnclosedElements(); for (ExecutableElement ctor : ElementFilter.constructorsIn(enclosedElements)) { for (VariableElement ctorParameter : ctor.getParameters()) { - queryParameters.add(INTO_QUERY_PARAMETER.apply(ctorParameter)); + addToQueryParametersIfApplicable(queryParameters, ctorParameter); } } for (VariableElement field : ElementFilter.fieldsIn(enclosedElements)) { - QueryParam queryParam = field.getAnnotation(QueryParam.class); - if (queryParam != null) { - queryParameters.add(INTO_QUERY_PARAMETER.apply(field)); - } + addToQueryParametersIfApplicable(queryParameters, field); } for (ExecutableElement method : ElementFilter.methodsIn(enclosedElements)) { - QueryParam queryParam = method.getAnnotation(QueryParam.class); - if (queryParam != null) { - queryParameters.add(INTO_QUERY_PARAMETER.apply(method)); + if (method.getSimpleName().toString().startsWith("set")) { + addToQueryParametersIfApplicable(queryParameters, method); } } } @@ -186,6 +182,14 @@ private ApiQuery apiQuery(Collection parameters) { return new ApiQuery(queryParameters); } + private void addToQueryParametersIfApplicable(Collection queryParameters, + Element ctorParameter) { + QueryParam queryParam = ctorParameter.getAnnotation(QueryParam.class); + if (queryParam != null) { + queryParameters.add(INTO_QUERY_PARAMETER.apply(ctorParameter)); + } + } + private ClassName className(ExecutableElement element) { TypeElement classElement = (TypeElement) element.getEnclosingElement(); return ClassName.valueOf(classElement.getQualifiedName().toString()); diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java index 7d8a3dc..49d21dd 100644 --- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java +++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java @@ -78,10 +78,12 @@ public void parses_method_to_mapping_representation_with_bean_param() { assertThat(api.getApiPath().getPathParameters()) .containsExactly(new PathParameter(ClassName.valueOf("int"), "id")); assertThat(api.getApiQuery().getQueryParameters()) - .hasSize(2) + .hasSize(4) .containsExactly( new QueryParameter("start-page"), - new QueryParameter("page-size") + new QueryParameter("page-size"), + new QueryParameter("is-applicable"), + new QueryParameter("haters-gonna-hate") ); } diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/PagingTest.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/PagingTest.java index bd90530..e26cecd 100644 --- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/PagingTest.java +++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/PagingTest.java @@ -6,6 +6,9 @@ public class PagingTest { private final int pageStart; private final int pageSize; + @QueryParam("is-applicable") + private boolean isApplicable = false; + public PagingTest(@DefaultValue("1") @QueryParam("start-page") int pageStart, @DefaultValue("25") @QueryParam("page-size") int pageSize) { @@ -13,4 +16,14 @@ public PagingTest(@DefaultValue("1") @QueryParam("start-page") int pageStart, this.pageSize = pageSize; } + @QueryParam("to be ignored") + public void testOfAnnotatedMethodIgnored(String value) { + + } + + @QueryParam("haters-gonna-hate") + public void setUselessParameter(String value) { + + } + } From 66eeb6dfe476b302f45d3a7622ba18f688e496d3 Mon Sep 17 00:00:00 2001 From: Olivier Girardot Date: Tue, 3 Mar 2015 11:45:02 +0100 Subject: [PATCH 6/8] Do not take into accound set methods with a return type != void --- .../fr/vidal/oss/jax_rs_linker/parser/ElementParser.java | 5 ++++- .../java/fr/vidal/oss/jax_rs_linker/parser/PagingTest.java | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java index c09789b..70bd2a1 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java @@ -10,6 +10,8 @@ import javax.annotation.processing.Messager; import javax.lang.model.element.*; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Types; import javax.ws.rs.BeanParam; @@ -173,7 +175,8 @@ private ApiQuery apiQuery(Collection parameters) { } for (ExecutableElement method : ElementFilter.methodsIn(enclosedElements)) { - if (method.getSimpleName().toString().startsWith("set")) { + if (method.getSimpleName().toString().startsWith("set") + && typeUtils.isSameType(method.getReturnType(),typeUtils.getNoType(TypeKind.VOID))) { addToQueryParametersIfApplicable(queryParameters, method); } } diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/PagingTest.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/PagingTest.java index e26cecd..8f454ee 100644 --- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/PagingTest.java +++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/PagingTest.java @@ -23,7 +23,11 @@ public void testOfAnnotatedMethodIgnored(String value) { @QueryParam("haters-gonna-hate") public void setUselessParameter(String value) { + } + @QueryParam("non-void-method") + public String setNonVoidMethod(String value) { + return ""; } } From 6554a48cc988cfd86d9be08b8a72604384f4885e Mon Sep 17 00:00:00 2001 From: Olivier Girardot Date: Tue, 3 Mar 2015 13:57:24 +0100 Subject: [PATCH 7/8] Create a simple queryParam visitor and a single loop --- .../jax_rs_linker/parser/ElementParser.java | 34 ++--------- .../parser/QueryParamElementVisitor.java | 57 +++++++++++++++++++ .../parser/ElementParserTest.java | 2 +- 3 files changed, 63 insertions(+), 30 deletions(-) create mode 100644 jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/QueryParamElementVisitor.java diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java index 70bd2a1..1ee5ab4 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/ElementParser.java @@ -10,14 +10,10 @@ import javax.annotation.processing.Messager; import javax.lang.model.element.*; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Types; import javax.ws.rs.BeanParam; import javax.ws.rs.QueryParam; import java.util.Collection; -import java.util.List; import static com.google.common.base.Optional.absent; import static com.google.common.base.Preconditions.checkArgument; @@ -154,7 +150,7 @@ private ApiPath apiPath(ExecutableElement methodElement, String path) { } private ApiQuery apiQuery(Collection parameters) { - Collection queryParameters = newArrayList(); + final Collection queryParameters = newArrayList(); for (VariableElement variableElement : parameters) { final QueryParam annotation = variableElement.getAnnotation(QueryParam.class); if (annotation != null) { @@ -163,36 +159,15 @@ private ApiQuery apiQuery(Collection parameters) { BeanParam beanParam = variableElement.getAnnotation(BeanParam.class); if (beanParam != null) { Element beanParamTargetClass = typeUtils.asElement(variableElement.asType()); - List enclosedElements = beanParamTargetClass.getEnclosedElements(); - for (ExecutableElement ctor : ElementFilter.constructorsIn(enclosedElements)) { - for (VariableElement ctorParameter : ctor.getParameters()) { - addToQueryParametersIfApplicable(queryParameters, ctorParameter); - } - } - - for (VariableElement field : ElementFilter.fieldsIn(enclosedElements)) { - addToQueryParametersIfApplicable(queryParameters, field); - } - - for (ExecutableElement method : ElementFilter.methodsIn(enclosedElements)) { - if (method.getSimpleName().toString().startsWith("set") - && typeUtils.isSameType(method.getReturnType(),typeUtils.getNoType(TypeKind.VOID))) { - addToQueryParametersIfApplicable(queryParameters, method); - } + ElementVisitor queryParamElementVisitor = new QueryParamElementVisitor(queryParameters, typeUtils); + for (Element element : beanParamTargetClass.getEnclosedElements()) { + queryParamElementVisitor.visit(element); } } } return new ApiQuery(queryParameters); } - private void addToQueryParametersIfApplicable(Collection queryParameters, - Element ctorParameter) { - QueryParam queryParam = ctorParameter.getAnnotation(QueryParam.class); - if (queryParam != null) { - queryParameters.add(INTO_QUERY_PARAMETER.apply(ctorParameter)); - } - } - private ClassName className(ExecutableElement element) { TypeElement classElement = (TypeElement) element.getEnclosingElement(); return ClassName.valueOf(classElement.getQualifiedName().toString()); @@ -212,4 +187,5 @@ private String qualified(Element element) { element.getSimpleName() ); } + } diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/QueryParamElementVisitor.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/QueryParamElementVisitor.java new file mode 100644 index 0000000..dd35d68 --- /dev/null +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/QueryParamElementVisitor.java @@ -0,0 +1,57 @@ +package fr.vidal.oss.jax_rs_linker.parser; + +import fr.vidal.oss.jax_rs_linker.model.QueryParameter; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.util.SimpleElementVisitor7; +import javax.lang.model.util.Types; +import javax.ws.rs.QueryParam; +import java.util.Collection; + +import static fr.vidal.oss.jax_rs_linker.functions.ElementToQueryParameter.INTO_QUERY_PARAMETER; + +/** +* Element visitor designed to check for QueryParam annotations on BeanParams +*/ +class QueryParamElementVisitor extends SimpleElementVisitor7 { + private final Collection queryParameters; + private final Types typeUtils; + + public QueryParamElementVisitor(Collection queryParameters, + Types typeUtils) { + this.queryParameters = queryParameters; + this.typeUtils = typeUtils; + } + + @Override + public Void visitVariable(VariableElement field, Void aVoid) { + addToQueryParametersIfApplicable(queryParameters, field); + return super.visitVariable(field, aVoid); + } + + @Override + public Void visitExecutable(ExecutableElement e, Void aVoid) { + if (e.getKind().equals(ElementKind.CONSTRUCTOR)) { + for (VariableElement ctorParameter : e.getParameters()) { + addToQueryParametersIfApplicable(queryParameters, ctorParameter); + } + } else if (e.getKind().equals(ElementKind.METHOD) && + e.getSimpleName().toString().startsWith("set") + && typeUtils.isSameType(e.getReturnType(),typeUtils.getNoType(TypeKind.VOID))) { + addToQueryParametersIfApplicable(queryParameters, e); + } + return super.visitExecutable(e, aVoid); + } + + private void addToQueryParametersIfApplicable(Collection queryParameters, + Element ctorParameter) { + QueryParam queryParam = ctorParameter.getAnnotation(QueryParam.class); + if (queryParam != null) { + queryParameters.add(INTO_QUERY_PARAMETER.apply(ctorParameter)); + } + } +} diff --git a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java index 49d21dd..afb272b 100644 --- a/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java +++ b/jax-rs-linker/src/test/java/fr/vidal/oss/jax_rs_linker/parser/ElementParserTest.java @@ -80,9 +80,9 @@ public void parses_method_to_mapping_representation_with_bean_param() { assertThat(api.getApiQuery().getQueryParameters()) .hasSize(4) .containsExactly( + new QueryParameter("is-applicable"), new QueryParameter("start-page"), new QueryParameter("page-size"), - new QueryParameter("is-applicable"), new QueryParameter("haters-gonna-hate") ); } From 520218c290a4d4f11825d4b9f12d3f0338aa7e36 Mon Sep 17 00:00:00 2001 From: Olivier Girardot Date: Tue, 3 Mar 2015 14:03:17 +0100 Subject: [PATCH 8/8] epic extract --- .../oss/jax_rs_linker/parser/QueryParamElementVisitor.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/QueryParamElementVisitor.java b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/QueryParamElementVisitor.java index dd35d68..cbac6aa 100644 --- a/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/QueryParamElementVisitor.java +++ b/jax-rs-linker/src/main/java/fr/vidal/oss/jax_rs_linker/parser/QueryParamElementVisitor.java @@ -35,11 +35,12 @@ public Void visitVariable(VariableElement field, Void aVoid) { @Override public Void visitExecutable(ExecutableElement e, Void aVoid) { - if (e.getKind().equals(ElementKind.CONSTRUCTOR)) { + ElementKind manKind = e.getKind(); + if (manKind.equals(ElementKind.CONSTRUCTOR)) { for (VariableElement ctorParameter : e.getParameters()) { addToQueryParametersIfApplicable(queryParameters, ctorParameter); } - } else if (e.getKind().equals(ElementKind.METHOD) && + } else if (manKind.equals(ElementKind.METHOD) && e.getSimpleName().toString().startsWith("set") && typeUtils.isSameType(e.getReturnType(),typeUtils.getNoType(TypeKind.VOID))) { addToQueryParametersIfApplicable(queryParameters, e);