Skip to content

Commit

Permalink
Merge pull request #3163 from MeroRai/PAYARA-3085
Browse files Browse the repository at this point in the history
PAYARA-3085 OpenAPI Doesn't Support @...Param Annotated Fields
  • Loading branch information
MattGill98 authored Oct 2, 2018
2 parents 4cda7ac + b072975 commit 4077ca3
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import javax.ws.rs.Consumes;
Expand Down Expand Up @@ -108,16 +109,16 @@ interface VisitorFunction<A extends Annotation, E extends AnnotatedElement> {

void visitConsumes(Consumes produces, AnnotatedElement element, ApiContext context);

void visitQueryParam(QueryParam param, java.lang.reflect.Parameter element, ApiContext context);
void visitQueryParam(QueryParam param, AnnotatedElement element, ApiContext context);

void visitPathParam(PathParam param, java.lang.reflect.Parameter element, ApiContext context);
void visitPathParam(PathParam param, AnnotatedElement element, ApiContext context);

void visitFormParam(FormParam param, java.lang.reflect.Parameter element, ApiContext context);
void visitFormParam(FormParam param, AnnotatedElement element, ApiContext context);

void visitHeaderParam(HeaderParam param, java.lang.reflect.Parameter element, ApiContext context);

void visitCookieParam(CookieParam param, java.lang.reflect.Parameter element, ApiContext context);
void visitHeaderParam(HeaderParam param, AnnotatedElement element, ApiContext context);

void visitCookieParam(CookieParam param, AnnotatedElement element, ApiContext context);

// OpenAPI annotations

void visitOpenAPI(OpenAPIDefinition definition, AnnotatedElement element, ApiContext context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@
import org.eclipse.microprofile.openapi.models.parameters.Parameter.In;

import fish.payara.microprofile.openapi.impl.model.OperationImpl;
import java.lang.reflect.GenericDeclaration;
import javax.ws.rs.Path;

public final class ModelUtils {

Expand Down Expand Up @@ -540,4 +542,52 @@ else if (newValue instanceof Constructible) {
}
}
}

public static org.eclipse.microprofile.openapi.models.Operation getOperation(Method method,
OpenAPI api, Map<String, Set<Class<?>>> resourceMapping) {
String path = getResourcePath(method, resourceMapping);
if (path != null) {
PathItem pathItem = api.getPaths().get(path);
if (pathItem != null) {
PathItem.HttpMethod httpMethod = getHttpMethod(method);
return pathItem.readOperationsMap().get(httpMethod);
}
}
return null;
}

public static String getResourcePath(GenericDeclaration declaration, Map<String, Set<Class<?>>> resourceMapping) {
String path = null;
if (declaration instanceof Method) {
Method method = (Method) declaration;

// If the method is a valid resource
if (method.isAnnotationPresent(GET.class) || method.isAnnotationPresent(POST.class)
|| method.isAnnotationPresent(PUT.class) || method.isAnnotationPresent(DELETE.class)
|| method.isAnnotationPresent(HEAD.class) || method.isAnnotationPresent(OPTIONS.class)
|| method.isAnnotationPresent(PATCH.class)) {
if (method.isAnnotationPresent(Path.class)) {
path = getResourcePath(method.getDeclaringClass(), resourceMapping) + "/"
+ method.getDeclaredAnnotation(Path.class).value();
} else {
path = getResourcePath(method.getDeclaringClass(), resourceMapping);
}
}
}
if (declaration instanceof Class) {
Class<?> clazz = (Class<?>) declaration;
clazz.toString();


// If the class is a resource and contains a mapping
if (clazz.isAnnotationPresent(Path.class)) {
for (Map.Entry<String, Set<Class<?>>> entry : resourceMapping.entrySet()) {
if (entry.getValue() != null && entry.getValue().contains(clazz)) {
path = entry.getKey() + "/" + clazz.getDeclaredAnnotation(Path.class).value();
}
}
}
}
return normaliseUrl(path);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@
import org.eclipse.microprofile.openapi.models.media.MediaType;
import org.eclipse.microprofile.openapi.models.media.Schema.SchemaType;
import org.eclipse.microprofile.openapi.models.parameters.Parameter.In;
import org.eclipse.microprofile.openapi.models.parameters.Parameter.Style;

import fish.payara.microprofile.openapi.api.processor.OASProcessor;
import fish.payara.microprofile.openapi.api.visitor.ApiContext;
Expand All @@ -123,7 +122,9 @@
import fish.payara.microprofile.openapi.impl.model.servers.ServerImpl;
import fish.payara.microprofile.openapi.impl.model.tags.TagImpl;
import fish.payara.microprofile.openapi.impl.model.util.ModelUtils;
import fish.payara.microprofile.openapi.impl.visitor.OpenApiContext;
import fish.payara.microprofile.openapi.impl.visitor.OpenApiWalker;
import org.eclipse.microprofile.openapi.models.parameters.Parameter.Style;

/**
* A processor to parse the application for annotations, to add to the OpenAPI
Expand Down Expand Up @@ -356,66 +357,95 @@ public void visitConsumes(Consumes consumes, AnnotatedElement element, ApiContex
}

@Override
public void visitQueryParam(QueryParam param, java.lang.reflect.Parameter element, ApiContext context) {
public void visitQueryParam(QueryParam param, AnnotatedElement element, ApiContext context) {
org.eclipse.microprofile.openapi.models.parameters.Parameter newParameter = new ParameterImpl();
newParameter.setName(param.value());
newParameter.setIn(In.QUERY);
newParameter.setStyle(Style.SIMPLE);
newParameter.setSchema(new SchemaImpl().type(ModelUtils.getSchemaType(element.getType())));
context.getWorkingOperation().addParameter(newParameter);
addParameter(element, context, newParameter);
}

@Override
public void visitPathParam(PathParam param, java.lang.reflect.Parameter element, ApiContext context) {
public void visitPathParam(PathParam param, AnnotatedElement element, ApiContext context) {
org.eclipse.microprofile.openapi.models.parameters.Parameter newParameter = new ParameterImpl();
newParameter.setName(param.value());
newParameter.setRequired(true);
newParameter.setIn(In.PATH);
newParameter.setStyle(Style.SIMPLE);
newParameter.setSchema(new SchemaImpl().type(ModelUtils.getSchemaType(element.getType())));
context.getWorkingOperation().addParameter(newParameter);
addParameter(element, context, newParameter);
}

@Override
public void visitFormParam(FormParam param, java.lang.reflect.Parameter element, ApiContext context) {
public void visitFormParam(FormParam param, AnnotatedElement element, ApiContext context) {
// Find the aggregate schema type of all the parameters
SchemaType formSchemaType = null;
for (java.lang.reflect.Parameter methodParam : element.getDeclaringExecutable().getParameters()) {
if (methodParam.isAnnotationPresent(FormParam.class)) {
formSchemaType = ModelUtils.getParentSchemaType(formSchemaType,
ModelUtils.getSchemaType(methodParam.getType()));

if (element instanceof java.lang.reflect.Parameter) {
java.lang.reflect.Parameter[] parameters = java.lang.reflect.Parameter.class.cast(element)
.getDeclaringExecutable().getParameters();
for (java.lang.reflect.Parameter methodParam : parameters) {
if (methodParam.isAnnotationPresent(FormParam.class)) {
formSchemaType = ModelUtils.getParentSchemaType(formSchemaType,
ModelUtils.getSchemaType(methodParam.getType()));
}
}
}

if (context.getWorkingOperation() != null) {
// If there's no request body, fill out a new one right down to the schema
if (context.getWorkingOperation().getRequestBody() == null) {
context.getWorkingOperation().setRequestBody(new RequestBodyImpl().content(new ContentImpl()
.addMediaType(javax.ws.rs.core.MediaType.WILDCARD, new MediaTypeImpl()
.schema(new SchemaImpl()))));
}
}

// If there's no request body, fill out a new one right down to the schema
if (context.getWorkingOperation().getRequestBody() == null) {
context.getWorkingOperation().setRequestBody(new RequestBodyImpl().content(new ContentImpl()
.addMediaType(javax.ws.rs.core.MediaType.WILDCARD, new MediaTypeImpl().schema(new SchemaImpl()))));
// Set the request body type accordingly.
context.getWorkingOperation().getRequestBody().getContent()
.get(javax.ws.rs.core.MediaType.WILDCARD).getSchema()
.setType(formSchemaType);
}

// Set the request body type accordingly.
context.getWorkingOperation().getRequestBody().getContent().get(javax.ws.rs.core.MediaType.WILDCARD).getSchema()
.setType(formSchemaType);
}

@Override
public void visitHeaderParam(HeaderParam param, java.lang.reflect.Parameter element, ApiContext context) {
public void visitHeaderParam(HeaderParam param, AnnotatedElement element, ApiContext context) {
org.eclipse.microprofile.openapi.models.parameters.Parameter newParameter = new ParameterImpl();
newParameter.setName(param.value());
newParameter.setIn(In.HEADER);
newParameter.setStyle(Style.SIMPLE);
newParameter.setSchema(new SchemaImpl().type(ModelUtils.getSchemaType(element.getType())));
context.getWorkingOperation().addParameter(newParameter);
addParameter(element, context, newParameter);
}

@Override
public void visitCookieParam(CookieParam param, java.lang.reflect.Parameter element, ApiContext context) {
public void visitCookieParam(CookieParam param, AnnotatedElement element, ApiContext context) {
org.eclipse.microprofile.openapi.models.parameters.Parameter newParameter = new ParameterImpl();
newParameter.setName(param.value());
newParameter.setIn(In.COOKIE);
newParameter.setStyle(Style.SIMPLE);
newParameter.setSchema(new SchemaImpl().type(ModelUtils.getSchemaType(element.getType())));
context.getWorkingOperation().addParameter(newParameter);
addParameter(element, context, newParameter);
}

private void addParameter(AnnotatedElement element, ApiContext context,
org.eclipse.microprofile.openapi.models.parameters.Parameter newParameter) {
if (element instanceof java.lang.reflect.Parameter) {
newParameter.setSchema(new SchemaImpl().type(ModelUtils
.getSchemaType(java.lang.reflect.Parameter.class.cast(element).getType())));
} else {
newParameter.setSchema(new SchemaImpl().type(ModelUtils
.getSchemaType(Field.class.cast(element).getType())));
}

if (context.getWorkingOperation() != null) {
context.getWorkingOperation().addParameter(newParameter);
} else {
Field field = Field.class.cast(element);
ApiContext apiContext;
OpenAPI api = context.getApi();
for (Method method : field.getDeclaringClass().getDeclaredMethods()) {
apiContext = new OpenApiContext(api, null, ModelUtils.getOperation(method,
api, generateResourceMapping(classes)));
apiContext.getWorkingOperation().addParameter(newParameter);
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,14 @@
*/
package fish.payara.microprofile.openapi.impl.visitor;

import static fish.payara.microprofile.openapi.impl.model.util.ModelUtils.getHttpMethod;
import static fish.payara.microprofile.openapi.impl.model.util.ModelUtils.normaliseUrl;
import static fish.payara.microprofile.openapi.impl.model.util.ModelUtils.getOperation;
import static fish.payara.microprofile.openapi.impl.model.util.ModelUtils.getResourcePath;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;

Expand Down Expand Up @@ -89,8 +87,6 @@
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.eclipse.microprofile.openapi.annotations.tags.Tags;
import org.eclipse.microprofile.openapi.models.OpenAPI;
import org.eclipse.microprofile.openapi.models.PathItem;
import org.eclipse.microprofile.openapi.models.PathItem.HttpMethod;

import fish.payara.microprofile.openapi.api.visitor.ApiContext;
import fish.payara.microprofile.openapi.api.visitor.ApiVisitor;
Expand Down Expand Up @@ -181,7 +177,7 @@ private <A extends Annotation, A2 extends Annotation, E extends AnnotatedElement
for (Class<?> clazz : classes) {

processAnnotation(clazz, annotationClass, annotationFunction, altClass, altFunction,
new OpenApiContext(api, getResourcePath(clazz)));
new OpenApiContext(api, getResourcePath(clazz, resourceMapping)));

for (Field field : clazz.getDeclaredFields()) {
processAnnotation(field, annotationClass, annotationFunction, altClass, altFunction,
Expand All @@ -191,11 +187,11 @@ private <A extends Annotation, A2 extends Annotation, E extends AnnotatedElement
for (Method method : clazz.getDeclaredMethods()) {

processAnnotation(method, annotationClass, annotationFunction, altClass, altFunction,
new OpenApiContext(api, getResourcePath(method), getOperation(method)));
new OpenApiContext(api, getResourcePath(method, resourceMapping), getOperation(method, api, resourceMapping)));

for (java.lang.reflect.Parameter parameter : method.getParameters()) {
processAnnotation(parameter, annotationClass, annotationFunction, altClass, altFunction,
new OpenApiContext(api, getResourcePath(method), getOperation(method)));
new OpenApiContext(api, getResourcePath(method, resourceMapping), getOperation(method, api, resourceMapping)));
}
}
}
Expand Down Expand Up @@ -245,50 +241,4 @@ private <A extends Annotation, A2 extends Annotation, E extends AnnotatedElement
}
}
}

