Skip to content

Commit 66f6973

Browse files
fix(normalizer): restore behavior of clearing a oneOf if the schema content cannot currently be used by the generator (#24585)
1 parent 922f3e1 commit 66f6973

5 files changed

Lines changed: 82 additions & 15 deletions

File tree

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import static org.openapitools.codegen.CodegenConstants.*;
4444
import static org.openapitools.codegen.utils.EnumUtils.ANY_OF;
4545
import static org.openapitools.codegen.utils.EnumUtils.ONE_OF;
46+
import static org.openapitools.codegen.utils.ModelUtils.isOneOfOfConsts;
4647
import static org.openapitools.codegen.utils.ModelUtils.simplifyOneOfAnyOfWithOnlyOneNonNullSubSchema;
4748
import static org.openapitools.codegen.utils.StringUtils.getUniqueString;
4849

@@ -1742,18 +1743,24 @@ protected Schema processSimplifyOneOf(Schema schema) {
17421743
}
17431744

17441745
schema = simplifyOneOfAnyOfWithOnlyOneNonNullSubSchema(openAPI, schema, oneOfSchemas);
1745-
if (ModelUtils.isIntegerSchema(schema) || ModelUtils.isNumberSchema(schema) || ModelUtils.isStringSchema(schema)) {
1746-
if (schema.getSpecVersion().equals(SpecVersion.V30)) {
1747-
schema.setOneOf(null);
1748-
} //else {
1749-
// TODO convert oneOf const/deprecated to enum
1750-
// }
1751-
}
1746+
clearOneOf(schema);
17521747
}
17531748

17541749
return schema;
17551750
}
17561751

1752+
/**
1753+
* Removes the {@code oneOf} from the schema if it is considered to not contain information that the generator can
1754+
* currently act upon. The schema is left untouched if all the {@code oneOf} branches contain an OAS 3.1 {@code const}.
1755+
* This since that structure can potentially be used for enum interpretation.
1756+
*/
1757+
private void clearOneOf(Schema schema) {
1758+
if (ModelUtils.isIntegerSchema(schema) || ModelUtils.isNumberSchema(schema) || ModelUtils.isStringSchema(schema)) {
1759+
if (!isOneOfOfConsts(schema)) {
1760+
schema.setOneOf(null);
1761+
}
1762+
}
1763+
}
17571764

