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

Fix generator for discriminator with custom type. #1675

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.atteo.evo.inflector.English;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenDiscriminator;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenParameter;
Expand Down Expand Up @@ -81,6 +82,7 @@
import static org.openapitools.codegen.CodegenConstants.MODEL_PACKAGE;
import static org.openapitools.codegen.CodegenConstants.PACKAGE_NAME;
import static org.openapitools.codegen.languages.KotlinClientCodegen.DATE_LIBRARY;
import static org.openapitools.codegen.utils.OnceLogger.once;
import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;

Expand Down Expand Up @@ -682,6 +684,45 @@ public void setVisitable(boolean visitable) {
this.visitable = visitable;
}

@Override
protected CodegenDiscriminator createDiscriminator(String schemaName, Schema schema) {

var discriminator = super.createDiscriminator(schemaName, schema);
if (discriminator == null) {
return null;
}

for (var entry : discriminator.getMapping().entrySet()) {
String name;
if (entry.getValue().indexOf('/') < 0) {
continue;
}
name = ModelUtils.getSimpleRef(entry.getValue());
var referencedSchema = ModelUtils.getSchema(openAPI, name);
if (referencedSchema == null) {
once(log).error("Failed to lookup the schema '{}' when processing the discriminator mapping of oneOf/anyOf. Please check to ensure it's defined properly.", name);
continue;
}
if (referencedSchema.getProperties() == null || referencedSchema.getProperties().isEmpty()) {
continue;
}
boolean isDiscriminatorPropTypeFound = false;
var props = (Map<String, Schema>) referencedSchema.getProperties();
for (var propEntry : props.entrySet()) {
if (!propEntry.getKey().equals(discriminator.getPropertyName())) {
continue;
}
discriminator.setPropertyType(getTypeDeclaration(propEntry.getValue()));
isDiscriminatorPropTypeFound = true;
break;
}
if (isDiscriminatorPropTypeFound) {
break;
}
}
return discriminator;
}

@Override
public String toApiVarName(String name) {
String apiVarName = super.toApiVarName(name);
Expand Down Expand Up @@ -1297,8 +1338,6 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
processParentModel(model, requiredVarsWithoutDiscriminator, requiredParentVarsWithoutDiscriminator, allVars, false);
model.allVars = allVars;

processOneOfModels(model, objs.values());

var withInheritance = model.hasChildren || model.parent != null;
model.vendorExtensions.put("withInheritance", withInheritance);

Expand Down Expand Up @@ -1344,6 +1383,11 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
addStrValueToEnum(model);
}

for (ModelsMap models : objs.values()) {
CodegenModel model = models.getModels().get(0).getModel();
processOneOfModels(model, objs.values());
}

return objs;
}

