From 5e7b67d09de1a5ae332fffe9424a145f77b9c490 Mon Sep 17 00:00:00 2001 From: Martin Hauner Date: Sun, 17 Nov 2019 09:25:07 +0100 Subject: [PATCH 1/3] end-to-end test for path parameters --- .../generatr/GeneratrPendingTest.groovy | 29 ++------------- .../generated/api/EndpointApi.java | 20 +++++++++++ .../openapi.yaml | 35 +++++++++++++++++++ 3 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 src/testInt/resources/path-params-simple-data-types/generated/api/EndpointApi.java create mode 100644 src/testInt/resources/path-params-simple-data-types/openapi.yaml diff --git a/src/testInt/groovy/com/github/hauner/openapi/generatr/GeneratrPendingTest.groovy b/src/testInt/groovy/com/github/hauner/openapi/generatr/GeneratrPendingTest.groovy index 8f3efffb..c406a223 100644 --- a/src/testInt/groovy/com/github/hauner/openapi/generatr/GeneratrPendingTest.groovy +++ b/src/testInt/groovy/com/github/hauner/openapi/generatr/GeneratrPendingTest.groovy @@ -16,10 +16,7 @@ package com.github.hauner.openapi.generatr -import com.github.hauner.openapi.spring.generatr.ApiOptions -import com.github.hauner.openapi.spring.generatr.mapping.ArrayTypeMapping -import com.github.hauner.openapi.spring.generatr.mapping.EndpointTypeMapping -import com.github.hauner.openapi.spring.generatr.mapping.ResponseTypeMapping +import org.junit.Ignore import org.junit.runner.RunWith import org.junit.runners.Parameterized @@ -30,29 +27,7 @@ class GeneratrPendingTest extends GeneratrTestBase { @Parameterized.Parameters(name = "{0}") static Collection sources () { return [ -// new TestSet(data: 'params-complex-data-types') - new TestSet(name: 'response-array-data-type-mapping', - options: new ApiOptions( - typeMappings: [ - new ArrayTypeMapping( - targetTypeName: 'java.util.Collection' - ), - new ResponseTypeMapping ( - contentType: 'application/vnd.global-response', - sourceTypeName: 'array', - targetTypeName: 'java.util.List' - ), - new EndpointTypeMapping ( - path: '/array-endpoint-response', - typeMappings: [ - new ResponseTypeMapping ( - contentType: 'application/vnd.any', - sourceTypeName: 'array', - targetTypeName: 'java.util.Set')] - ) - ] - ) - ) + new TestSet(name: 'path-params-simple-data-types') ] } diff --git a/src/testInt/resources/path-params-simple-data-types/generated/api/EndpointApi.java b/src/testInt/resources/path-params-simple-data-types/generated/api/EndpointApi.java new file mode 100644 index 00000000..cfcd1e4c --- /dev/null +++ b/src/testInt/resources/path-params-simple-data-types/generated/api/EndpointApi.java @@ -0,0 +1,20 @@ +/* + * This class is auto generated by https://github.com/hauner/openapi-generatr-spring. + * DO NOT EDIT. + */ + +package generated.api; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +public interface EndpointApi { + + @GetMapping(path = "/endpoint/{foo}") + ResponseEntity getEndpoint(@PathVariable(name = "foo") String foo); + + @GetMapping(path = "/endpoint-optional/{foo}") + ResponseEntity getEndpointOptional(@PathVariable(name = "foo", required = false) String foo); + +} diff --git a/src/testInt/resources/path-params-simple-data-types/openapi.yaml b/src/testInt/resources/path-params-simple-data-types/openapi.yaml new file mode 100644 index 00000000..fd0bdb22 --- /dev/null +++ b/src/testInt/resources/path-params-simple-data-types/openapi.yaml @@ -0,0 +1,35 @@ +openapi: 3.0.2 +info: + title: test simple path parameters + version: 1.0.0 + +paths: + /endpoint/{foo}: + get: + tags: + - endpoint + parameters: + - name: foo + description: path, required, string + in: path + required: true + schema: + type: string + responses: + '204': + description: empty + + /endpoint-optional/{foo}: + get: + tags: + - endpoint + parameters: + - name: foo + description: path, not required, string + in: path + required: false + schema: + type: string + responses: + '204': + description: empty From 6f0a8537a297f179b64b1d573d11922d37249c9c Mon Sep 17 00:00:00 2001 From: Martin Hauner Date: Sun, 17 Nov 2019 10:15:31 +0100 Subject: [PATCH 2/3] expected is wrong --- .../generated/api/EndpointApi.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/testInt/resources/path-params-simple-data-types/generated/api/EndpointApi.java b/src/testInt/resources/path-params-simple-data-types/generated/api/EndpointApi.java index cfcd1e4c..9290a878 100644 --- a/src/testInt/resources/path-params-simple-data-types/generated/api/EndpointApi.java +++ b/src/testInt/resources/path-params-simple-data-types/generated/api/EndpointApi.java @@ -7,14 +7,14 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.PathVariable; public interface EndpointApi { @GetMapping(path = "/endpoint/{foo}") - ResponseEntity getEndpoint(@PathVariable(name = "foo") String foo); + ResponseEntity getEndpointFoo(@PathVariable(name = "foo") String foo); @GetMapping(path = "/endpoint-optional/{foo}") - ResponseEntity getEndpointOptional(@PathVariable(name = "foo", required = false) String foo); + ResponseEntity getEndpointOptionalFoo(@PathVariable(name = "foo", required = false) String foo); } From fa1f816e889acc952f1c9017093b0e3d56f03f9b Mon Sep 17 00:00:00 2001 From: Martin Hauner Date: Sun, 17 Nov 2019 10:16:22 +0100 Subject: [PATCH 3/3] handle path parameter --- .../spring/converter/ApiConverter.groovy | 14 +++- .../openapi/spring/model/Endpoint.groovy | 4 +- .../spring/model/parameters/Parameter.groovy | 26 +++++++ .../model/parameters/PathParameter.groovy | 72 +++++++++++++++++++ .../model/parameters/QueryParameter.groovy | 2 +- .../openapi/spring/writer/MethodWriter.groovy | 6 +- .../ApiConverterParameterSpec.groovy | 42 +++++++++++ 7 files changed, 158 insertions(+), 8 deletions(-) create mode 100644 src/main/groovy/com/github/hauner/openapi/spring/model/parameters/Parameter.groovy create mode 100644 src/main/groovy/com/github/hauner/openapi/spring/model/parameters/PathParameter.groovy diff --git a/src/main/groovy/com/github/hauner/openapi/spring/converter/ApiConverter.groovy b/src/main/groovy/com/github/hauner/openapi/spring/converter/ApiConverter.groovy index 6d358748..1d1cace8 100644 --- a/src/main/groovy/com/github/hauner/openapi/spring/converter/ApiConverter.groovy +++ b/src/main/groovy/com/github/hauner/openapi/spring/converter/ApiConverter.groovy @@ -18,6 +18,8 @@ package com.github.hauner.openapi.spring.converter import com.github.hauner.openapi.spring.model.Api import com.github.hauner.openapi.spring.model.Endpoint +import com.github.hauner.openapi.spring.model.parameters.Parameter as ModelParameter +import com.github.hauner.openapi.spring.model.parameters.PathParameter import com.github.hauner.openapi.spring.model.parameters.QueryParameter import com.github.hauner.openapi.spring.model.Response import com.github.hauner.openapi.spring.model.datatypes.DataType @@ -111,13 +113,21 @@ class ApiConverter { } } - private QueryParameter createParameter (Parameter parameter, Api target, resolver) { + private ModelParameter createParameter (Parameter parameter, Api target, resolver) { def info = new SchemaInfo (parameter.schema, parameter.name) info.resolver = resolver DataType dataType = dataTypeConverter.convert (info, target.models) - new QueryParameter(name: parameter.name, required: parameter.required, dataType: dataType) + switch (parameter.in) { + case 'query': + return new QueryParameter (name: parameter.name, required: parameter.required, dataType: dataType) + case 'path': + return new PathParameter (name: parameter.name, required: parameter.required, dataType: dataType) + default: + // todo throw + null + } } private String getInlineResponseName (String path, String httpStatus) { diff --git a/src/main/groovy/com/github/hauner/openapi/spring/model/Endpoint.groovy b/src/main/groovy/com/github/hauner/openapi/spring/model/Endpoint.groovy index fef1ea59..7443fa6a 100644 --- a/src/main/groovy/com/github/hauner/openapi/spring/model/Endpoint.groovy +++ b/src/main/groovy/com/github/hauner/openapi/spring/model/Endpoint.groovy @@ -16,7 +16,7 @@ package com.github.hauner.openapi.spring.model -import com.github.hauner.openapi.spring.model.parameters.QueryParameter +import com.github.hauner.openapi.spring.model.parameters.Parameter /** * Endpoint properties. @@ -28,7 +28,7 @@ class Endpoint { HttpMethod method List responses = [] - List parameters = [] + List parameters = [] Response getResponse () { responses.first () diff --git a/src/main/groovy/com/github/hauner/openapi/spring/model/parameters/Parameter.groovy b/src/main/groovy/com/github/hauner/openapi/spring/model/parameters/Parameter.groovy new file mode 100644 index 00000000..2ce65c5a --- /dev/null +++ b/src/main/groovy/com/github/hauner/openapi/spring/model/parameters/Parameter.groovy @@ -0,0 +1,26 @@ +/* + * Copyright 2019 the original 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 + * + * http://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 com.github.hauner.openapi.spring.model.parameters + +/** + * Common parameter interface implemented by all OpenAPI parameter types. + * + * @author Martin Hauner + */ +interface Parameter { + +} diff --git a/src/main/groovy/com/github/hauner/openapi/spring/model/parameters/PathParameter.groovy b/src/main/groovy/com/github/hauner/openapi/spring/model/parameters/PathParameter.groovy new file mode 100644 index 00000000..e7c70a57 --- /dev/null +++ b/src/main/groovy/com/github/hauner/openapi/spring/model/parameters/PathParameter.groovy @@ -0,0 +1,72 @@ +/* + * Copyright 2019 the original 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 + * + * http://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 com.github.hauner.openapi.spring.model.parameters + +import com.github.hauner.openapi.spring.model.datatypes.DataType + +/** + * OpenAPI path parameter. + * + * @author Martin Hauner + */ +class PathParameter implements Parameter { + String name + boolean required + DataType dataType + + String getAnnotationName () { + "PathVariable" + } + + String getAnnotationWithPackage () { + "org.springframework.web.bind.annotation.${annotationName}" + } + + String getAnnotation () { + "@${annotationName}" + } + + Set getDataTypeImports () { + dataType.imports + } + + /** + * Is the parameter required? + * + * @return true if the parameter is required, otherwise false. + */ + boolean isRequired () { + required + } + + /** + * Create annotation? + */ + boolean withAnnotation () { + true + } + + /** + * Create annotation with parameters? + * + * @return true if the annotation should have parameters, false otherwise + */ + boolean withParameters () { + true + } + +} diff --git a/src/main/groovy/com/github/hauner/openapi/spring/model/parameters/QueryParameter.groovy b/src/main/groovy/com/github/hauner/openapi/spring/model/parameters/QueryParameter.groovy index d7f63bf3..bccf9f5e 100644 --- a/src/main/groovy/com/github/hauner/openapi/spring/model/parameters/QueryParameter.groovy +++ b/src/main/groovy/com/github/hauner/openapi/spring/model/parameters/QueryParameter.groovy @@ -26,7 +26,7 @@ import com.github.hauner.openapi.spring.model.datatypes.ObjectDataType * * @author Martin Hauner */ -class QueryParameter { +class QueryParameter implements Parameter { String name boolean required DataType dataType diff --git a/src/main/groovy/com/github/hauner/openapi/spring/writer/MethodWriter.groovy b/src/main/groovy/com/github/hauner/openapi/spring/writer/MethodWriter.groovy index 84131c0a..73782e78 100644 --- a/src/main/groovy/com/github/hauner/openapi/spring/writer/MethodWriter.groovy +++ b/src/main/groovy/com/github/hauner/openapi/spring/writer/MethodWriter.groovy @@ -17,7 +17,7 @@ package com.github.hauner.openapi.spring.writer import com.github.hauner.openapi.spring.model.Endpoint -import com.github.hauner.openapi.spring.model.parameters.QueryParameter +import com.github.hauner.openapi.spring.model.parameters.Parameter import com.github.hauner.openapi.support.Identifier /** @@ -48,11 +48,11 @@ class MethodWriter { mapping } - private String createParameterAnnotation (QueryParameter parameter) { + private String createParameterAnnotation (Parameter parameter) { String param = "${parameter.annotation}" if (! parameter.withParameters ()) { - return param; + return param } param += '(' diff --git a/src/test/groovy/com/github/hauner/openapi/spring/converter/ApiConverterParameterSpec.groovy b/src/test/groovy/com/github/hauner/openapi/spring/converter/ApiConverterParameterSpec.groovy index 1d0519dd..ad3e457c 100644 --- a/src/test/groovy/com/github/hauner/openapi/spring/converter/ApiConverterParameterSpec.groovy +++ b/src/test/groovy/com/github/hauner/openapi/spring/converter/ApiConverterParameterSpec.groovy @@ -58,6 +58,48 @@ paths: param.name == 'foo' param.required param.dataType.name == 'String' + param.annotation == '@RequestParam' + param.annotationWithPackage == 'org.springframework.web.bind.annotation.RequestParam' + } + + void "converts simple path parameter"() { + def openApi = parse ( +"""\ +openapi: 3.0.2 +info: + title: test simple path parameter + version: 1.0.0 + +paths: + /endpoint/{foo}: + + get: + tags: + - endpoint + parameters: + - name: foo + description: path, required, string + in: path + required: true + schema: + type: string + responses: + '204': + description: empty +""") + + when: + def api = new ApiConverter ().convert (openApi) + + then: + def itf = api.interfaces.first () + def ep = itf.endpoints.first () + def param = ep.parameters.first () + param.name == 'foo' + param.required + param.dataType.name == 'String' + param.annotation == '@PathVariable' + param.annotationWithPackage == 'org.springframework.web.bind.annotation.PathVariable' } }