Skip to content

Commit 515bf22

Browse files
committed
Rename module and allow for example response
1 parent 0a0684a commit 515bf22

36 files changed

+282
-128
lines changed

mock/core/src/main/java/io/quarkiverse/openapi/generator/QuarkiverseMapper.java

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

mock/core/src/main/java/io/quarkiverse/openapi/generator/QuarkiverseMockImporter.java

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

mock/core/src/main/java/io/quarkiverse/openapi/generator/model/Parameter.java

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

mock/core/pom.xml renamed to moqu/core/pom.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
<modelVersion>4.0.0</modelVersion>
66
<parent>
77
<groupId>io.quarkiverse.openapi.generator</groupId>
8-
<artifactId>quarkus-openapi-generator-mock-parent</artifactId>
8+
<artifactId>quarkus-openapi-generator-moqu-parent</artifactId>
99
<version>3.0.0-SNAPSHOT</version>
1010
</parent>
1111

12-
<artifactId>quarkus-openapi-generator-mock-core</artifactId>
12+
<artifactId>quarkus-openapi-generator-moqu-core</artifactId>
1313

1414
<properties>
1515
<commons.io.version>2.16.1</commons.io.version>
@@ -45,5 +45,9 @@
4545
<artifactId>commons-io</artifactId>
4646
<version>${commons.io.version}</version>
4747
</dependency>
48+
<dependency>
49+
<groupId>org.jboss.logmanager</groupId>
50+
<artifactId>jboss-logmanager</artifactId>
51+
</dependency>
4852
</dependencies>
4953
</project>
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66

77
import io.quarkiverse.openapi.generator.model.RequestResponsePair;
88

