From 31dae3399b3af146b297d6b78855d05ef55e0a7b Mon Sep 17 00:00:00 2001 From: bnasslah Date: Wed, 7 Apr 2021 23:41:19 +0200 Subject: [PATCH] enhacement for #1128 --- .../core/MethodParameterPojoExtractor.java | 28 ++++- .../org/springdoc/core/ReturnTypeParser.java | 6 +- .../app155/AbstractIntParameterObject.java | 24 ++++ .../api/app155/AbstractParameterObject.java | 28 +++++ .../springdoc/api/app155/ConcreteEnum.java | 9 ++ .../app155/ConcreteIntParameterObject.java | 14 +++ .../api/app155/ConcreteParameterObject.java | 14 +++ .../springdoc/api/app155/HelloController.java | 44 +++++++ .../api/app155/SpringDocApp155Test.java | 34 +++++ .../src/test/resources/results/app155.json | 117 ++++++++++++++++++ 10 files changed, 314 insertions(+), 4 deletions(-) create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/AbstractIntParameterObject.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/AbstractParameterObject.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteEnum.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteIntParameterObject.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteParameterObject.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/HelloController.java create mode 100644 springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/SpringDocApp155Test.java create mode 100644 springdoc-openapi-webmvc-core/src/test/resources/results/app155.json diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/MethodParameterPojoExtractor.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/MethodParameterPojoExtractor.java index 1632562a1..7f7df5ebb 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/core/MethodParameterPojoExtractor.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/core/MethodParameterPojoExtractor.java @@ -24,6 +24,8 @@ import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; import java.time.Duration; import java.time.LocalTime; import java.util.ArrayList; @@ -131,10 +133,34 @@ private static Stream extractFrom(Class clazz, String fieldN private static Stream fromGetterOfField(Class paramClass, Field field, String fieldNamePrefix) { if (isSimpleType(field.getType())) return fromSimpleClass(paramClass, field, fieldNamePrefix); + else if (field.getGenericType() instanceof TypeVariable) + return extractTypeParameter(paramClass, (TypeVariable) field.getGenericType(), field, fieldNamePrefix); else return extractFrom(field.getType(), fieldNamePrefix + field.getName() + "."); } + /** + * Extract type parameter stream. + * + * @param owningClass the owning class + * @param genericType the generic type + * @param field the field + * @param fieldNamePrefix the field name prefix + * @return the stream + */ + private static Stream extractTypeParameter( + Class owningClass, + TypeVariable genericType, + Field field, + String fieldNamePrefix) { + + Type resolvedType = ReturnTypeParser.resolveType(genericType, owningClass); + if (resolvedType instanceof Class && isSimpleType((Class) resolvedType)) { + return fromSimpleClass(owningClass, field, fieldNamePrefix); + } + return Stream.empty(); + } + /** * From simple class stream. * @@ -262,4 +288,4 @@ private static Nullable getNullable() { return null; } } -} +} \ No newline at end of file diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/ReturnTypeParser.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/ReturnTypeParser.java index 80355e477..2fd95b5d9 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/core/ReturnTypeParser.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/core/ReturnTypeParser.java @@ -191,10 +191,10 @@ default Type getReturnType(MethodParameter methodParameter) { * @return the type */ static Type getType(MethodParameter methodParameter) { - if (methodParameter.getGenericParameterType() instanceof ParameterizedType) - return ReturnTypeParser.resolveType(methodParameter.getGenericParameterType(), methodParameter.getContainingClass()); + Type genericParameterType = methodParameter.getGenericParameterType(); + if (genericParameterType instanceof ParameterizedType || genericParameterType instanceof TypeVariable ) + return ReturnTypeParser.resolveType(genericParameterType, methodParameter.getContainingClass()); return methodParameter.getParameterType(); } } - diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/AbstractIntParameterObject.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/AbstractIntParameterObject.java new file mode 100644 index 000000000..db60532a9 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/AbstractIntParameterObject.java @@ -0,0 +1,24 @@ +package test.org.springdoc.api.app155; + +public class AbstractIntParameterObject { + + int primitiveBaseField; + + T genericField; + + public int getPrimitiveBaseField() { + return primitiveBaseField; + } + + public void setPrimitiveBaseField(int primitiveBaseField) { + this.primitiveBaseField = primitiveBaseField; + } + + public T getGenericField() { + return genericField; + } + + public void setGenericField(T genericField) { + this.genericField = genericField; + } +} diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/AbstractParameterObject.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/AbstractParameterObject.java new file mode 100644 index 000000000..80b99fad6 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/AbstractParameterObject.java @@ -0,0 +1,28 @@ +package test.org.springdoc.api.app155; + +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; + +public class AbstractParameterObject> { + + int primitiveBaseField; + + @Parameter(schema=@Schema(type = "string", allowableValues = {"ONE", "TWO"}) ) + T genericField; + + public int getPrimitiveBaseField() { + return primitiveBaseField; + } + + public void setPrimitiveBaseField(int primitiveBaseField) { + this.primitiveBaseField = primitiveBaseField; + } + + public T getGenericField() { + return genericField; + } + + public void setGenericField(T genericField) { + this.genericField = genericField; + } +} diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteEnum.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteEnum.java new file mode 100644 index 000000000..25a18d1bf --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteEnum.java @@ -0,0 +1,9 @@ +package test.org.springdoc.api.app155; + + + +enum ConcreteEnum { + ONE, + TWO + +} \ No newline at end of file diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteIntParameterObject.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteIntParameterObject.java new file mode 100644 index 000000000..1005d9e40 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteIntParameterObject.java @@ -0,0 +1,14 @@ +package test.org.springdoc.api.app155; + +public class ConcreteIntParameterObject extends AbstractIntParameterObject{ + + int primitiveConcreteField; + + public int getPrimitiveConcreteField() { + return primitiveConcreteField; + } + + public void setPrimitiveConcreteField(int primitiveConcreteField) { + this.primitiveConcreteField = primitiveConcreteField; + } +} diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteParameterObject.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteParameterObject.java new file mode 100644 index 000000000..93cfe32d6 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/ConcreteParameterObject.java @@ -0,0 +1,14 @@ +package test.org.springdoc.api.app155; + +public class ConcreteParameterObject extends AbstractParameterObject { + + int primitiveConcreteField; + + public int getPrimitiveConcreteField() { + return primitiveConcreteField; + } + + public void setPrimitiveConcreteField(int primitiveConcreteField) { + this.primitiveConcreteField = primitiveConcreteField; + } +} diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/HelloController.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/HelloController.java new file mode 100644 index 000000000..b71e346c2 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/HelloController.java @@ -0,0 +1,44 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package test.org.springdoc.api.app155; + +import org.springdoc.api.annotations.ParameterObject; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + @GetMapping( "/test1") + public ResponseEntity sayHello( @ParameterObject final ConcreteParameterObject test) { + System.out.println("Field B = " + test); + return new ResponseEntity("{\"Say\": \"Hello\"}", HttpStatus.OK); + } + + @GetMapping( "/test2") + public ResponseEntity sayHello( @ParameterObject final ConcreteIntParameterObject test) { + System.out.println("Field B = " + test); + return new ResponseEntity("{\"Say\": \"Hello\"}", HttpStatus.OK); + } + + +} \ No newline at end of file diff --git a/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/SpringDocApp155Test.java b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/SpringDocApp155Test.java new file mode 100644 index 000000000..9b72b5c65 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app155/SpringDocApp155Test.java @@ -0,0 +1,34 @@ +/* + * + * * Copyright 2019-2020 the original author or authors. + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * https://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package test.org.springdoc.api.app155; + + +import test.org.springdoc.api.AbstractSpringDocTest; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Tests Spring meta-annotations as method parameters + */ +public class SpringDocApp155Test extends AbstractSpringDocTest { + + @SpringBootApplication + static class SpringDocTestApp {} + +} diff --git a/springdoc-openapi-webmvc-core/src/test/resources/results/app155.json b/springdoc-openapi-webmvc-core/src/test/resources/results/app155.json new file mode 100644 index 000000000..51994ba06 --- /dev/null +++ b/springdoc-openapi-webmvc-core/src/test/resources/results/app155.json @@ -0,0 +1,117 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + } + ], + "paths": { + "/test2": { + "get": { + "tags": [ + "hello-controller" + ], + "operationId": "sayHello", + "parameters": [ + { + "name": "primitiveConcreteField", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "primitiveBaseField", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "genericField", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/test1": { + "get": { + "tags": [ + "hello-controller" + ], + "operationId": "sayHello_1", + "parameters": [ + { + "name": "primitiveConcreteField", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "primitiveBaseField", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "genericField", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "ONE", + "TWO" + ] + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "string" + } + } + } + } + } + } + } + }, + "components": {} +}