mirror of
https://github.com/zaaarf/route-cartographer.git
synced 2024-12-05 00:24:53 +01:00
feat: request/response dto support
This commit is contained in:
parent
729bf6f2a7
commit
47b45e2e42
2 changed files with 98 additions and 10 deletions
|
@ -34,6 +34,16 @@ public class Route {
|
|||
*/
|
||||
public final boolean deprecated;
|
||||
|
||||
/**
|
||||
* A {@link DTO} representing the response body.
|
||||
*/
|
||||
public final DTO returnType;
|
||||
|
||||
/**
|
||||
* A {@link DTO} representing the request body.
|
||||
*/
|
||||
public final DTO inputType;
|
||||
|
||||
/**
|
||||
* An array of {@link Param}s, representing parameters accepted by the endpoint.
|
||||
*/
|
||||
|
@ -48,8 +58,8 @@ public class Route {
|
|||
* @param deprecated whether the endpoint is deprecated
|
||||
* @param params {@link Param}s of the endpoint, may be null
|
||||
*/
|
||||
public Route(String path, RequestMethod[] methods, MediaType consumes, MediaType produces, boolean deprecated,
|
||||
Param... params) {
|
||||
public Route(String path, RequestMethod[] methods, MediaType consumes, MediaType produces,
|
||||
boolean deprecated, DTO returnType, DTO inputType, Param... params) {
|
||||
this.path = path;
|
||||
|
||||
StringBuilder methodStringBuilder = new StringBuilder("[");
|
||||
|
@ -70,6 +80,9 @@ public class Route {
|
|||
|
||||
this.deprecated = deprecated;
|
||||
|
||||
this.returnType = returnType;
|
||||
this.inputType = inputType;
|
||||
|
||||
if(params != null) this.params = params;
|
||||
else this.params = new Param[0]; //just in case
|
||||
}
|
||||
|
@ -106,4 +119,31 @@ public class Route {
|
|||
this.defaultValue = defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Representation of a DTO type.
|
||||
*/
|
||||
public static class DTO {
|
||||
|
||||
/**
|
||||
* Fully-qualified name of the type.
|
||||
*/
|
||||
public final String FQN;
|
||||
|
||||
/**
|
||||
* An array of {@link Param} representing the type's fields.
|
||||
*/
|
||||
public final Route.Param[] fields;
|
||||
|
||||
/**
|
||||
* The one and only constructor.
|
||||
* @param FQN the fully-qualified name
|
||||
* @param fields the {@link Param}s representing the fields
|
||||
*/
|
||||
public DTO(String FQN, Route.Param ... fields) {
|
||||
this.FQN = FQN;
|
||||
if(fields == null) this.fields = new Route.Param[0];
|
||||
else this.fields = fields;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import javax.lang.model.element.Element;
|
|||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.StandardLocation;
|
||||
|
@ -18,6 +20,7 @@ import java.io.IOException;
|
|||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -58,6 +61,7 @@ public class RouteCompass extends AbstractProcessor {
|
|||
* @return false, letting other processor process the annotations again
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("OptionalGetWithoutIsPresent")
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
|
||||
for(TypeElement annotationType : annotations) {
|
||||
env.getElementsAnnotatedWith(annotationType)
|
||||
|
@ -73,7 +77,11 @@ public class RouteCompass extends AbstractProcessor {
|
|||
this.getConsumedType(annotationType, elem),
|
||||
this.getProducedType(annotationType, elem),
|
||||
this.isDeprecated(elem),
|
||||
this.getParams(elem.getParameters())
|
||||
this.getDTO(this.processingEnv.getTypeUtils().asElement(elem.getReturnType())),
|
||||
this.getDTO(elem.getParameters().stream()
|
||||
.filter(e -> e.getAnnotation(RequestBody.class) != null)
|
||||
.findFirst().get()),
|
||||
this.getQueryParams(elem.getParameters())
|
||||
));
|
||||
});
|
||||
}
|
||||
|
@ -96,12 +104,24 @@ public class RouteCompass extends AbstractProcessor {
|
|||
if(r.produces != null) out.print("(returns: " + r.produces + ")");
|
||||
out.println();
|
||||
|
||||
for(Route.Param p : r.params) {
|
||||
out.print("\t\t- " + p.typeFQN + " " + p.name);
|
||||
BiConsumer<String, Route.Param[]> printParam = (name, params) -> {
|
||||
if(name != null) out.println("\t\t" + name);
|
||||
for(Route.Param p : params) {
|
||||
out.print(name != null ? "\t\t\t" : "\t\t");
|
||||
out.print("- " + p.typeFQN + " " + p.name);
|
||||
if(p.defaultValue != null)
|
||||
out.print(" " + "(default: " + p.defaultValue + ")");
|
||||
out.println();
|
||||
}
|
||||
};
|
||||
|
||||
printParam.accept(null, r.params);
|
||||
|
||||
if(r.inputType != null)
|
||||
printParam.accept("input: " + r.inputType.FQN, r.inputType.fields);
|
||||
|
||||
if(r.returnType != null)
|
||||
printParam.accept("output: " + r.returnType.FQN, r.returnType.fields);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +218,7 @@ public class RouteCompass extends AbstractProcessor {
|
|||
* @param params the {@link VariableElement}s representing the parameters of a request
|
||||
* @return an array of {@link Route.Param} representing the parameters of the request.
|
||||
*/
|
||||
private Route.Param[] getParams(List<? extends VariableElement> params) {
|
||||
private Route.Param[] getQueryParams(List<? extends VariableElement> params) {
|
||||
return params.stream()
|
||||
.map(p -> {
|
||||
RequestParam ann = p.getAnnotation(RequestParam.class);
|
||||
|
@ -220,6 +240,34 @@ public class RouteCompass extends AbstractProcessor {
|
|||
}).filter(Objects::nonNull).toArray(Route.Param[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a representation of a DTO type.
|
||||
* @param type the {@link TypeElement} to examine
|
||||
* @return a {@link Route.DTO} representing the given type
|
||||
*/
|
||||
private Route.DTO getDTO(Element type) {
|
||||
if(!(type instanceof TypeElement)) //doubles as null check
|
||||
return null;
|
||||
|
||||
List<VariableElement> fieldElements = new ArrayList<>();
|
||||
TypeElement typeElement = (TypeElement) type;
|
||||
do {
|
||||
fieldElements.addAll(typeElement
|
||||
.getEnclosedElements()
|
||||
.stream().filter(e -> e instanceof VariableElement)
|
||||
.map(e -> (VariableElement) e)
|
||||
.collect(Collectors.toList()));
|
||||
TypeMirror superclass = typeElement.getSuperclass();
|
||||
if(superclass.getKind() == TypeKind.DECLARED)
|
||||
typeElement = (TypeElement) this.processingEnv.getTypeUtils().asElement(superclass);
|
||||
else typeElement = null;
|
||||
} while(typeElement != null);
|
||||
|
||||
return new Route.DTO(type.asType().toString(), fieldElements.stream() //TODO @JsonIgnore
|
||||
.map(e -> new Route.Param(e.asType().toString(), e.getSimpleName().toString(), null))
|
||||
.toArray(Route.Param[]::new));
|
||||
}
|
||||
|
||||
/**
|
||||
* An annotation value.
|
||||
* @param annotationType the {@link TypeElement} with the annotation we are processing
|
||||
|
|
Loading…
Reference in a new issue