1
1
/*
2
- * Copyright 2019 the original authors
2
+ * Copyright 2019-2020 the original authors
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
@@ -21,10 +21,13 @@ import com.github.hauner.openapi.spring.converter.schema.RefResolver
21
21
import com.github.hauner.openapi.spring.converter.schema.ResponseSchemaInfo
22
22
import com.github.hauner.openapi.spring.converter.schema.SchemaInfo
23
23
import com.github.hauner.openapi.spring.model.Api
24
+ import com.github.hauner.openapi.spring.model.DataTypes
24
25
import com.github.hauner.openapi.spring.model.Endpoint
25
- import com.github.hauner.openapi.spring.model.RequestBody
26
+ import com.github.hauner.openapi.spring.model.RequestBody as ModelRequestBody
27
+ import com.github.hauner.openapi.spring.model.datatypes.ObjectDataType
26
28
import com.github.hauner.openapi.spring.model.parameters.CookieParameter
27
29
import com.github.hauner.openapi.spring.model.parameters.HeaderParameter
30
+ import com.github.hauner.openapi.spring.model.parameters.MultipartParameter
28
31
import com.github.hauner.openapi.spring.model.parameters.Parameter as ModelParameter
29
32
import com.github.hauner.openapi.spring.model.parameters.PathParameter
30
33
import com.github.hauner.openapi.spring.model.parameters.QueryParameter
@@ -36,7 +39,9 @@ import io.swagger.v3.oas.models.OpenAPI
36
39
import io.swagger.v3.oas.models.PathItem
37
40
import io.swagger.v3.oas.models.media.MediaType
38
41
import io.swagger.v3.oas.models.parameters.Parameter
42
+ import io.swagger.v3.oas.models.parameters.RequestBody
39
43
import io.swagger.v3.oas.models.responses.ApiResponse
44
+ import io.swagger.v3.oas.models.responses.ApiResponses
40
45
41
46
/**
42
47
* Converts the open api model to a new model that is better suited for generating source files
@@ -46,6 +51,7 @@ import io.swagger.v3.oas.models.responses.ApiResponse
46
51
*/
47
52
@Slf4j
48
53
class ApiConverter {
54
+ public static final String MULTIPART = " multipart/form-data"
49
55
50
56
private DataTypeConverter dataTypeConverter
51
57
private ApiOptions options
@@ -76,7 +82,6 @@ class ApiConverter {
76
82
}
77
83
78
84
private Map<String , PathItem > addEndpointsToInterfaces (OpenAPI api , Api target ) {
79
- def resolver = new RefResolver (api. components)
80
85
81
86
api. paths. each { Map.Entry <String , PathItem > pathEntry ->
82
87
String path = pathEntry. key
@@ -89,47 +94,11 @@ class ApiConverter {
89
94
Endpoint ep = new Endpoint (path : path, method : httpOperation. httpMethod)
90
95
91
96
try {
92
- httpOperation. parameters. each { Parameter parameter ->
93
- ep. parameters. addAll (createParameter(path, parameter, target, resolver))
94
- }
95
-
96
- if (httpOperation. requestBody != null ) {
97
- def required = httpOperation. requestBody. required != null ?: false
98
- httpOperation. requestBody. content. each { Map.Entry <String , MediaType > requestBodyEntry ->
99
- def contentType = requestBodyEntry. key
100
- def requestBody = requestBodyEntry. value
101
-
102
- def info = new SchemaInfo (path, requestBody. schema, getInlineTypeName (path))
103
- info. resolver = resolver
104
-
105
- DataType dataType = dataTypeConverter. convert (info, target. models)
106
-
107
- def body = new RequestBody (
108
- contentType : contentType,
109
- requestBodyType : dataType,
110
- required : required)
111
-
112
- ep. requestBodies. add (body)
113
- }
114
- }
115
-
116
- httpOperation. responses. each { Map.Entry <String , ApiResponse > responseEntry ->
117
- def httpStatus = responseEntry. key
118
- def httpResponse = responseEntry. value
119
-
120
- if (! httpResponse. content) {
121
- ep. responses. add (createEmptyResponse ())
122
- } else {
123
- List<Response > responses = createResponses (
124
- path,
125
- httpResponse,
126
- getInlineResponseName (path, httpStatus),
127
- target,
128
- resolver)
129
-
130
- ep. responses. addAll (responses)
131
- }
132
- }
97
+ def resolver = new RefResolver (api. components)
98
+
99
+ collectParameters (httpOperation. parameters, ep, target. models, resolver)
100
+ collectRequestBody (httpOperation. requestBody, ep, target. models, resolver)
101
+ collectResponses (httpOperation. responses, ep, target. models, resolver)
133
102
134
103
itf. endpoints. add (ep)
135
104
@@ -140,11 +109,59 @@ class ApiConverter {
140
109
}
141
110
}
142
111
143
- private ModelParameter createParameter (String path , Parameter parameter , Api target , resolver ) {
112
+ private void collectParameters (List<Parameter > parameters , Endpoint ep , DataTypes dataTypes , RefResolver resolver ) {
113
+ parameters. each { Parameter parameter ->
114
+ ep. parameters. add (createParameter (ep. path, parameter, dataTypes, resolver))
115
+ }
116
+ }
117
+
118
+ private void collectRequestBody (RequestBody requestBody , Endpoint ep , DataTypes dataTypes , RefResolver resolver ) {
119
+ if (requestBody == null ) {
120
+ return
121
+ }
122
+
123
+ def required = requestBody. required != null ?: false
124
+
125
+ requestBody. content. each { Map.Entry <String , MediaType > requestBodyEntry ->
126
+ def contentType = requestBodyEntry. key
127
+ def reqBody = requestBodyEntry. value
128
+
129
+ def info = new SchemaInfo (ep. path, reqBody. schema, getInlineTypeName (ep. path))
130
+ info. resolver = resolver
131
+
132
+ if (contentType == MULTIPART ) {
133
+ ep. parameters. addAll (createMultipartParameter (info, required))
134
+ } else {
135
+ ep. requestBodies. add (createRequestBody (contentType, info, required, dataTypes))
136
+ }
137
+ }
138
+ }
139
+
140
+ private collectResponses (ApiResponses responses , Endpoint ep , DataTypes dataTypes , RefResolver resolver ) {
141
+ responses. each { Map.Entry <String , ApiResponse > responseEntry ->
142
+ def httpStatus = responseEntry. key
143
+ def httpResponse = responseEntry. value
144
+
145
+ if (! httpResponse. content) {
146
+ ep. responses. add (createEmptyResponse ())
147
+ } else {
148
+ List<Response > results = createResponses (
149
+ ep. path,
150
+ httpResponse,
151
+ getInlineResponseName (ep. path, httpStatus),
152
+ dataTypes,
153
+ resolver)
154
+
155
+ ep. responses. addAll (results)
156
+ }
157
+ }
158
+ }
159
+
160
+ private ModelParameter createParameter (String path , Parameter parameter , DataTypes dataTypes , resolver ) {
144
161
def info = new ParameterSchemaInfo (path, parameter. schema, parameter. name)
145
162
info. resolver = resolver
146
163
147
- DataType dataType = dataTypeConverter. convert (info, target . models )
164
+ DataType dataType = dataTypeConverter. convert (info, dataTypes )
148
165
149
166
switch (parameter. in ) {
150
167
case ' query' :
@@ -161,19 +178,27 @@ class ApiConverter {
161
178
}
162
179
}
163
180
164
- private String getInlineTypeName (String path ) {
165
- Identifier . toClass (path) + ' RequestBody'
166
- }
181
+ private ModelRequestBody createRequestBody (String contentType , SchemaInfo info , boolean required , DataTypes dataTypes ) {
182
+ DataType dataType = dataTypeConverter. convert (info, dataTypes)
167
183
168
- private String getInlineResponseName (String path , String httpStatus ) {
169
- Identifier . toClass (path) + ' Response' + httpStatus
184
+ new ModelRequestBody (
185
+ contentType : contentType,
186
+ requestBodyType : dataType,
187
+ required : required)
170
188
}
171
189
172
- private Response createEmptyResponse () {
173
- new Response (responseType : dataTypeConverter. none ())
190
+ private Collection<ModelParameter > createMultipartParameter (SchemaInfo info , boolean required ) {
191
+ DataType dataType = dataTypeConverter. convert (info, new DataTypes ())
192
+ if (! (dataType instanceof ObjectDataType )) {
193
+ throw new MultipartResponseBodyException (info. path)
194
+ }
195
+
196
+ dataType. getObjectProperties (). collect {
197
+ new MultipartParameter (name : it. key, required : required, dataType : it. value)
198
+ }
174
199
}
175
200
176
- private List<Response > createResponses (String path , ApiResponse apiResponse , String inlineName , Api target , RefResolver resolver ) {
201
+ private List<Response > createResponses (String path , ApiResponse apiResponse , String inlineName , DataTypes dataTypes , RefResolver resolver ) {
177
202
def responses = []
178
203
179
204
apiResponse. content. each { Map.Entry <String , MediaType > contentEntry ->
@@ -188,9 +213,7 @@ class ApiConverter {
188
213
inlineName)
189
214
info. resolver = resolver
190
215
191
- DataType dataType = dataTypeConverter. convert (
192
- info,
193
- target. models)
216
+ DataType dataType = dataTypeConverter. convert (info, dataTypes)
194
217
195
218
def response = new Response (
196
219
contentType : contentType,
@@ -202,6 +225,18 @@ class ApiConverter {
202
225
responses
203
226
}
204
227
228
+ private String getInlineTypeName (String path ) {
229
+ Identifier . toClass (path) + ' RequestBody'
230
+ }
231
+
232
+ private String getInlineResponseName (String path , String httpStatus ) {
233
+ Identifier . toClass (path) + ' Response' + httpStatus
234
+ }
235
+
236
+ private Response createEmptyResponse () {
237
+ new Response (responseType : dataTypeConverter. none ())
238
+ }
239
+
205
240
private void collectInterfaces (OpenAPI api , Api target ) {
206
241
target. interfaces = new InterfaceCollector (options)
207
242
.collect (api. paths)
0 commit comments