private org.eclipse.microprofile.openapi.models.Operation getOperation(Method method) {
String path = getResourcePath(method);
if (path != null) {
PathItem pathItem = api.getPaths().get(path);
if (pathItem != null) {
HttpMethod httpMethod = getHttpMethod(method);
return pathItem.readOperationsMap().get(httpMethod);
}
}
return null;
}

private String getResourcePath(GenericDeclaration declaration) {
String path = null;
if (declaration instanceof Method) {
Method method = (Method) declaration;

// If the method is a valid resource
if (method.isAnnotationPresent(GET.class) || method.isAnnotationPresent(POST.class)
|| method.isAnnotationPresent(PUT.class) || method.isAnnotationPresent(DELETE.class)
|| method.isAnnotationPresent(HEAD.class) || method.isAnnotationPresent(OPTIONS.class)
|| method.isAnnotationPresent(PATCH.class)) {
if (method.isAnnotationPresent(Path.class)) {
path = getResourcePath(method.getDeclaringClass()) + "/"
+ method.getDeclaredAnnotation(Path.class).value();
} else {
path = getResourcePath(method.getDeclaringClass());
}
}
}
if (declaration instanceof Class) {
Class<?> clazz = (Class<?>) declaration;

// If the class is a resource and contains a mapping
if (clazz.isAnnotationPresent(Path.class)) {
for (Entry<String, Set<Class<?>>> entry : resourceMapping.entrySet()) {
if (entry.getValue() != null && entry.getValue().contains(clazz)) {
path = entry.getKey() + "/" + clazz.getDeclaredAnnotation(Path.class).value();
}
}
}
}
return normaliseUrl(path);
}

}
}

0 comments on commit 4077ca3

Please sign in to comment.