9-
public class QuarkiverseMock {
9+
public class Moqu {
1010

1111
private List<RequestResponsePair> requestResponsePairs = new ArrayList<>();
1212

13-
public QuarkiverseMock(List<RequestResponsePair> requestResponsePairs) {
13+
public Moqu(List<RequestResponsePair> requestResponsePairs) {
1414
this.requestResponsePairs = Objects.requireNonNull(requestResponsePairs);
1515
}
1616

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.quarkiverse.openapi.generator;
2+
3+
/**
4+
* {@link MoquImporter} aims to convert an specification {@link Moqu} model.
5+
*/
6+
public interface MoquImporter {
7+
8+
/**
9+
* @param content OpenAPI content
10+
* @return A new {@link Moqu} instance
11+
*/
12+
Moqu parse(String content);
13+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.quarkiverse.openapi.generator;
2+
3+
import java.util.List;
4+
5+
public interface MoquMapper<T> {
6+
7+
List<T> map(Moqu mock);
8+
}
Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
package io.quarkiverse.openapi.generator;
22

3-
import java.util.*;
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
import java.util.Objects;
9+
import java.util.Optional;
10+
import java.util.Set;
411
import java.util.stream.Collectors;
512

13+
import com.google.common.base.Strings;
14+
import io.swagger.v3.oas.models.media.Schema;
615
import org.slf4j.Logger;
716
import org.slf4j.LoggerFactory;
817

@@ -23,13 +32,18 @@
2332
import io.swagger.v3.parser.OpenAPIV3Parser;
2433
import io.swagger.v3.parser.core.models.SwaggerParseResult;
2534

26-
public class OpenAPIQuarkiverseMockImporter implements QuarkiverseMockImporter {
35+
import static io.swagger.v3.parser.util.SchemaTypeUtil.INTEGER_TYPE;
36+
import static io.swagger.v3.parser.util.SchemaTypeUtil.OBJECT_TYPE;
37+
import static io.swagger.v3.parser.util.SchemaTypeUtil.STRING_TYPE;
2738

28-
private static final Logger LOGGER = LoggerFactory.getLogger(OpenAPIQuarkiverseMockImporter.class);
39+
public class OpenAPIMoquImporter implements MoquImporter {
40+
41+
private static final Logger LOGGER = LoggerFactory.getLogger(OpenAPIMoquImporter.class);
2942
private static final String HTTP_HEADER_ACCEPT = "Accept";
43+
private static final String REFERENCE_PREFIX = "#/components/schemas/";
3044

3145
@Override
32-
public QuarkiverseMock parse(String content) {
46+
public Moqu parse(String content) {
3347

3448
SwaggerParseResult swaggerParseResult = new OpenAPIV3Parser().readContents(content);
3549

@@ -45,13 +59,15 @@ public QuarkiverseMock parse(String content) {
4559
throw new IllegalArgumentException("Cannot parse OpenAPI V3 content: " + content);
4660
}
4761

48-
return new QuarkiverseMock(
62+
return new Moqu(
4963
getRequestResponsePairs(openAPI));
5064
}
5165

5266
private List<RequestResponsePair> getRequestResponsePairs(OpenAPI openAPI) {
5367
Map<Request, Response> requestResponsePairs = new HashMap<>();
5468

69+
Map<String, Schema> localSchemas = openAPI.getComponents().getSchemas();
70+
5571
Set<Map.Entry<String, PathItem>> entries = Optional.ofNullable(openAPI.getPaths())
5672
.orElseThrow(IllegalArgumentException::new)
5773
.entrySet();
@@ -73,10 +89,10 @@ private List<RequestResponsePair> getRequestResponsePairs(OpenAPI openAPI) {
7389
}
7490

7591
Map<String, Multimap<String, String>> examplesOnPath = extractParameters(httpMethodOperation.getValue(),
76-
ParameterTypes.PATH);
92+
ParameterType.PATH);
7793

7894
requestResponsePairs.putAll(getContentRequestResponsePairs(statusApiResponse, examplesOnPath,
79-
httpMethodOperation.getKey(), entry.getKey()));
95+
httpMethodOperation.getKey(), entry.getKey(), localSchemas));
8096
}
8197
}
8298
}
@@ -94,17 +110,18 @@ private int tryGetStatusCode(Map.Entry<String, ApiResponse> statusApiResponse) {
94110
}
95111
}
96112

97-
private Map<String, Multimap<String, String>> extractParameters(Operation operation, ParameterTypes parameterTypes) {
113+
private Map<String, Multimap<String, String>> extractParameters(Operation operation, ParameterType parameterType) {
98114
List<Parameter> parameters = Optional.ofNullable(operation.getParameters()).orElse(Collections.emptyList());
99115
Map<String, Multimap<String, String>> finalParameters = new HashMap<>();
100116

101117
for (Parameter parameter : parameters) {
102-
if (isEligibleForExtraction(parameter, parameterTypes)) {
118+
if (isEligibleForExtraction(parameter, parameterType)) {
103119

104120
Set<String> exampleNames = parameter.getExamples().keySet();
105121
for (String exampleName : exampleNames) {
106122

107123
Example example = parameter.getExamples().get(exampleName);
124+
108125
Object object = example.getValue();
109126
String value = resolveContent(object);
110127
finalParameters.computeIfAbsent(exampleName,
@@ -116,12 +133,12 @@ private Map<String, Multimap<String, String>> extractParameters(Operation operat
116133
return finalParameters;
117134
}
118135

119-
private boolean isEligibleForExtraction(Parameter parameter, ParameterTypes type) {
136+
private boolean isEligibleForExtraction(Parameter parameter, ParameterType type) {
120137
return parameter.getIn().equals(type.value()) && !Objects.isNull(parameter.getExamples());
121138
}
122139

123140
private Map<Request, Response> getContentRequestResponsePairs(Map.Entry<String, ApiResponse> statusApiResponse,
124-
Map<String, Multimap<String, String>> parametersOnPath, PathItem.HttpMethod httpMethod, String url) {
141+
Map<String, Multimap<String, String>> parametersOnPath, PathItem.HttpMethod httpMethod, String url, Map<String, Schema> localSchemas) {
125142
Map<Request, Response> requestResponseMap = new HashMap<>();
126143

127144
ApiResponse apiResponse = statusApiResponse.getValue();
@@ -134,11 +151,14 @@ private Map<Request, Response> getContentRequestResponsePairs(Map.Entry<String,
134151
Map<String, Example> examples = Optional.ofNullable(mediaType.getExamples()).orElse(Collections.emptyMap());
135152

136153
examples.forEach((exampleName, example) -> {
154+
155+
String content = resolveContent(localSchemas, example);
156+
137157
Response response = new Response(
138158
exampleName,
139159
mediaType,
140160
statusCode,
141-
resolveContent(example.getValue()),
161+
content,
142162
List.of());
143163

144164
Multimap<String, String> onPath = parametersOnPath.get(exampleName);
@@ -149,13 +169,13 @@ private Map<Request, Response> getContentRequestResponsePairs(Map.Entry<String,
149169
io.quarkiverse.openapi.generator.model.Parameter parameter = new io.quarkiverse.openapi.generator.model.Parameter(
150170
paramEntry.getKey(),
151171
paramEntry.getValue(),
152-
ParameterTypes.PATH);
172+
ParameterType.PATH);
153173
reqParams.add(parameter);
154174
}
155175
}
156176

157177
List<io.quarkiverse.openapi.generator.model.Parameter> parameters = reqParams.stream()
158-
.filter(reqParam -> reqParam.where().equals(ParameterTypes.PATH)).toList();
178+
.filter(reqParam -> reqParam.where().equals(ParameterType.PATH)).toList();
159179
String finalUrl = resolveUrlParameters(url, parameters);
160180
Request request = new Request(
161181
finalUrl,
@@ -170,6 +190,14 @@ private Map<Request, Response> getContentRequestResponsePairs(Map.Entry<String,
170190
return requestResponseMap;
171191
}
172192

193+
private String resolveContent(Map<String, Schema> localSchemas, Example example) {
194+
if (!Strings.isNullOrEmpty(example.get$ref())) {
195+
return resolveRef(example.get$ref(), localSchemas);
196+
} else {
197+
return resolveContent(example.getValue());
198+
}
199+
}
200+
173201
private String resolveUrlParameters(String url, List<io.quarkiverse.openapi.generator.model.Parameter> parameters) {
174202
for (io.quarkiverse.openapi.generator.model.Parameter parameter : parameters) {
175203
String placeholder = "{%s}".formatted(parameter.key());
@@ -178,6 +206,23 @@ private String resolveUrlParameters(String url, List<io.quarkiverse.openapi.gene
178206
return url;
179207
}
180208

209+
private String resolveRef(String ref, Map<String, Schema> localSchemas) {
210+
if (!ref.startsWith(REFERENCE_PREFIX)) {
211+
throw new IllegalArgumentException("There is no support for external $ref schemas. Please, configure the %s as local schema"
212+
.formatted(ref));
213+
}
214+
215+
String refName = ref.substring(REFERENCE_PREFIX.length(), ref.length());
216+
217+
Schema schema = localSchemas.get(refName);
218+
219+
if (schema == null) {
220+
throw new IllegalArgumentException("Schema not found: " + refName);
221+
}
222+
223+
return generateResponseBody(schema);
224+
}
225+
181226
private String resolveContent(Object object) {
182227
if (object instanceof String) {
183228
return (String) object;
@@ -187,4 +232,13 @@ private String resolveContent(Object object) {
187232
}
188233
throw new IllegalArgumentException("Object is not a String");
189234
}
235+
236+
private static String generateResponseBody(final Schema<?> schema) {
237+
String schemaType = Optional.ofNullable(schema.getType()).orElse(OBJECT_TYPE);
238+
return switch (schemaType) {
239+
case STRING_TYPE, INTEGER_TYPE -> (String) schema.getExample();
240+
case OBJECT_TYPE -> SchemaReader.readObjectExample(schema);
241+
default -> "";
242+
};
243+
}
190244
}

mock/core/src/main/java/io/quarkiverse/openapi/generator/ParameterTypes.java renamed to moqu/core/src/main/java/io/quarkiverse/openapi/generator/ParameterType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package io.quarkiverse.openapi.generator;
22

3-
public enum ParameterTypes {
3+
public enum ParameterType {
44
PATH("path"),
55
QUERY("query"),
66
HEADER("header");
77

88
private final String value;
99

10-
ParameterTypes(String value) {
10+
ParameterType(String value) {
1111
this.value = value;
1212
}
1313

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package io.quarkiverse.openapi.generator;
2+
3+
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import io.quarkiverse.openapi.generator.marshall.ObjectMapperFactory;
5+
import io.swagger.v3.oas.models.media.Schema;
6+
7+
import java.util.HashMap;
8+
import java.util.Map;
9+
import java.util.Optional;
10+
11+
import static io.swagger.v3.parser.util.SchemaTypeUtil.OBJECT_TYPE;
12+
13+
public class SchemaReader {
14+
15+
static String EMPTY_JSON_OBJECT = "{}";
16+
17+
static String readObjectExample(Schema<?> schema) {
18+
try {
19+
Map<String, Object> map = mapObjectExample(schema);
20+
return ObjectMapperFactory.getInstance().writeValueAsString(map);
21+
} catch (JsonProcessingException e) {
22+
return EMPTY_JSON_OBJECT;
23+
}
24+
}
25+
26+
private static Map<String, Object> mapObjectExample(Schema<?> example) {
27+
Map<String, Object> currentRoot = new HashMap<>();
28+
Optional.ofNullable(example.getProperties()).orElse(Map.of())
29+
.forEach((key, schema) -> {
30+
if (schema.getType().equals(OBJECT_TYPE)) {
31+
currentRoot.put(key, mapObjectExample(schema));
32+
} else {
33+
currentRoot.put(key, schema.getExample());
34+
}
35+
});
36+
return currentRoot;
37+
}
38+
}
39+

0 commit comments

Comments
 (0)