Expand Down Expand Up @@ -1377,10 +1421,31 @@ private void processOneOfModels(CodegenModel model, Collection<ModelsMap> models
if (prop.name.equals(discriminator.getPropertyName())) {
prop.isDiscriminator = true;
prop.isOverridden = true;
prop.isNullable = false;
prop.isOptional = false;
prop.required = true;
prop.isReadOnly = false;
prop.vendorExtensions.put("typeWithEnumWithGenericAnnotations", discriminator.getPropertyType());
prop.vendorExtensions.put("overridden", true);
break;
}
}
var properties = (ArrayList<CodegenProperty>) m.vendorExtensions.get("requiredVarsWithoutDiscriminator");
if (properties != null && !properties.isEmpty()) {
for (var prop : properties) {
if (prop.name.equals(discriminator.getPropertyName())) {
prop.isDiscriminator = true;
prop.isOverridden = true;
prop.isNullable = false;
prop.isOptional = false;
prop.required = true;
prop.isReadOnly = false;
prop.vendorExtensions.put("typeWithEnumWithGenericAnnotations", discriminator.getPropertyType());
prop.vendorExtensions.put("overridden", true);
break;
}
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ public interface {{classname}}{{#vendorExtensions.x-implements}}{{#-first}} exte
{{/formatNoEmptyLines}}

{{#discriminator}}
public {{propertyType}} {{propertyGetter}}();
{{propertyType}} {{propertyGetter}}();
{{/discriminator}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ void testOneOf() {
String outputPath = generateFiles(codegen, "src/test/resources/3_0/oneof-with-discriminator.yml", CodegenConstants.APIS, CodegenConstants.MODELS);
String path = outputPath + "src/main/java/org/openapitools/";

assertFileContains(path + "model/Subject.java", "public String getTypeCode();");
assertFileContains(path + "model/Subject.java", "String getTypeCode();");
assertFileContains(path + "model/Person.java", "public String getTypeCode() {");
}

Expand All @@ -504,4 +504,19 @@ void testOneOfWithoutDiscriminator() {
"@JsonTypeInfo"
);
}

@Test
void testDiscriminatorCustomType() {

var codegen = new JavaMicronautClientCodegen();
String outputPath = generateFiles(codegen, "src/test/resources/3_0/oneof-with-discriminator2.yml", CodegenConstants.APIS, CodegenConstants.MODELS);
String path = outputPath + "src/main/java/org/openapitools/";

assertFileContains(path + "model/CancellationReasonTypesV2.java", """
@NotNull
@JsonProperty(JSON_PROPERTY_VERSION)
protected Integer version;
""");
assertFileContains(path + "model/CancellationReasonTypesDTO.java", "Integer getVersion();");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -550,4 +550,19 @@ void testOneOfWithoutDiscriminator() {
"@JsonTypeInfo"
);
}

@Test
void testDiscriminatorCustomType() {

var codegen = new KotlinMicronautClientCodegen();
String outputPath = generateFiles(codegen, "src/test/resources/3_0/oneof-with-discriminator2.yml", CodegenConstants.APIS, CodegenConstants.MODELS);
String path = outputPath + "src/main/kotlin/org/openapitools/";

assertFileContains(path + "model/CancellationReasonTypesV2.kt", """
@field:NotNull
@field:JsonProperty(JSON_PROPERTY_VERSION)
override var version: Int,
""");
assertFileContains(path + "model/CancellationReasonTypesDTO.kt", "val version: Int");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
openapi: 3.0.0
info:
description: This is a library API
version: 1.0.0
title: Library
license:
name: Apache-2.0
url: "https://www.apache.org/licenses/LICENSE-2.0.html"
tags:
- name: books
description: Add books
paths:
/add-subject:
post:
tags: [ subjects ]
summary: Add a new subject
operationId: addSubject
requestBody:
required: true
content:
"application/json":
schema:
$ref: "#/components/schemas/CancellationReasonTypesDTO"
responses:
"200":
description: Success
content:
"application/json":
schema:
$ref: "#/components/schemas/CancellationReasonTypesDTO"
"400":
description: Bad Request
components:
schemas:
CancellationReasonTypesDTO:
discriminator:
propertyName: version
mapping:
'-1': '#/components/schemas/CancellationReasonTypesV1'
'0': '#/components/schemas/CancellationReasonTypesV2'
'1': '#/components/schemas/CancellationReasonTypesV2'
'2': '#/components/schemas/CancellationReasonTypesV2'
'3': '#/components/schemas/CancellationReasonTypesV2'
'4': '#/components/schemas/CancellationReasonTypesV3'
oneOf:
- $ref: '#/components/schemas/CancellationReasonTypesV1'
- $ref: '#/components/schemas/CancellationReasonTypesV2'
- $ref: '#/components/schemas/CancellationReasonTypesV3'
CancellationReasonTypesV1:
type: object
properties:
version:
type: integer
title:
type: string
comments_field_prompt:
type: string
action_button_title:
type: string
can_cancel:
type: boolean
CancellationReasonTypesV2:
properties:
version:
type: integer
action_button_title:
type: string
can_cancel:
type: boolean
CancellationReasonTypesV3:
properties:
version:
type: integer
title:
type: string
Loading