Skip to content

Commit f099ee7

Browse files
Add handling for sibling enum discriminators
1 parent 2bbd428 commit f099ee7

25 files changed

Lines changed: 824 additions & 49 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3301,7 +3301,7 @@ private CodegenProperty discriminatorFound(String composedSchemaName, Schema sc,
33013301
}
33023302

33033303
if (refSchema.getProperties() != null && refSchema.getProperties().get(discPropName) != null) {
3304-
Schema discSchema = ModelUtils.getReferencedSchema(openAPI, (Schema) refSchema.getProperties().get(discPropName));
3304+
Schema discSchema = ModelUtils.getReferencedSchema(openAPI, getDiscriminatorSchema(refSchema, discPropName));
33053305
CodegenProperty cp = new CodegenProperty();
33063306
if (ModelUtils.isStringSchema(discSchema)) {
33073307
cp.isString = true;
@@ -3632,14 +3632,7 @@ protected CodegenDiscriminator createDiscriminator(String schemaName, Schema sch
36323632
// FIXME: there are other ways to define the type of the discriminator property (inline
36333633
// for example). Handling those scenarios is too complicated for me, I'm leaving it for
36343634
// the future..
3635-
String propertyType =
3636-
Optional.ofNullable(schema.getProperties())
3637-
.map(p -> (Schema<?>) p.get(discriminatorPropertyName))
3638-
.map(Schema::get$ref)
3639-
.map(ModelUtils::getSimpleRef)
3640-
.map(this::toModelName)
3641-
.orElseGet(() -> typeMapping.get("string"));
3642-
discriminator.setPropertyType(propertyType);
3635+
discriminator.setPropertyType(getDiscriminatorPropertyType(schema, discriminatorPropertyName));
36433636

36443637
// check to see if the discriminator property is an enum string
36453638
boolean isEnum = Optional
@@ -3703,6 +3696,39 @@ protected CodegenDiscriminator createDiscriminator(String schemaName, Schema sch
37033696
return discriminator;
37043697
}
37053698

3699+
/**
3700+
* Get the Schema for the discriminator type. Requires special handling due to siblings from OAS 3.1.
3701+
* An example of a sibling is an enum-ref that has its own description. This will lead to the enum being
3702+
* referenced as an allOf that in turn has a ref, rather than a regular ref directly to the enum.
3703+
*
3704+
* @param schema The input OAS schema.
3705+
* @param discriminatorName The name of the discriminator property.
3706+
*/
3707+
protected Schema getDiscriminatorSchema(Schema schema, String discriminatorName) {
3708+
if (schema.getProperties() == null) {
3709+
return null;
3710+
}
3711+
Schema discSchema = (Schema) schema.getProperties().get(discriminatorName);
3712+
if (ModelUtils.isAllOf(discSchema)) {
3713+
discSchema = (Schema) discSchema.getAllOf().get(0);
3714+
}
3715+
return discSchema;
3716+
}
3717+
3718+
/**
3719+
* Get the property type for the discriminator
3720+
*
3721+
* @param schema The input OAS schema.
3722+
* @param discriminatorPropertyName The name of the discriminator property.
3723+
*/
3724+
protected String getDiscriminatorPropertyType(Schema schema, String discriminatorPropertyName) {
3725+
return Optional.ofNullable(getDiscriminatorSchema(schema, discriminatorPropertyName))
3726+
.map(Schema::get$ref)
3727+
.map(ModelUtils::getSimpleRef)
3728+
.map(this::toModelName)
3729+
.orElseGet(() -> typeMapping.get("string"));
3730+
}
3731+
37063732
/**
37073733
* Handle the model for the 'additionalProperties' keyword in the OAS schema.
37083734
*

modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,40 @@ public void testDiscriminatorWithCustomMapping() {
11311131
assertTrue(personModel.getHasDiscriminatorWithNonEmptyMapping());
11321132
}
11331133

1134+
@Test
1135+
public void testEnumDiscriminatorWithDescriptionOverridden3_0() {
1136+
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/oneof_polymorphism_and_inheritance.yaml");
1137+
new OpenAPINormalizer(openAPI, Map.of()).normalize();
1138+
DefaultCodegen codegen = new DefaultCodegen();
1139+
codegen.setUseOneOfInterfaces(true);
1140+
1141+
Schema fruit2 = openAPI.getComponents().getSchemas().get("Fruit2");
1142+
codegen.setOpenAPI(openAPI);
1143+
CodegenModel fruitModel = codegen.fromModel("Fruit2", fruit2);
1144+
assertTrue(fruitModel.getHasDiscriminatorWithNonEmptyMapping());
1145+
assertTrue(fruitModel.discriminator.getIsEnum());
1146+
assertEquals("FruitType", fruitModel.discriminator.getPropertyType());
1147+
assertNull(fruitModel.getVars().get(0).description);
1148+
assertTrue(fruitModel.getVars().get(0).isEnumRef);
1149+
}
1150+
1151+
@Test
1152+
public void testEnumDiscriminatorWithDescriptionOverridden3_1() {
1153+
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_1/oneof_polymorphism_and_inheritance.yaml");
1154+
new OpenAPINormalizer(openAPI, Map.of()).normalize();
1155+
DefaultCodegen codegen = new DefaultCodegen();
1156+
codegen.setUseOneOfInterfaces(true);
1157+
1158+
Schema fruit2 = openAPI.getComponents().getSchemas().get("Fruit2");
1159+
codegen.setOpenAPI(openAPI);
1160+
CodegenModel fruitModel = codegen.fromModel("Fruit2", fruit2);
1161+
assertTrue(fruitModel.getHasDiscriminatorWithNonEmptyMapping());
1162+
assertTrue(fruitModel.discriminator.getIsEnum());
1163+
assertEquals("FruitType", fruitModel.discriminator.getPropertyType());
1164+
assertEquals("test", fruitModel.getVars().get(0).description);
1165+
assertTrue(fruitModel.getVars().get(0).isEnumRef);
1166+
}
1167+
11341168
@Test
11351169
public void testParentName() {
11361170
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/allOf.yaml");

modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4063,4 +4063,22 @@ public void testOneOfInterfaceWithAnnotation() {
40634063
.isInterface()
40644064
.assertTypeAnnotations().containsWithName("SuppressWarnings");
40654065
}
4066+
4067+
@Test
4068+
public void testOneOfInterfaceWithEnumDiscriminatorHavingCustomDescription3_0() {
4069+
final Map<String, File> files = generateFromContract("src/test/resources/3_0/oneof_polymorphism_and_inheritance.yaml", WEBCLIENT,
4070+
Map.of(USE_ONE_OF_INTERFACES, "true"));
4071+
JavaFileAssert.assertThat(files.get("Fruit2.java"))
4072+
.isInterface()
4073+
.fileContainsPattern("public FruitType getFruitType()");
4074+
}
4075+
4076+
@Test
4077+
public void testOneOfInterfaceWithEnumDiscriminatorHavingCustomDescription3_1() {
4078+
final Map<String, File> files = generateFromContract("src/test/resources/3_1/oneof_polymorphism_and_inheritance.yaml", WEBCLIENT,
4079+
Map.of(USE_ONE_OF_INTERFACES, "true"));
4080+
JavaFileAssert.assertThat(files.get("Fruit2.java"))
4081+
.isInterface()
4082+
.fileContainsPattern("public FruitType getFruitType()");
4083+
}
40664084
}

modules/openapi-generator/src/test/resources/3_0/oneof_polymorphism_and_inheritance.yaml

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ paths:
4848
'application/json':
4949
schema:
5050
$ref: '#/components/schemas/Bar'
51+
5152
components:
5253
schemas:
5354
Addressable:
@@ -184,6 +185,8 @@ components:
184185
properties:
185186
fruitType:
186187
$ref: "#/components/schemas/FruitType"
188+
required:
189+
- fruitType
187190
oneOf:
188191
- $ref: '#/components/schemas/Apple'
189192
- $ref: '#/components/schemas/Banana'
@@ -192,8 +195,6 @@ components:
192195
mapping:
193196
APPLE: '#/components/schemas/Apple'
194197
BANANA: '#/components/schemas/Banana'
195-
required:
196-
- fruitType
197198
Apple:
198199
type: object
199200
required:
@@ -208,6 +209,44 @@ components:
208209
properties:
209210
length:
210211
type: integer
212+
Fruit2:
213+
type: object
214+
properties:
215+
fruitType:
216+
$ref: "#/components/schemas/FruitType"
217+
description: "test"
218+
required:
219+
- fruitType
220+
oneOf:
221+
- $ref: '#/components/schemas/Apple2'
222+
- $ref: '#/components/schemas/Banana2'
223+
discriminator:
224+
propertyName: fruitType
225+
mapping:
226+
APPLE: '#/components/schemas/Apple2'
227+
BANANA: '#/components/schemas/Banana2'
228+
Apple2:
229+
type: object
230+
required:
231+
- seeds
232+
- fruitType
233+
properties:
234+
seeds:
235+
type: integer
236+
fruitType:
237+
$ref: "#/components/schemas/FruitType"
238+
description: "test"
239+
Banana2:
240+
type: object
241+
required:
242+
- length
243+
- fruitType
244+
properties:
245+
length:
246+
type: integer
247+
fruitType:
248+
$ref: "#/components/schemas/FruitType"
249+
description: "test"
211250
Animal:
212251
oneOf:
213252
- $ref: '#/components/schemas/Dog'

modules/openapi-generator/src/test/resources/3_1/oneof_polymorphism_and_inheritance.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,44 @@ components:
209209
properties:
210210
length:
211211
type: integer
212+
Fruit2:
213+
type: object
214+
properties:
215+
fruitType:
216+
$ref: "#/components/schemas/FruitType"
217+
description: "test"
218+
required:
219+
- fruitType
220+
oneOf:
221+
- $ref: '#/components/schemas/Apple2'
222+
- $ref: '#/components/schemas/Banana2'
223+
discriminator:
224+
propertyName: fruitType
225+
mapping:
226+
APPLE: '#/components/schemas/Apple2'
227+
BANANA: '#/components/schemas/Banana2'
228+
Apple2:
229+
type: object
230+
required:
231+
- seeds
232+
- fruitType
233+
properties:
234+
seeds:
235+
type: integer
236+
fruitType:
237+
$ref: "#/components/schemas/FruitType"
238+
description: "test"
239+
Banana2:
240+
type: object
241+
required:
242+
- length
243+
- fruitType
244+
properties:
245+
length:
246+
type: integer
247+
fruitType:
248+
$ref: "#/components/schemas/FruitType"
249+
description: "test"
212250
Animal:
213251
oneOf:
214252
- $ref: '#/components/schemas/Dog'

samples/client/others/java/webclient-sealedInterface/.openapi-generator/FILES

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ build.sbt
88
docs/Addressable.md
99
docs/Animal.md
1010
docs/Apple.md
11+
docs/Apple2.md
1112
docs/Banana.md
13+
docs/Banana2.md
1214
docs/Bar.md
1315
docs/BarApi.md
1416
docs/BarCreate.md
@@ -24,6 +26,7 @@ docs/FooApi.md
2426
docs/FooRef.md
2527
docs/FooRefOrValue.md
2628
docs/Fruit.md
29+
docs/Fruit2.md
2730
docs/FruitType.md
2831
docs/Pasta.md
2932
docs/Pizza.md
@@ -54,7 +57,9 @@ src/main/java/org/openapitools/client/auth/HttpBearerAuth.java
5457
src/main/java/org/openapitools/client/model/Addressable.java
5558
src/main/java/org/openapitools/client/model/Animal.java
5659
src/main/java/org/openapitools/client/model/Apple.java
60+
src/main/java/org/openapitools/client/model/Apple2.java
5761
src/main/java/org/openapitools/client/model/Banana.java
62+
src/main/java/org/openapitools/client/model/Banana2.java
5863
src/main/java/org/openapitools/client/model/Bar.java
5964
src/main/java/org/openapitools/client/model/BarCreate.java
6065
src/main/java/org/openapitools/client/model/BarRef.java
@@ -68,6 +73,7 @@ src/main/java/org/openapitools/client/model/Foo.java
6873
src/main/java/org/openapitools/client/model/FooRef.java
6974
src/main/java/org/openapitools/client/model/FooRefOrValue.java
7075
src/main/java/org/openapitools/client/model/Fruit.java
76+
src/main/java/org/openapitools/client/model/Fruit2.java
7177
src/main/java/org/openapitools/client/model/FruitType.java
7278
src/main/java/org/openapitools/client/model/Pasta.java
7379
src/main/java/org/openapitools/client/model/Pizza.java

samples/client/others/java/webclient-sealedInterface/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ Class | Method | HTTP request | Description
126126
- [Addressable](docs/Addressable.md)
127127
- [Animal](docs/Animal.md)
128128
- [Apple](docs/Apple.md)
129+
- [Apple2](docs/Apple2.md)
129130
- [Banana](docs/Banana.md)
131+
- [Banana2](docs/Banana2.md)
130132
- [Bar](docs/Bar.md)
131133
- [BarCreate](docs/BarCreate.md)
132134
- [BarRef](docs/BarRef.md)
@@ -140,6 +142,7 @@ Class | Method | HTTP request | Description
140142
- [FooRef](docs/FooRef.md)
141143
- [FooRefOrValue](docs/FooRefOrValue.md)
142144
- [Fruit](docs/Fruit.md)
145+
- [Fruit2](docs/Fruit2.md)
143146
- [FruitType](docs/FruitType.md)
144147
- [Pasta](docs/Pasta.md)
145148
- [Pizza](docs/Pizza.md)

samples/client/others/java/webclient-sealedInterface/api/openapi.yaml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,42 @@ components:
302302
required:
303303
- length
304304
type: object
305+
Fruit2:
306+
discriminator:
307+
mapping:
308+
APPLE: "#/components/schemas/Apple2"
309+
BANANA: "#/components/schemas/Banana2"
310+
propertyName: fruitType
311+
oneOf:
312+
- $ref: "#/components/schemas/Apple2"
313+
- $ref: "#/components/schemas/Banana2"
314+
properties:
315+
fruitType:
316+
$ref: "#/components/schemas/FruitType"
317+
required:
318+
- fruitType
319+
type: object
320+
x-one-of-name: Fruit2
321+
Apple2:
322+
properties:
323+
seeds:
324+
type: integer
325+
fruitType:
326+
$ref: "#/components/schemas/FruitType"
327+
required:
328+
- fruitType
329+
- seeds
330+
type: object
331+
Banana2:
332+
properties:
333+
length:
334+
type: integer
335+
fruitType:
336+
$ref: "#/components/schemas/FruitType"
337+
required:
338+
- fruitType
339+
- length
340+
type: object
305341
Animal:
306342
oneOf:
307343
- $ref: "#/components/schemas/Dog"

samples/client/others/java/webclient-sealedInterface/docs/Apple2.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
| Name | Type | Description | Notes |
99
|------------ | ------------- | ------------- | -------------|
1010
|**seeds** | **Integer** | | |
11-
|**type** | **FruitType** | | |
11+
|**fruitType** | **FruitType** | | |
1212

1313

1414
## Implemented Interfaces

samples/client/others/java/webclient-sealedInterface/docs/Banana2.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
| Name | Type | Description | Notes |
99
|------------ | ------------- | ------------- | -------------|
1010
|**length** | **Integer** | | |
11-
|**type** | **FruitType** | | |
11+
|**fruitType** | **FruitType** | | |
1212

1313

1414
## Implemented Interfaces

0 commit comments

Comments
 (0)