Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle @BeanParam as added @QueryParam fields #39

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,21 @@
package fr.vidal.oss.jax_rs_linker.functions;

import com.google.common.base.Function;
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 ElementToQueryParameter implements Function<Element, QueryParameter> {

INTO_QUERY_PARAMETER;

@Nullable
@Override
public QueryParameter apply(Element parameterElement) {
return new QueryParameter(parameterElement.getAnnotation(QueryParam.class).value());
}

}

This file was deleted.

Expand Up @@ -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) {
Expand All @@ -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 + '\'' +
'}';
}
}
Expand Up @@ -11,6 +11,7 @@
import javax.annotation.processing.Messager;
import javax.lang.model.element.*;
import javax.lang.model.util.Types;
import javax.ws.rs.BeanParam;
import javax.ws.rs.QueryParam;
import java.util.Collection;

Expand All @@ -20,10 +21,9 @@
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;

public class ElementParser {
Expand All @@ -32,11 +32,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();
Expand Down Expand Up @@ -91,21 +93,21 @@ private Optional<ApiLink> link(ExecutableElement methodElement, boolean withSelf

private Optional<SubResourceTarget> 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())
)
);
}

Expand All @@ -127,33 +129,41 @@ private Optional<CompilationError> 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)
);
}

private ApiQuery apiQuery(Collection<? extends VariableElement> parameters) {
Collection<QueryParameter> queryParameters = newArrayList();
final Collection<QueryParameter> queryParameters = newArrayList();
for (VariableElement variableElement : parameters) {
final QueryParam annotation = variableElement.getAnnotation(QueryParam.class);
if (annotation != null) {
queryParameters.add(INTO_QUERY_PARAMETER.apply(variableElement));
}
BeanParam beanParam = variableElement.getAnnotation(BeanParam.class);
if (beanParam != null) {
Element beanParamTargetClass = typeUtils.asElement(variableElement.asType());
ElementVisitor<Void, Void> queryParamElementVisitor = new QueryParamElementVisitor(queryParameters, typeUtils);
for (Element element : beanParamTargetClass.getEnclosedElements()) {
queryParamElementVisitor.visit(element);
}
}
}
return new ApiQuery(queryParameters);
}
Expand All @@ -177,4 +187,5 @@ private String qualified(Element element) {
element.getSimpleName()
);
}

}
@@ -0,0 +1,58 @@
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<Void, Void> {
private final Collection<QueryParameter> queryParameters;
private final Types typeUtils;

public QueryParamElementVisitor(Collection<QueryParameter> 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) {
ElementKind manKind = e.getKind();
if (manKind.equals(ElementKind.CONSTRUCTOR)) {
for (VariableElement ctorParameter : e.getParameters()) {
addToQueryParametersIfApplicable(queryParameters, ctorParameter);
}
} else if (manKind.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<QueryParameter> queryParameters,
Element ctorParameter) {
QueryParam queryParam = ctorParameter.getAnnotation(QueryParam.class);
if (queryParam != null) {
queryParameters.add(INTO_QUERY_PARAMETER.apply(ctorParameter));
}
}
}
Expand Up @@ -158,12 +158,11 @@ private String pathParametersAsList(Collection<PathParameter> pathParameters) {
private String queryParametersAsList(Collection<QueryParameter> queryParameters) {
StringBuilder builder = new StringBuilder();
Iterator<QueryParameter> 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
));
Expand Down Expand Up @@ -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();
Expand Down
Expand Up @@ -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")
);
Expand Down
Expand Up @@ -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<QueryParameter> queryParameters = newArrayList(new QueryParameter(ClassName.valueOf("fr.vidal.oss.Foo"),"Foo"),new QueryParameter(ClassName.valueOf("fr.vidal.oss.Bar"),"Bar") );
Collection<QueryParameter> queryParameters = newArrayList(new QueryParameter("Foo"),new QueryParameter("Bar") );
ApiQuery apiQuery = new ApiQuery(queryParameters);

assertThat(apiQuery.toString()).isEqualTo("ApiQuery{queryParameters=[FooBar]}");
Expand Down
Expand Up @@ -8,42 +8,32 @@ 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);
}

@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);
}

@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'}");
}
}