Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use enum type for discriminator #15978

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9f35097
Fix #12412 Use enum type for discriminator
bernie-schelberg-mywave Oct 28, 2022
74093a7
Rename variable
bernie-schelberg-mywave Nov 2, 2022
d53f07f
Fix required property in test resource
bernie-schelberg-mywave Nov 7, 2022
0cf0de7
Add example of enum mapping to samples
bernie-schelberg-mywave Nov 7, 2022
2519d25
Merge branch 'master' into issue12412
bernie-schelberg-mywave Nov 25, 2022
e07aca2
Generate samples
bernie-schelberg-mywave Nov 25, 2022
c8b4a9f
Merge branch 'master' into issue12412
bernie-schelberg-mywave Feb 22, 2023
0e08a4a
Generate samples after merging master
bernie-schelberg-mywave Feb 22, 2023
d1964ab
Merge branch '7.0.x' into issue12412
bernie-schelberg-mywave Mar 6, 2023
e0f1b1c
Regenerate samples
bernie-schelberg-mywave Mar 6, 2023
7857121
Fix raw use of parameterized class
bernie-schelberg-mywave Mar 6, 2023
77cc895
Add test showing serialization and deserialization of classes with en…
bernie-schelberg-mywave Mar 7, 2023
268da29
Remove old generated files
bernie-schelberg-mywave Mar 7, 2023
135f677
Merge branch '7.0.x' into issue12412
bernie-schelberg-mywave Mar 27, 2023
0b0a69f
Merge branch 'master' into issue12412
bernie-schelberg-mywave Jun 20, 2023
bb7bbd9
Generate samples
bernie-schelberg-mywave Jun 21, 2023
e147159
Merge branch 'issue12412' of https://github.com/bernie-schelberg-mywa…
wing328 Jul 3, 2023
6e0b077
Merge remote-tracking branch 'origin/master' into bernie-schelberg-my…
wing328 Jul 3, 2023
5df2fcc
update samples
wing328 Jul 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3526,22 +3526,30 @@ protected CodegenDiscriminator createDiscriminator(String schemaName, Schema sch
return null;
}
CodegenDiscriminator discriminator = new CodegenDiscriminator();
String discPropName = sourceDiscriminator.getPropertyName();
discriminator.setPropertyName(toVarName(discPropName));
String discriminatorPropertyName = sourceDiscriminator.getPropertyName();
discriminator.setPropertyName(toVarName(discriminatorPropertyName));
discriminator.setPropertyBaseName(sourceDiscriminator.getPropertyName());
discriminator.setPropertyGetter(toGetter(discriminator.getPropertyName()));

if (sourceDiscriminator.getExtensions() != null) {
discriminator.setVendorExtensions(sourceDiscriminator.getExtensions());
}

// FIXME: for now, we assume that the discriminator property is String
discriminator.setPropertyType(typeMapping.get("string"));
// FIXME: there are other ways to define the type of the discriminator property (inline
// for example). Handling those scenarios is too complicated for me, I'm leaving it for
// the future..
String propertyType =
Optional.ofNullable(schema.getProperties())
.map(p -> (Schema<?>) p.get(discriminatorPropertyName))
.map(Schema::get$ref)
.map(ModelUtils::getSimpleRef)
.orElseGet(() -> typeMapping.get("string"));
discriminator.setPropertyType(propertyType);

