Skip to content

Commit 0d41fbc

Browse files
Support discriminator mappings for polymorphism
1 parent 0b8a6d6 commit 0d41fbc

File tree

5 files changed

+302
-1
lines changed

5 files changed

+302
-1
lines changed

client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{@org.openapitools.codegen.CodegenModel m}
12
{#if withXml}
23
{#else}
34
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -20,6 +21,14 @@ import com.fasterxml.jackson.annotation.JsonProperty;
2021
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
2122
{/if}
2223
{#include additionalModelTypeAnnotations.qute m=m/}
24+
{#if m.discriminator && m.discriminator.mappedModels && !m.discriminator.mappedModels.empty}
25+
@com.fasterxml.jackson.annotation.JsonTypeInfo(use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME, include = com.fasterxml.jackson.annotation.JsonTypeInfo.As.EXISTING_PROPERTY, property = "{m.discriminator.propertyBaseName}")
26+
@com.fasterxml.jackson.annotation.JsonSubTypes({
27+
{#for child in m.discriminator.mappedModels}
28+
@com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = {child.model.classname}.class, name = "{child.mappingName}"),
29+
{/for}
30+
})
31+
{/if}
2332
public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if m.serializableModel} implements java.io.Serializable{/if} {
2433

2534
{#for v in m.vars}
@@ -151,4 +160,4 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if m.serializa
151160
}
152161

153162
{#include pojoQueryParam.qute m=m.model withXml=withXml codegen=classes-codegen package=modelPackage/}
154-
}
163+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<parent>
5+
<artifactId>quarkus-openapi-generator-integration-tests</artifactId>
6+
<groupId>io.quarkiverse.openapi.generator</groupId>
7+
<version>3.0.0-SNAPSHOT</version>
8+
</parent>
9+
<modelVersion>4.0.0</modelVersion>
10+
11+
<artifactId>quarkus-openapi-generator-it-polymorphism</artifactId>
12+
<name>Quarkus - Openapi Generator - Integration Tests - Polymorphism</name>
13+
14+
<dependencies>
15+
<dependency>
16+
<groupId>io.quarkiverse.openapi.generator</groupId>
17+
<artifactId>quarkus-openapi-generator</artifactId>
18+
</dependency>
19+
<dependency>
20+
<groupId>io.quarkus</groupId>
21+
<artifactId>quarkus-junit5</artifactId>
22+
<scope>test</scope>
23+
</dependency>
24+
<dependency>
25+
<groupId>com.github.tomakehurst</groupId>
26+
<artifactId>wiremock-jre8</artifactId>
27+
<scope>test</scope>
28+
</dependency>
29+
<dependency>
30+
<groupId>org.assertj</groupId>
31+
<artifactId>assertj-core</artifactId>
32+
<scope>test</scope>
33+
</dependency>
34+
</dependencies>
35+
<build>
36+
<plugins>
37+
<plugin>
38+
<groupId>io.quarkus</groupId>
39+
<artifactId>quarkus-maven-plugin</artifactId>
40+
<extensions>true</extensions>
41+
<executions>
42+
<execution>
43+
<goals>
44+
<goal>build</goal>
45+
<goal>generate-code</goal>
46+
<goal>generate-code-tests</goal>
47+
</goals>
48+
</execution>
49+
</executions>
50+
</plugin>
51+
</plugins>
52+
</build>
53+
<profiles>
54+
<profile>
55+
<id>native-image</id>
56+
<activation>
57+
<property>
58+
<name>native</name>
59+
</property>
60+
</activation>
61+
<build>
62+
<plugins>
63+
<plugin>
64+
<artifactId>maven-surefire-plugin</artifactId>
65+
<configuration>
66+
<skipTests>${native.surefire.skip}</skipTests>
67+
</configuration>
68+
</plugin>
69+
<plugin>
70+
<artifactId>maven-failsafe-plugin</artifactId>
71+
<executions>
72+
<execution>
73+
<goals>
74+
<goal>integration-test</goal>
75+
<goal>verify</goal>
76+
</goals>
77+
<configuration>
78+
<systemPropertyVariables>
79+
<native.image.path>
80+
${project.build.directory}/${project.build.finalName}-runner
81+
</native.image.path>
82+
<java.util.logging.manager>org.jboss.logmanager.LogManager
83+
</java.util.logging.manager>
84+
<maven.home>${maven.home}</maven.home>
85+
</systemPropertyVariables>
86+
</configuration>
87+
</execution>
88+
</executions>
89+
</plugin>
90+
</plugins>
91+
</build>
92+
<properties>
93+
<quarkus.package.type>native</quarkus.package.type>
94+
</properties>
95+
</profile>
96+
</profiles>
97+
</project>
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
{
2+
"openapi": "3.0.3",
3+
"info": {
4+
"title": "tuto API",
5+
"version": "1.0.0-SNAPSHOT"
6+
},
7+
"servers": [
8+
{
9+
"url": "http://localhost:8080",
10+
"description": "Auto generated value"
11+
},
12+
{
13+
"url": "http://0.0.0.0:8080",
14+
"description": "Auto generated value"
15+
}
16+
],
17+
"paths": {
18+
"/": {
19+
"get": {
20+
"tags": [
21+
"Default"
22+
],
23+
"operationId": "get",
24+
"responses": {
25+
"200": {
26+
"description": "OK",
27+
"content": {
28+
"application/json": {
29+
"schema": {
30+
"$ref": "#/components/schemas/Data"
31+
}
32+
}
33+
}
34+
}
35+
}
36+
}
37+
}
38+
},
39+
"components": {
40+
"schemas": {
41+
"Data": {
42+
"required": [
43+
"things"
44+
],
45+
"type": "object",
46+
"properties": {
47+
"things": {
48+
"type": "array",
49+
"items": {
50+
"$ref": "#/components/schemas/Thing"
51+
},
52+
"anyOf": [
53+
{
54+
"$ref": "#/components/schemas/SomeThing"
55+
},
56+
{
57+
"$ref": "#/components/schemas/OtherThing"
58+
}
59+
]
60+
}
61+
}
62+
},
63+
"OtherThing": {
64+
"description": "Other thing",
65+
"required": [
66+
"other"
67+
],
68+
"type": "object",
69+
"allOf": [
70+
{
71+
"$ref": "#/components/schemas/Thing"
72+
}
73+
],
74+
"properties": {
75+
"other": {
76+
"type": "string"
77+
}
78+
}
79+
},
80+
"SomeThing": {
81+
"description": "Some thing",
82+
"required": [
83+
"some"
84+
],
85+
"type": "object",
86+
"allOf": [
87+
{
88+
"$ref": "#/components/schemas/Thing"
89+
}
90+
],
91+
"properties": {
92+
"some": {
93+
"type": "string"
94+
}
95+
}
96+
},
97+
"Thing": {
98+
"description": "Thing",
99+
"required": [
100+
"thing"
101+
],
102+
"type": "object",
103+
"properties": {
104+
"thing": {
105+
"type": "string"
106+
}
107+
},
108+
"discriminator": {
109+
"propertyName": "@type",
110+
"mapping": {
111+
"SomeThing": "#/components/schemas/SomeThing",
112+
"OtherThing": "#/components/schemas/OtherThing"
113+
}
114+
}
115+
}
116+
}
117+
}
118+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package io.quarkiverse.openapi.generator.it;
2+
3+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
4+
import static com.github.tomakehurst.wiremock.client.WireMock.get;
5+
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
6+
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
7+
8+
import java.util.Collections;
9+
import java.util.Map;
10+
11+
import jakarta.inject.Inject;
12+
13+
import org.eclipse.microprofile.rest.client.inject.RestClient;
14+
import org.junit.jupiter.api.Test;
15+
16+
import com.github.tomakehurst.wiremock.WireMockServer;
17+
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
18+
import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer;
19+
20+
import io.quarkus.test.common.QuarkusTestResource;
21+
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
22+
import io.quarkus.test.junit.QuarkusTest;
23+
24+
@QuarkusTest
25+
@QuarkusTestResource(PolymorphismTest.MockServer.class)
26+
class PolymorphismTest {
27+
28+
@RestClient
29+
@Inject
30+
org.openapi.quarkus.polymorphism_json.api.DefaultApi api;
31+
32+
@Test
33+
void apiIsBeingGenerated() {
34+
35+
org.openapi.quarkus.polymorphism_json.model.Data data = api.get();
36+
37+
data.getThings()
38+
.forEach(it -> assertInstanceOf(org.openapi.quarkus.polymorphism_json.model.Thing.class, it));
39+
assertInstanceOf(org.openapi.quarkus.polymorphism_json.model.SomeThing.class, data.getThings().get(0));
40+
assertInstanceOf(org.openapi.quarkus.polymorphism_json.model.OtherThing.class, data.getThings().get(1));
41+
}
42+
43+
public static class MockServer implements QuarkusTestResourceLifecycleManager {
44+
45+
private WireMockServer wireMockServer;
46+
47+
@Override
48+
public Map<String, String> start() {
49+
configureWiremockServer();
50+
return Collections.singletonMap("org.openapi.quarkus.polymorphism_json.api.DefaultApi/mp-rest/url",
51+
wireMockServer.baseUrl());
52+
}
53+
54+
private void configureWiremockServer() {
55+
var wireMockConfiguration = WireMockConfiguration.wireMockConfig()
56+
.extensions(new ResponseTemplateTransformer(false)).dynamicPort();
57+
wireMockServer = new WireMockServer(wireMockConfiguration);
58+
wireMockServer.start();
59+
60+
wireMockServer.stubFor(get(urlEqualTo("/"))
61+
.willReturn(aResponse()
62+
.withStatus(200)
63+
.withHeader("Content-Type", "application/json")
64+
.withBody(
65+
"{\"things\":[{\"@type\":\"SomeThing\",\"thing\":\"thing\",\"some\":\"some\"},{\"@type\":\"OtherThing\",\"thing\":\"thing\",\"other\":\"other\"}]}")
66+
.withTransformers("response-template")));
67+
}
68+
69+
@Override
70+
public void stop() {
71+
if (wireMockServer != null) {
72+
wireMockServer.stop();
73+
}
74+
}
75+
}
76+
}

client/integration-tests/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
<module>mutiny-return-response</module>
3232
<module>open-api-normalizer</module>
3333
<module>part-filename</module>
34+
<module>polymorphism</module>
3435
<module>return-response</module>
3536
<module>security</module>
3637
<module>simple</module>

0 commit comments

Comments
 (0)