17581765
/**
17591766
* Ensure inheritance is correctly defined for OneOf and Discriminators.

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2847,6 +2847,19 @@ public static boolean containsEnums(OpenAPI openAPI) {
28472847
return schemaMap.values().stream().anyMatch(ModelUtils::isEnumSchema);
28482848
}
28492849

2850+
/**
2851+
* Whether all branches in the oneOf contains a {@code const}. Returns false for OAS 3.0 since that does not support
2852+
* {@code const}.
2853+
* @param schema The Schema
2854+
* @return true if all {@code oneOf} branches contains a {@code const}.
2855+
*/
2856+
public static boolean isOneOfOfConsts(Schema<?> schema) {
2857+
if (hasOneOf(schema) && !schema.getSpecVersion().equals(SpecVersion.V30)) {
2858+
return schema.getOneOf().stream().allMatch(oneOf -> oneOf.getConst() != null);
2859+
}
2860+
return false;
2861+
}
2862+
28502863
@FunctionalInterface
28512864
private interface OpenAPISchemaVisitor {
28522865

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

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343

4444
public class OpenAPINormalizerTest {
4545

46+
private static final String SIMPLIFY_ONE_OF_ANY_OF = "SIMPLIFY_ONEOF_ANYOF";
47+
private static final String SIMPLIFY_ONEOF_ANYOF_ENUM = "SIMPLIFY_ONEOF_ANYOF_ENUM";
4648
private static final String REF_AS_PARENT_IN_ALLOF = "REF_AS_PARENT_IN_ALLOF";
4749
private static final String X_PARENT = "x-parent";
4850
private static final String X_INTERNAL = "x-internal";
@@ -210,7 +212,7 @@ public void testSimplifyOneOfAnyOfEnum() throws Exception {
210212

211213
// Test with rule enabled (default)
212214
Map<String, String> options = new HashMap<>();
213-
options.put("SIMPLIFY_ONEOF_ANYOF_ENUM", "true");
215+
options.put(SIMPLIFY_ONEOF_ANYOF_ENUM, "true");
214216
OpenAPINormalizer normalizer = new OpenAPINormalizer(openAPI, options);
215217
normalizer.normalize();
216218

@@ -248,7 +250,7 @@ public void testSimplifyOneOfAnyOfEnum() throws Exception {
248250
// Test with rule disabled
249251
OpenAPI openAPI2 = TestUtils.parseSpec("src/test/resources/3_0/simplifyOneOfWithEnums_test.yaml");
250252
Map<String, String> options2 = new HashMap<>();
251-
options2.put("SIMPLIFY_ONEOF_ANYOF_ENUM", "false");
253+
options2.put(SIMPLIFY_ONEOF_ANYOF_ENUM, "false");
252254
OpenAPINormalizer normalizer2 = new OpenAPINormalizer(openAPI2, options2);
253255
normalizer2.normalize();
254256

@@ -312,7 +314,7 @@ public void testOpenAPINormalizerSimplifyOneOfAnyOf() {
312314
assertEquals(schema19.getAnyOf().size(), 1);
313315

314316
Map<String, String> options = new HashMap<>();
315-
options.put("SIMPLIFY_ONEOF_ANYOF", "true");
317+
options.put(SIMPLIFY_ONE_OF_ANY_OF, "true");
316318
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
317319
openAPINormalizer.normalize();
318320

@@ -370,7 +372,7 @@ public void testOpenAPINormalizerSimplifyOneOfWithSingleRef() {
370372
assertEquals(((Schema) oneOfWithSingleRef.getProperties().get("number")).getOneOf().size(), 1);
371373

372374
Map<String, String> options = new HashMap<>();
373-
options.put("SIMPLIFY_ONEOF_ANYOF", "true");
375+
options.put(SIMPLIFY_ONE_OF_ANY_OF, "true");
374376
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
375377
openAPINormalizer.normalize();
376378

@@ -511,7 +513,7 @@ public void testOpenAPINormalizerConvertEnumNullToNullable() {
511513
assertNull(schema.getNullable());
512514

513515
Map<String, String> options = new HashMap<>();
514-
options.put("SIMPLIFY_ONEOF_ANYOF", "true");
516+
options.put(SIMPLIFY_ONE_OF_ANY_OF, "true");
515517
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
516518
openAPINormalizer.normalize();
517519

@@ -1539,7 +1541,7 @@ public void testOpenAPINormalizerSimplifyOneOfAnyOf31Spec() {
15391541

15401542
// start the normalization
15411543
Map<String, String> options = new HashMap<>();
1542-
options.put("SIMPLIFY_ONEOF_ANYOF", "true");
1544+
options.put(SIMPLIFY_ONE_OF_ANY_OF, "true");
15431545
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
15441546
openAPINormalizer.normalize();
15451547

@@ -1613,6 +1615,40 @@ public void testOpenAPINormalizerSimplifyOneOfAnyOf31Spec() {
16131615
assertEquals(((Schema) schema24.getProperties().get("anyof_nullable_number")).getTypes().size(), 1);
16141616
}
16151617

1618+
@Test
1619+
public void testOneOfWithStringsWithDifferentPatternsAreCollapsedWithSimplifyOneOfAnyOf() {
1620+
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_1/simplifyOneOfAnyOf_test.yaml");
1621+
1622+
Schema stringPatternsWithOneOf = openAPI.getComponents().getSchemas().get("StringPatternsWithOneOf");
1623+
assertEquals(stringPatternsWithOneOf.getOneOf().size(), 2);
1624+
1625+
// start the normalization
1626+
Map<String, String> options = new HashMap<>();
1627+
options.put(SIMPLIFY_ONE_OF_ANY_OF, "true");
1628+
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
1629+
openAPINormalizer.normalize();
1630+
1631+
Schema normalizedStringPatternsWithOneOf = openAPI.getComponents().getSchemas().get("StringPatternsWithOneOf");
1632+
assertNull(normalizedStringPatternsWithOneOf.getOneOf());
1633+
}
1634+
1635+
@Test
1636+
public void testOneOfWithConstsIsUntouchedBySimplifyOneOfAnyOf() {
1637+
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_1/simplifyOneOfAnyOf_test.yaml");
1638+
1639+
Schema integerWithOneOfConsts = openAPI.getComponents().getSchemas().get("TypeIntegerWithOneOf");
1640+
assertEquals(integerWithOneOfConsts.getOneOf().size(), 3);
1641+
1642+
// start the normalization
1643+
Map<String, String> options = new HashMap<>();
1644+
options.put(SIMPLIFY_ONEOF_ANYOF_ENUM, "false");
1645+
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
1646+
openAPINormalizer.normalize();
1647+
1648+
Schema normalizedIntegerWithOneOfConsts = openAPI.getComponents().getSchemas().get("TypeIntegerWithOneOf");
1649+
assertEquals(normalizedIntegerWithOneOfConsts.getOneOf().size(), 3);
1650+
}
1651+
16161652
@Test
16171653
public void testOpenAPINormalizerSimplifyOneOfWithSingleRef31Spec() {
16181654
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_1/simplifyOneOfAnyOf_test.yaml");
@@ -1621,7 +1657,7 @@ public void testOpenAPINormalizerSimplifyOneOfWithSingleRef31Spec() {
16211657
assertEquals(((Schema) oneOfWithSingleRef.getProperties().get("number")).getOneOf().size(), 1);
16221658

16231659
Map<String, String> options = new HashMap<>();
1624-
options.put("SIMPLIFY_ONEOF_ANYOF", "true");
1660+
options.put(SIMPLIFY_ONE_OF_ANY_OF, "true");
16251661
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
16261662
openAPINormalizer.normalize();
16271663

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,13 @@ components:
150150
OneOfNullAndRef3:
151151
oneOf:
152152
- $ref: '#/components/schemas/Parent'
153-
- type: "null"
153+
- type: "null"
154+
StringPatternsWithOneOf:
155+
type: string
156+
oneOf:
157+
- type: string
158+
description: Numeric identifier
159+
pattern: '^\d{1,35}$'
160+
- type: string
161+
description: UUID identifier
162+
pattern: '^[0-9a-f-]{36}$'

samples/client/petstore/csharp/generichost/latest/AnnotatedEnum/api/openapi.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ components:
131131
allOf:
132132
- $ref: "#/components/schemas/Parent"
133133
nullable: true
134+
StringPatternsWithOneOf:
135+
type: string
134136
ParentWithPluralOneOfProperty_number:
135137
oneOf:
136138
- $ref: "#/components/schemas/Number"

0 commit comments

Comments
 (0)