// check to see if the discriminator property is an enum string
if (schema.getProperties() != null &&
schema.getProperties().get(discPropName) instanceof StringSchema) {
StringSchema s = (StringSchema) schema.getProperties().get(discPropName);
schema.getProperties().get(discriminatorPropertyName) instanceof StringSchema) {
StringSchema s = (StringSchema) schema.getProperties().get(discriminatorPropertyName);
if (s.getEnum() != null && !s.getEnum().isEmpty()) { // it's an enum string
discriminator.setIsEnum(true);
}
Expand Down Expand Up @@ -3586,7 +3594,7 @@ protected CodegenDiscriminator createDiscriminator(String schemaName, Schema sch
}
// if there are composed oneOf/anyOf schemas, add them to this discriminator
if (ModelUtils.isComposedSchema(schema) && !this.getLegacyDiscriminatorBehavior()) {
List<MappedModel> otherDescendants = getOneOfAnyOfDescendants(schemaName, discPropName, (ComposedSchema) schema, openAPI);
List<MappedModel> otherDescendants = getOneOfAnyOfDescendants(schemaName, discriminatorPropertyName, (ComposedSchema) schema, openAPI);
for (MappedModel otherDescendant : otherDescendants) {
if (!uniqueDescendants.contains(otherDescendant)) {
uniqueDescendants.add(otherDescendant);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import java.util.stream.Collectors;

import static junit.framework.Assert.assertEquals;
import static org.assertj.core.api.Assertions.assertThat;
import static org.testng.Assert.*;

public class DefaultCodegenTest {
Expand Down Expand Up @@ -1509,6 +1510,12 @@ public void testComposedSchemaOneOfDiscriminatorMap() {
hs.add(new CodegenDiscriminator.MappedModel(mn, mn));
Assert.assertEquals(cm.discriminator.getMappedModels(), hs);

// ref oneOf models with enum property discriminator
modelName = "FruitOneOfEnumMappingDisc";
sc = openAPI.getComponents().getSchemas().get(modelName);
cm = codegen.fromModel(modelName, sc);
assertThat(cm.discriminator.getPropertyType()).isEqualTo("FruitTypeEnum");

// ref oneOf models with discriminator in the grandparent schemas of those oneof models
modelName = "FruitGrandparentDisc";
sc = openAPI.getComponents().getSchemas().get(modelName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,55 @@ public void testDiscriminatorWithoutMappingIssue14731() throws IOException {
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithoutMappingBDTO.java"), "@JsonTypeName");
}

@Test
void testOneOfWithEnumDiscriminator() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');
OpenAPI openAPI = new OpenAPIParser()
.readLocation("src/test/resources/3_0/oneOfDiscriminator.yaml", null, new ParseOptions()).getOpenAPI();

SpringCodegen codegen = new SpringCodegen();
codegen.setOutputDir(output.getAbsolutePath());
codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true");
codegen.setUseOneOfInterfaces(true);

ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);

DefaultGenerator generator = new DefaultGenerator();
codegen.setHateoas(true);
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
//generator.setGeneratorPropertyDefault(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "false");

codegen.setUseOneOfInterfaces(true);
codegen.setLegacyDiscriminatorBehavior(false);

generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");

generator.opts(input).generate();

assertFileContains(
Paths.get(outputPath + "/src/main/java/org/openapitools/model/FruitOneOfEnumMappingDisc.java"),
"public FruitTypeEnum getFruitType();"
);
assertFileContains(
Paths.get(outputPath + "/src/main/java/org/openapitools/model/AppleOneOfEnumMappingDisc.java"),
"private FruitTypeEnum fruitType;",
"public FruitTypeEnum getFruitType() {"
);
assertFileContains(
Paths.get(outputPath + "/src/main/java/org/openapitools/model/BananaOneOfEnumMappingDisc.java"),
"private FruitTypeEnum fruitType;",
"public FruitTypeEnum getFruitType() {"
);
}

@Test
public void testTypeMappings() {
final SpringCodegen codegen = new SpringCodegen();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,38 @@ components:
type: integer
oneOf:
- $ref: '#/components/schemas/FruitType'
FruitTypeEnum:
type: string
enum: [APPLE, BANANA]
FruitOneOfEnumMappingDisc:
type: object
properties:
fruitType:
$ref: "#/components/schemas/FruitTypeEnum"
required:
- fruitType
oneOf:
- $ref: '#/components/schemas/AppleOneOfEnumMappingDisc'
- $ref: '#/components/schemas/BananaOneOfEnumMappingDisc'
discriminator:
propertyName: fruitType
mapping:
APPLE: '#/components/schemas/AppleOneOfEnumMappingDisc'
BANANA: '#/components/schemas/BananaOneOfEnumMappingDisc'
AppleOneOfEnumMappingDisc:
type: object
required:
- seeds
properties:
seeds:
type: integer
BananaOneOfEnumMappingDisc:
type: object
required:
- length
properties:
length:
type: integer
FruitGrandparentDisc:
oneOf:
- $ref: '#/components/schemas/AppleGrandparentDisc'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,38 @@ components:
type: string
allOf:
- $ref: '#/components/schemas/Pizza'
FruitType:
type: string
enum: [APPLE, BANANA]
Fruit:
type: object
properties:
fruitType:
$ref: "#/components/schemas/FruitType"
required:
- fruitType
oneOf:
- $ref: '#/components/schemas/Apple'
- $ref: '#/components/schemas/Banana'
discriminator:
propertyName: fruitType
mapping:
APPLE: '#/components/schemas/Apple'
BANANA: '#/components/schemas/Banana'
Apple:
type: object
required:
- seeds
properties:
seeds:
type: integer
Banana:
type: object
required:
- length
properties:
length:
type: integer

requestBodies:
Foo:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1438,16 +1438,16 @@ public async Task<ApiResponse<object>> TestBodyWithFileSchemaAsync(FileSchemaTes
/// <summary>
/// Validates the request parameters
/// </summary>
/// <param name="query"></param>
/// <param name="user"></param>
/// <param name="query"></param>
/// <returns></returns>
private void ValidateTestBodyWithQueryParams(string query, User user)
private void ValidateTestBodyWithQueryParams(User user, string query)
{
if (query == null)
throw new ArgumentNullException(nameof(query));

if (user == null)
throw new ArgumentNullException(nameof(user));

if (query == null)
throw new ArgumentNullException(nameof(query));
}

/// <summary>
Expand Down Expand Up @@ -1530,7 +1530,7 @@ public async Task<ApiResponse<object>> TestBodyWithQueryParamsAsync(User user, s

try
{
ValidateTestBodyWithQueryParams(query, user);
ValidateTestBodyWithQueryParams(user, query);

FormatTestBodyWithQueryParams(user, ref query);

Expand Down Expand Up @@ -2023,18 +2023,15 @@ public async Task<ApiResponse<object>> TestEndpointParametersAsync(byte[] varByt
/// <summary>
/// Validates the request parameters
/// </summary>
/// <param name="enumHeaderString"></param>
/// <param name="enumHeaderStringArray"></param>
/// <param name="enumQueryStringArray"></param>
/// <param name="enumFormStringArray"></param>
/// <param name="enumFormString"></param>
/// <param name="enumQueryString"></param>
/// <param name="enumHeaderString"></param>
/// <param name="enumFormString"></param>
/// <returns></returns>
private void ValidateTestEnumParameters(Option<string> enumHeaderString, Option<List<string>> enumHeaderStringArray, Option<List<string>> enumQueryStringArray, Option<List<string>> enumFormStringArray, Option<string> enumFormString, Option<string> enumQueryString)
private void ValidateTestEnumParameters(Option<List<string>> enumHeaderStringArray, Option<List<string>> enumQueryStringArray, Option<List<string>> enumFormStringArray, Option<string> enumQueryString, Option<string> enumHeaderString, Option<string> enumFormString)
{
if (enumHeaderString.IsSet && enumHeaderString.Value == null)
throw new ArgumentNullException(nameof(enumHeaderString));

if (enumHeaderStringArray.IsSet && enumHeaderStringArray.Value == null)
throw new ArgumentNullException(nameof(enumHeaderStringArray));

Expand All @@ -2044,11 +2041,14 @@ private void ValidateTestEnumParameters(Option<string> enumHeaderString, Option<
if (enumFormStringArray.IsSet && enumFormStringArray.Value == null)
throw new ArgumentNullException(nameof(enumFormStringArray));

if (enumFormString.IsSet && enumFormString.Value == null)
throw new ArgumentNullException(nameof(enumFormString));

if (enumQueryString.IsSet && enumQueryString.Value == null)
throw new ArgumentNullException(nameof(enumQueryString));

if (enumHeaderString.IsSet && enumHeaderString.Value == null)
throw new ArgumentNullException(nameof(enumHeaderString));

if (enumFormString.IsSet && enumFormString.Value == null)
throw new ArgumentNullException(nameof(enumFormString));
}

/// <summary>
Expand Down Expand Up @@ -2167,7 +2167,7 @@ public async Task<ApiResponse<object>> TestEnumParametersAsync(Option<List<strin

try
{
ValidateTestEnumParameters(enumHeaderString, enumHeaderStringArray, enumQueryStringArray, enumFormStringArray, enumFormString, enumQueryString);
ValidateTestEnumParameters(enumHeaderStringArray, enumQueryStringArray, enumFormStringArray, enumQueryString, enumHeaderString, enumFormString);

FormatTestEnumParameters(enumHeaderStringArray, enumQueryStringArray, ref enumQueryDouble, ref enumQueryInteger, enumFormStringArray, ref enumHeaderString, ref enumQueryString, ref enumFormString);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2023,30 +2023,30 @@ public async Task<ApiResponse<object>> TestEndpointParametersAsync(byte[] varByt
/// </summary>
/// <param name="enumQueryStringArray"></param>
/// <param name="enumFormStringArray"></param>
/// <param name="enumHeaderString"></param>
/// <param name="enumQueryString"></param>
/// <param name="enumHeaderStringArray"></param>
/// <param name="enumFormString"></param>
/// <param name="enumQueryString"></param>
/// <param name="enumHeaderString"></param>
/// <returns></returns>
private void ValidateTestEnumParameters(Option<List<string>> enumQueryStringArray, Option<List<string>> enumFormStringArray, Option<string> enumHeaderString, Option<List<string>> enumHeaderStringArray, Option<string> enumFormString, Option<string> enumQueryString)
private void ValidateTestEnumParameters(Option<List<string>> enumQueryStringArray, Option<List<string>> enumFormStringArray, Option<string> enumQueryString, Option<List<string>> enumHeaderStringArray, Option<string> enumFormString, Option<string> enumHeaderString)
{
if (enumQueryStringArray.IsSet && enumQueryStringArray.Value == null)
throw new ArgumentNullException(nameof(enumQueryStringArray));

if (enumFormStringArray.IsSet && enumFormStringArray.Value == null)
throw new ArgumentNullException(nameof(enumFormStringArray));

if (enumHeaderString.IsSet && enumHeaderString.Value == null)
throw new ArgumentNullException(nameof(enumHeaderString));
if (enumQueryString.IsSet && enumQueryString.Value == null)
throw new ArgumentNullException(nameof(enumQueryString));

if (enumHeaderStringArray.IsSet && enumHeaderStringArray.Value == null)
throw new ArgumentNullException(nameof(enumHeaderStringArray));

if (enumFormString.IsSet && enumFormString.Value == null)
throw new ArgumentNullException(nameof(enumFormString));

if (enumQueryString.IsSet && enumQueryString.Value == null)
throw new ArgumentNullException(nameof(enumQueryString));
if (enumHeaderString.IsSet && enumHeaderString.Value == null)
throw new ArgumentNullException(nameof(enumHeaderString));
}

/// <summary>
Expand Down Expand Up @@ -2165,7 +2165,7 @@ public async Task<ApiResponse<object>> TestEnumParametersAsync(Option<List<strin

try
{
ValidateTestEnumParameters(enumQueryStringArray, enumFormStringArray, enumHeaderString, enumHeaderStringArray, enumFormString, enumQueryString);
ValidateTestEnumParameters(enumQueryStringArray, enumFormStringArray, enumQueryString, enumHeaderStringArray, enumFormString, enumHeaderString);

FormatTestEnumParameters(enumHeaderStringArray, enumQueryStringArray, ref enumQueryDouble, ref enumQueryInteger, enumFormStringArray, ref enumHeaderString, ref enumQueryString, ref enumFormString);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2016,30 +2016,30 @@ public async Task<ApiResponse<object>> TestEndpointParametersAsync(byte[] varByt
/// </summary>
/// <param name="enumQueryStringArray"></param>
/// <param name="enumFormStringArray"></param>
/// <param name="enumHeaderString"></param>
/// <param name="enumQueryString"></param>
/// <param name="enumHeaderStringArray"></param>
/// <param name="enumFormString"></param>
/// <param name="enumQueryString"></param>
/// <param name="enumHeaderString"></param>
/// <returns></returns>
private void ValidateTestEnumParameters(Option<List<string>> enumQueryStringArray, Option<List<string>> enumFormStringArray, Option<string> enumHeaderString, Option<List<string>> enumHeaderStringArray, Option<string> enumFormString, Option<string> enumQueryString)
private void ValidateTestEnumParameters(Option<List<string>> enumQueryStringArray, Option<List<string>> enumFormStringArray, Option<string> enumQueryString, Option<List<string>> enumHeaderStringArray, Option<string> enumFormString, Option<string> enumHeaderString)
{
if (enumQueryStringArray.IsSet && enumQueryStringArray.Value == null)
throw new ArgumentNullException(nameof(enumQueryStringArray));

if (enumFormStringArray.IsSet && enumFormStringArray.Value == null)
throw new ArgumentNullException(nameof(enumFormStringArray));

if (enumHeaderString.IsSet && enumHeaderString.Value == null)
throw new ArgumentNullException(nameof(enumHeaderString));
if (enumQueryString.IsSet && enumQueryString.Value == null)
throw new ArgumentNullException(nameof(enumQueryString));

if (enumHeaderStringArray.IsSet && enumHeaderStringArray.Value == null)
throw new ArgumentNullException(nameof(enumHeaderStringArray));

if (enumFormString.IsSet && enumFormString.Value == null)
throw new ArgumentNullException(nameof(enumFormString));

if (enumQueryString.IsSet && enumQueryString.Value == null)
throw new ArgumentNullException(nameof(enumQueryString));
if (enumHeaderString.IsSet && enumHeaderString.Value == null)
throw new ArgumentNullException(nameof(enumHeaderString));
}

/// <summary>
Expand Down Expand Up @@ -2158,7 +2158,7 @@ public async Task<ApiResponse<object>> TestEnumParametersAsync(Option<List<strin

try
{
ValidateTestEnumParameters(enumQueryStringArray, enumFormStringArray, enumHeaderString, enumHeaderStringArray, enumFormString, enumQueryString);
ValidateTestEnumParameters(enumQueryStringArray, enumFormStringArray, enumQueryString, enumHeaderStringArray, enumFormString, enumHeaderString);

FormatTestEnumParameters(enumHeaderStringArray, enumQueryStringArray, ref enumQueryDouble, ref enumQueryInteger, enumFormStringArray, ref enumHeaderString, ref enumQueryString, ref enumFormString);

Expand Down
Loading