Skip to content

Commit d67125a

Browse files
committed
yaml mapping reader
1 parent 22025d1 commit d67125a

File tree

4 files changed

+386
-0
lines changed

4 files changed

+386
-0
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Copyright 2019 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
18+
19+
import com.github.hauner.openapi.spring.generatr.mapping.EndpointTypeMapping
20+
import com.github.hauner.openapi.spring.generatr.mapping.ParameterTypeMapping
21+
import com.github.hauner.openapi.spring.generatr.mapping.ResponseTypeMapping
22+
import com.github.hauner.openapi.spring.generatr.mapping.TypeMapping
23+
import org.yaml.snakeyaml.Yaml
24+
25+
import java.util.regex.Matcher
26+
import java.util.regex.Pattern
27+
28+
/**
29+
* Reader for mapping yaml.
30+
*
31+
* @author Martin Hauner
32+
*/
33+
class TypeMappingReader {
34+
private Pattern GENERIC_INLINE = ~/(.+?)<(.+?)>/
35+
36+
List<?> read (String typeMappings) {
37+
if (typeMappings == null) {
38+
return []
39+
}
40+
41+
String mapping = typeMappings
42+
if (isFileName (typeMappings)) {
43+
mapping = new File(typeMappings).text
44+
}
45+
46+
Yaml yaml = new Yaml()
47+
Map props = yaml.load (mapping)
48+
parse (props)
49+
}
50+
51+
private List<?> parse (Map<String, ?> props) {
52+
//def version = props.get ('openapi-generatr-spring')
53+
54+
def root = props.get ('map') as Map<String, ?>
55+
56+
def mappings = readTypeMappings (root)
57+
58+
def paths = root.get ('paths') as Map<String, ?>
59+
paths.each {
60+
def epm = new EndpointTypeMapping(path: it.key)
61+
epm.typeMappings = readTypeMappings (it.value as Map<String, ?>)
62+
mappings.add (epm)
63+
}
64+
65+
mappings
66+
}
67+
68+
private List<?> readTypeMappings (Map<String, ?> root) {
69+
def mappings = []
70+
71+
def types = root.get ('types') as List<Map<String, ?> >
72+
types.each { Map<String, ?> it ->
73+
mappings.add (readTypMapping (it))
74+
}
75+
76+
def responses = root.get ('responses') as List<Map<String, ?> >
77+
responses.each {
78+
mappings.add (readResponseTypeMapping (it))
79+
}
80+
81+
def parameters = root.get ('parameters') as List<Map<String, ?> >
82+
parameters.each {
83+
mappings.add (readParameterTypeMapping (it))
84+
}
85+
86+
return mappings
87+
}
88+
89+
private ParameterTypeMapping readParameterTypeMapping (Map<String, ?> source) {
90+
def name = source.name
91+
def mapping = readTypMapping (source)
92+
new ParameterTypeMapping (parameterName: name, mapping: mapping)
93+
}
94+
95+
private ResponseTypeMapping readResponseTypeMapping (Map<String, ?> source) {
96+
def content = source.content
97+
def mapping = readTypMapping (source)
98+
new ResponseTypeMapping(contentType: content, mapping: mapping)
99+
}
100+
101+
private TypeMapping readTypMapping (Map<String, ?> source) {
102+
Matcher matcher = source.to =~ GENERIC_INLINE
103+
104+
String from = source.from
105+
String to = source.to
106+
List<String> generics = []
107+
108+
// has inline generics
109+
if (matcher.find ()) {
110+
to = matcher.group (1)
111+
generics = matcher
112+
.group (2)
113+
.split (',')
114+
.collect { it.trim () }
115+
116+
// has explicit generic list
117+
} else if (source.containsKey ('generics')) {
118+
generics = source.generics as List
119+
}
120+
121+
new TypeMapping (sourceTypeName: from, targetTypeName: to, genericTypeNames: generics)
122+
}
123+
124+
private boolean isFileName (String name) {
125+
name.endsWith ('.yaml') || name.endsWith ('.yml')
126+
}
127+
128+
}

src/main/groovy/com/github/hauner/openapi/spring/generatr/mapping/ResponseTypeMapping.groovy

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,19 @@ class ResponseTypeMapping {
3232
/**
3333
* The OpenAPI schema type that should be mapped to the {@link #targetTypeName} java type.
3434
*/
35+
@Deprecated // use mapping
3536
String sourceTypeName
3637

3738
/**
3839
* The fully qualified java type name that will be used for {@link #sourceTypeName} in an
3940
* {@link #contentType} response.
4041
*/
42+
@Deprecated // use mapping
4143
String targetTypeName
4244

45+
/**
46+
* Type mapping valid only for responses with {@link #contentType}.
47+
*/
48+
TypeMapping mapping
49+
4350
}

src/test/groovy/com/github/hauner/openapi/learn/RegexSpec.groovy

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,14 @@ class RegexSpec extends Specification {
5151
expect:
5252
"prefix\nXXXX\npostfix" ==~ /(?s)prefix(.+?)postfix/
5353
}
54+
55+
void "extract generic types" () {
56+
Pattern p = ~/.+?<(.+?)>/
57+
Matcher m = "mapping.Bar<java.lang.String, java.lang.Boolean>" =~ p
58+
59+
expect:
60+
m.find ()
61+
m.group (1) == "java.lang.String, java.lang.Boolean"
62+
}
63+
5464
}

0 commit comments

Comments
 (0)