Skip to content

Commit c6ef454

Browse files
authored
Merge pull request #70 from hauner/mapping-reader
mapping yaml is easier to understand with a java mapping
2 parents fa0b14a + 5ef4457 commit c6ef454

File tree

13 files changed

+547
-59
lines changed

13 files changed

+547
-59
lines changed

build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ plugins {
99
group 'com.github.hauner.openapi'
1010
version '1.0.0.M5'
1111

12+
sourceCompatibility = JavaVersion.VERSION_1_8
1213
targetCompatibility = JavaVersion.VERSION_1_8
1314

1415
ext {
@@ -35,7 +36,7 @@ check.dependsOn testInt
3536
dependencies {
3637
implementation 'org.codehaus.groovy:groovy:2.5.4'
3738
implementation 'io.swagger.parser.v3:swagger-parser:2.0.12'
38-
implementation 'org.yaml:snakeyaml:1.25'
39+
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.9.8'
3940
implementation 'com.google.googlejavaformat:google-java-format:1.7'
4041
compileOnly "com.github.hauner.openapi:openapi-generatr-api:$generatrApiVersion"
4142

src/main/groovy/com/github/hauner/openapi/spring/generatr/TypeMappingReader.groovy

Lines changed: 77 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,26 @@
1616

1717
package com.github.hauner.openapi.spring.generatr
1818

19+
import com.fasterxml.jackson.databind.DeserializationFeature
20+
import com.fasterxml.jackson.databind.ObjectMapper
21+
import com.fasterxml.jackson.databind.PropertyNamingStrategy
22+
import com.fasterxml.jackson.databind.module.SimpleModule
23+
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
1924
import com.github.hauner.openapi.spring.converter.mapping.AddParameterTypeMapping
2025
import com.github.hauner.openapi.spring.converter.mapping.EndpointTypeMapping
2126
import com.github.hauner.openapi.spring.converter.mapping.ParameterTypeMapping
2227
import com.github.hauner.openapi.spring.converter.mapping.ResponseTypeMapping
2328
import com.github.hauner.openapi.spring.converter.mapping.TypeMapping
2429
import com.github.hauner.openapi.spring.converter.mapping.Mapping
25-
import org.yaml.snakeyaml.Yaml
30+
import com.github.hauner.openapi.spring.generatr.mapping.AdditionalParameter
31+
import com.github.hauner.openapi.spring.generatr.mapping.Mapping as YamlMapping
32+
import com.github.hauner.openapi.spring.generatr.mapping.Parameter
33+
import com.github.hauner.openapi.spring.generatr.mapping.Parameter as YamlParameter
34+
import com.github.hauner.openapi.spring.generatr.mapping.ParameterDeserializer
35+
import com.github.hauner.openapi.spring.generatr.mapping.Path as YamlPath
36+
import com.github.hauner.openapi.spring.generatr.mapping.RequestParameter
37+
import com.github.hauner.openapi.spring.generatr.mapping.Response as YamlResponse
38+
import com.github.hauner.openapi.spring.generatr.mapping.Type as YamlType
2639

2740
import java.util.regex.Matcher
2841
import java.util.regex.Pattern
@@ -36,7 +49,7 @@ class TypeMappingReader {
3649
private Pattern GENERIC_INLINE = ~/(.+?)<(.+?)>/
3750

3851
List<Mapping> read (String typeMappings) {
39-
if (typeMappings == null) {
52+
if (typeMappings == null || typeMappings.empty) {
4053
return []
4154
}
4255

@@ -45,90 +58,91 @@ class TypeMappingReader {
4558
mapping = new File(typeMappings).text
4659
}
4760

48-
Yaml yaml = new Yaml()
49-
Map props = yaml.load (mapping)
61+
def mapper = createYamlParser()
62+
def props = mapper.readValue (mapping, YamlMapping)
5063

51-
if (props == null) {
52-
return null
53-
}
54-
55-
parse (props)
64+
convert (props)
5665
}
5766

58-
private List<Mapping> parse (Map<String, ?> props) {
59-
//def version = props.get ('openapi-generatr-spring')
67+
private List<Mapping> convert (YamlMapping source) {
68+
def result = new ArrayList<Mapping>()
6069

61-
def root = props.get ('map') as Map<String, ?>
70+
source.map.types.each {
71+
result.add (convert (it))
72+
}
6273

63-
def mappings = readTypeMappings (root)
74+
source.map.parameters.each {
75+
result.add (convert (it))
76+
}
6477

65-
def paths = root.get ('paths') as Map<String, ?>
66-
paths.each {
67-
def epm = new EndpointTypeMapping(path: it.key)
68-
def types = readTypeMappings (it.value as Map<String, ?>)
69-
epm.typeMappings = types
70-
mappings.add (epm)
78+
source.map.responses.each {
79+
result.add (convert (it))
7180
}
7281

73-
mappings
82+
source.map.paths.each {
83+
result.add(convert (it.key, it.value))
84+
}
85+
86+
result
7487
}
7588

76-
private List<Mapping> readTypeMappings (Map<String, ?> root) {
77-
def mappings = []
89+
private EndpointTypeMapping convert (String path, YamlPath source) {
90+
def result = new ArrayList<Mapping>()
7891

79-
def types = root.get ('types') as List<Map<String, ?> >
80-
types.each { Map<String, ?> it ->
81-
mappings.add (readTypMapping (it))
92+
source.types.each {
93+
result.add (convert (it))
8294
}
8395

84-
def responses = root.get ('responses') as List<Map<String, ?> >
85-
responses.each {
86-
mappings.add (readResponseTypeMapping (it))
96+
source.parameters.each {
97+
result.add (convert (it))
8798
}
8899

89-
def parameters = root.get ('parameters') as List<Map<String, ?> >
90-
parameters.each {
91-
mappings.add (readParameterTypeMapping (it))
100+
source.responses.each {
101+
result.add (convert (it))
92102
}
93103

94-
return mappings
104+
new EndpointTypeMapping(path: path, typeMappings: result)
95105
}
96106

97-
private Mapping readParameterTypeMapping (Map<String, ?> source) {
98-
if (isParameterMappings (source)) {
107+
private Mapping convert (YamlParameter source) {
108+
if (source instanceof RequestParameter) {
99109
def name = source.name
100-
def mapping = readTypMapping (source)
110+
def mapping = convert (new YamlType(
111+
from: null,
112+
to: source.to,
113+
generics: source.generics
114+
))
101115
new ParameterTypeMapping (parameterName: name, mapping: mapping)
102116

103-
} else if (isParameterAddition (source)) {
117+
} else if (source instanceof AdditionalParameter) {
104118
def name = source.add
105-
def mapping = readTypMapping (source, 'as')
119+
def mapping = convert (new YamlType(
120+
from: null,
121+
to: source.to,
122+
generics: source.generics
123+
))
106124
new AddParameterTypeMapping (parameterName: name, mapping: mapping)
107125

108126
} else {
109127
throw new Exception("unknown parameter mapping $source")
110128
}
111129
}
112130

113-
private boolean isParameterAddition (Map<String, ?> source) {
114-
source.containsKey ('add') && source.containsKey ('as')
115-
}
116-
117-
private boolean isParameterMappings (Map<String, ?> source) {
118-
source.containsKey ('name') && source.containsKey ('to')
119-
}
120-
121-
private ResponseTypeMapping readResponseTypeMapping (Map<String, ?> source) {
131+
private ResponseTypeMapping convert (YamlResponse source) {
122132
def content = source.content
123-
def mapping = readTypMapping (source)
133+
def mapping = convert (new YamlType(
134+
from: null,
135+
to: source.to,
136+
generics: source.generics
137+
))
124138
new ResponseTypeMapping(contentType: content, mapping: mapping)
125139
}
126140

127-
private TypeMapping readTypMapping (Map<String, ?> source, String target = 'to') {
128-
Matcher matcher = source.to =~ GENERIC_INLINE
141+
private TypeMapping convert (YamlType type) {
142+
Matcher matcher = type.to =~ GENERIC_INLINE
129143

130-
def (from, format) = source.from ? (source.from as String).tokenize (':') : [null, null]
131-
String to = source[target]
144+
def (from, format) = type.from ? (type.from as String).tokenize (':') : [null, null]
145+
String to = type.to
132146
List<String> generics = []
133147

134148
// has inline generics
@@ -140,15 +154,25 @@ class TypeMappingReader {
140154
.collect { it.trim () }
141155

142156
// has explicit generic list
143-
} else if (source.containsKey ('generics')) {
144-
generics = source.generics as List
157+
} else if (type.generics) {
158+
generics = type.generics
145159
}
146160

147161
new TypeMapping (
148162
sourceTypeName: from, sourceTypeFormat: format,
149163
targetTypeName: to, genericTypeNames: generics)
150164
}
151165

166+
private ObjectMapper createYamlParser () {
167+
SimpleModule module = new SimpleModule ()
168+
module.addDeserializer (Parameter, new ParameterDeserializer ())
169+
170+
new ObjectMapper (new YAMLFactory ())
171+
.configure (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
172+
.setPropertyNamingStrategy (PropertyNamingStrategy.KEBAB_CASE)
173+
.registerModule (module)
174+
}
175+
152176
private boolean isFileName (String name) {
153177
name.endsWith ('.yaml') || name.endsWith ('.yml')
154178
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2020 the original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.github.hauner.openapi.spring.generatr.mapping
18+
19+
import com.fasterxml.jackson.annotation.JsonProperty
20+
21+
/**
22+
* a "parameters:" add parameter entry in the mapping yaml
23+
*
24+
* @author Martin Hauner
25+
*/
26+
class AdditionalParameter extends Parameter {
27+
28+
/**
29+
* name of the additional parameter
30+
*/
31+
String add
32+
33+
/**
34+
* target java type
35+
*/
36+
String to
37+
38+
/**
39+
* (optional) generic parameters of {@link #to}
40+
*/
41+
List<String> generics
42+
43+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2020 the original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.github.hauner.openapi.spring.generatr.mapping
18+
19+
/**
20+
* the "map:" entry in the mapping yaml
21+
*
22+
* @author Martin Hauner
23+
*/
24+
class Map {
25+
26+
/**
27+
* global type mappings
28+
*/
29+
List<Type> types
30+
31+
/**
32+
* global parameter mappings
33+
*/
34+
List<Parameter> parameters
35+
36+
/**
37+
* global response mappings
38+
*/
39+
List<Response> responses
40+
41+
/**
42+
* endpoint mappings
43+
*
44+
* the LinkedHashMap preserves order
45+
*/
46+
LinkedHashMap<String, Path> paths
47+
48+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2020 the original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.github.hauner.openapi.spring.generatr.mapping
18+
19+
/**
20+
* *the* Schema of the mapping yaml
21+
*
22+
* @author Martin Hauner
23+
*/
24+
class Mapping {
25+
26+
/**
27+
* version (currently optional)
28+
*/
29+
String openapiGeneratrSpring
30+
31+
/**
32+
* the mappings
33+
*/
34+
Map map
35+
36+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2020 the original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.github.hauner.openapi.spring.generatr.mapping
18+
19+
/**
20+
* a "parameters:" entry in the mapping yaml
21+
*
22+
* @author Martin Hauner
23+
*/
24+
class Parameter {
25+
}

0 commit comments

Comments
 (0)