Skip to content

Commit 52a30e3

Browse files
committed
Merge branch '#68'
Conflicts: src/main/groovy/com/github/hauner/openapi/spring/generatr/SpringGeneratr.groovy src/testInt/groovy/com/github/hauner/openapi/generatr/GeneratrEndToEndTest.groovy
2 parents e603ce2 + ef83b99 commit 52a30e3

File tree

19 files changed

+511
-319
lines changed

19 files changed

+511
-319
lines changed

src/main/groovy/com/github/hauner/openapi/spring/converter/ApiConverter.groovy

Lines changed: 75 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package com.github.hauner.openapi.spring.converter
1818

1919
import com.github.hauner.openapi.spring.converter.mapping.AddParameterTypeMapping
20+
import com.github.hauner.openapi.spring.converter.mapping.AmbiguousTypeMappingException
21+
import com.github.hauner.openapi.spring.converter.mapping.EndpointTypeMapping
2022
import com.github.hauner.openapi.spring.converter.mapping.Mapping
2123
import com.github.hauner.openapi.spring.converter.mapping.MappingSchema
2224
import com.github.hauner.openapi.spring.converter.mapping.TargetType
@@ -26,6 +28,7 @@ import com.github.hauner.openapi.spring.converter.schema.SchemaInfo
2628
import com.github.hauner.openapi.spring.model.Api
2729
import com.github.hauner.openapi.spring.model.DataTypes
2830
import com.github.hauner.openapi.spring.model.Endpoint
31+
import com.github.hauner.openapi.spring.model.Interface
2932
import com.github.hauner.openapi.spring.model.RequestBody as ModelRequestBody
3033
import com.github.hauner.openapi.spring.model.datatypes.MappedDataType
3134
import com.github.hauner.openapi.spring.model.datatypes.ObjectDataType
@@ -57,16 +60,17 @@ import io.swagger.v3.oas.models.responses.ApiResponses
5760
@Slf4j
5861
class ApiConverter {
5962
public static final String MULTIPART = "multipart/form-data"
63+
public static final String INTERFACE_DEFAULT_NAME = ''
6064

6165
private DataTypeConverter dataTypeConverter
6266
private ApiOptions options
6367

6468
class MappingSchemaEndpoint implements MappingSchema {
65-
Endpoint endpoint
69+
String path
6670

6771
@Override
6872
String getPath () {
69-
endpoint.path
73+
path
7074
}
7175

7276
@Override
@@ -98,40 +102,62 @@ class ApiConverter {
98102
*/
99103
Api convert (OpenAPI api) {
100104
def target = new Api ()
101-
102-
collectInterfaces (api, target)
103-
addEndpointsToInterfaces (api, target)
104-
105+
createInterfaces (api, target)
105106
target
106107
}
107108

108-
private Map<String, PathItem> addEndpointsToInterfaces (OpenAPI api, Api target) {
109+
private void createInterfaces (OpenAPI api, Api target) {
110+
def resolver = new RefResolver (api.components)
111+
Map<String, Interface>interfaces = new HashMap<> ()
109112

110113
api.paths.each { Map.Entry<String, PathItem> pathEntry ->
111114
String path = pathEntry.key
112115
PathItem pathItem = pathEntry.value
113116

114-
def operations = new OperationCollector ().collect (pathItem)
117+
def operations = new OperationCollector ()
118+
.collect (pathItem)
119+
115120
operations.each { httpOperation ->
116-
def itf = target.getInterface (getInterfaceName (httpOperation))
121+
Interface itf = createInterface (path, httpOperation, interfaces)
122+
Endpoint ep = createEndpoint (path, httpOperation, target.models, resolver)
123+
if (ep) {
124+
itf.endpoints.add (ep)
125+
}
126+
}
127+
}
117128

118-
Endpoint ep = new Endpoint (path: path,
119-
method: (httpOperation as HttpMethodTrait).httpMethod)
129+
target.interfaces = interfaces.values () as List<Interface>
130+
}
120131

121-
try {
122-
def resolver = new RefResolver (api.components)
132+
private Interface createInterface (String path, def operation, Map<String, Interface> interfaces) {
133+
def targetInterfaceName = getInterfaceName (operation, isExcluded (path))
123134

124-
collectParameters (httpOperation.parameters, ep, target.models, resolver)
125-
collectRequestBody (httpOperation.requestBody, ep, target.models, resolver)
126-
collectResponses (httpOperation.responses, ep, target.models, resolver)
135+
def itf = interfaces.get (targetInterfaceName)
136+
if (itf) {
137+
return itf
138+
}
127139

128-
itf.endpoints.add (ep)
140+
itf = new Interface (
141+
pkg: [options.packageName, 'api'].join ('.'),
142+
name: targetInterfaceName
143+
)
129144

130-
} catch (UnknownDataTypeException e) {
131-
log.error ("failed to parse endpoint {} {} because of: '{}'",
132-
ep.path, ep.method, e.message)
133-
}
134-
}
145+
interfaces.put (targetInterfaceName, itf)
146+
itf
147+
}
148+
149+
private Endpoint createEndpoint (String path, def operation, DataTypes dataTypes, RefResolver resolver) {
150+
Endpoint ep = new Endpoint (path: path, method: (operation as HttpMethodTrait).httpMethod)
151+
152+
try {
153+
collectParameters (operation.parameters, ep, dataTypes, resolver)
154+
collectRequestBody (operation.requestBody, ep, dataTypes, resolver)
155+
collectResponses (operation.responses, ep, dataTypes, resolver)
156+
ep
157+
158+
} catch (UnknownDataTypeException e) {
159+
log.error ("failed to parse endpoint {} {} because of: '{}'", ep.path, ep.method, e.message)
160+
null
135161
}
136162
}
137163

@@ -277,13 +303,13 @@ class ApiConverter {
277303

278304
private List<Mapping> findAdditionalParameter (Endpoint ep) {
279305
def addMappings = options.typeMappings.findAll {
280-
it.matches (Mapping.Level.ENDPOINT, new MappingSchemaEndpoint (endpoint: ep))
306+
it.matches (Mapping.Level.ENDPOINT, new MappingSchemaEndpoint (path: ep.path))
281307
}.collectMany {
282308
it.childMappings
283309
}.findAll {
284310
it.matches (Mapping.Level.ADD, null as MappingSchema)
285311
}
286-
addMappings
312+
addMappings as List<Mapping>
287313
}
288314

289315
private String getInlineRequestBodyName (String path) {
@@ -298,17 +324,35 @@ class ApiConverter {
298324
new Response (responseType: dataTypeConverter.none ())
299325
}
300326

301-
private void collectInterfaces (OpenAPI api, Api target) {
302-
target.interfaces = new InterfaceCollector (options)
303-
.collect (api.paths)
327+
private boolean isExcluded (String path) {
328+
def endpointMatches = options.typeMappings.findAll {
329+
it.matches (Mapping.Level.ENDPOINT, new MappingSchemaEndpoint(path: path))
330+
}
331+
332+
if (!endpointMatches.empty) {
333+
if (endpointMatches.size () != 1) {
334+
throw new AmbiguousTypeMappingException (endpointMatches)
335+
}
336+
337+
def match = endpointMatches.first () as EndpointTypeMapping
338+
return match.exclude
339+
}
340+
341+
false
304342
}
305343

306-
private String getInterfaceName(def operation) {
307-
if (!hasTags (operation)) {
308-
return InterfaceCollector.INTERFACE_DEFAULT_NAME
344+
private String getInterfaceName (def op, boolean excluded) {
345+
String targetInterfaceName = INTERFACE_DEFAULT_NAME
346+
347+
if (hasTags (op)) {
348+
targetInterfaceName = op.tags.first ()
349+
}
350+
351+
if (excluded) {
352+
targetInterfaceName += 'Excluded'
309353
}
310354

311-
operation.tags.first ()
355+
targetInterfaceName
312356
}
313357

314358
private boolean hasTags (op) {

src/main/groovy/com/github/hauner/openapi/spring/converter/InterfaceCollector.groovy

Lines changed: 0 additions & 84 deletions
This file was deleted.

src/main/groovy/com/github/hauner/openapi/spring/converter/mapping/EndpointTypeMapping.groovy

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ class EndpointTypeMapping implements Mapping {
3434
*/
3535
String path
3636

37+
/**
38+
* Exclude endpoint.
39+
*/
40+
boolean exclude
41+
3742
/**
3843
* Provides type mappings for the endpoint. The list can contain the following mappings:
3944
*

0 commit comments

Comments
 (0)