Skip to content

Commit

Permalink
multiple mapping support for open api oneOf (#181)
Browse files Browse the repository at this point in the history
  • Loading branch information
Squiry authored Jul 7, 2023
1 parent 51ce572 commit f60b30d
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 15 deletions.
31 changes: 31 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,37 @@ def isPublishedLibrary = { Project p ->
}
return true
}
subprojects {
configurations {
all {
resolutionStrategy.force "com.fasterxml.jackson.core:jackson-annotations:" + libs.versions.jackson.get()
resolutionStrategy.force "com.fasterxml.jackson.core:jackson-core:" + libs.versions.jackson.get()
resolutionStrategy.force "com.fasterxml.jackson.core:jackson-databind:" + libs.versions.jackson.get()
resolutionStrategy.force "io.netty:netty-buffer:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-codec:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-codec-dns:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-codec-http2:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-codec-http:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-codec-socks:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-codec-common:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-handler:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-handler-proxy:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-resolver:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-resolver-dns:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-resolver-dns-classes-macos:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-resolver-dns-classes-macos:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-transport:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-transport-clasess-epoll:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-transport-clasess-kqueue:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-transport-native-epoll:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-transport-native-kqueue:" + libs.versions.netty.get()
resolutionStrategy.force "io.netty:netty-transport-unix-common:" + libs.versions.netty.get()
resolutionStrategy.force "org.jetbrains.kotlin:kotlin-stdlib:" + libs.versions.kotlin.get().get()
resolutionStrategy.force "org.jetbrains.kotlin:kotlin-stdlib-jdk7:" + libs.versions.kotlin.get().get()
resolutionStrategy.force "org.jetbrains.kotlin:kotlin-stdlib-jdk8:" + libs.versions.kotlin.get().get()
}
}
}

// config published libraries
subprojects {
Expand Down
2 changes: 1 addition & 1 deletion dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ dependencyResolutionManagement { DependencyResolutionManagement it ->

library('commons.codec', 'commons-codec', 'commons-codec').version('1.15')

library('openapi-generator', 'org.openapitools', 'openapi-generator').version('6.4.0')
library('openapi-generator', 'org.openapitools', 'openapi-generator').version('6.6.0')
library('swagger-core', 'io.swagger.core.v3', 'swagger-core').version('2.2.6')
library('swagger-annotations', 'io.swagger.core.v3', 'swagger-annotations').version('2.2.6')
library('swagger-models', 'io.swagger.core.v3', 'swagger-models').version('2.2.6')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,11 +419,51 @@ public Map<String, ModelsMap> updateAllModels(Map<String, ModelsMap> objs) {
}
}
if (model.discriminator != null) {
for (CodegenDiscriminator.MappedModel mappedModel : model.discriminator.getMappedModels()) {
CodegenModel childModel = allModels.get(mappedModel.getModelName());
childModel.vendorExtensions.put("x-discriminator-value", mappedModel.getMappingName());
childModel.allVars.removeIf(prop -> StringUtils.equals(model.discriminator.getPropertyBaseName(), prop.baseName));
childModel.requiredVars.removeIf(prop -> StringUtils.equals(model.discriminator.getPropertyBaseName(), prop.baseName));
var map = model.discriminator.getMappedModels().stream()
.collect(Collectors.toMap(CodegenDiscriminator.MappedModel::getModelName, m -> List.of(m.getMappingName()), (l1, l2) -> {
var l = new ArrayList<String>(l1.size() + l2.size());
l.addAll(l1);
l.addAll(l2);
return l;
}));
var uniqueMappedModels = model.discriminator.getMappedModels().stream().map(CodegenDiscriminator.MappedModel::getModelName).collect(Collectors.toSet());
model.vendorExtensions.put("x-unique-mapped-models", uniqueMappedModels);
for (var mappedModel : model.discriminator.getMappedModels()) {
var childModel = allModels.get(mappedModel.getModelName());
childModel.parentModel = model;
childModel.parent = model.classname;
var mappings = map.get(mappedModel.getModelName());
if (mappings.size() == 1) {
childModel.vars.removeIf(prop -> StringUtils.equals(model.discriminator.getPropertyBaseName(), prop.baseName));
childModel.hasVars = !childModel.allVars.isEmpty();
childModel.emptyVars = childModel.allVars.isEmpty();
childModel.allVars.removeIf(prop -> StringUtils.equals(model.discriminator.getPropertyBaseName(), prop.baseName));
childModel.requiredVars.removeIf(prop -> StringUtils.equals(model.discriminator.getPropertyBaseName(), prop.baseName));
} else if (!childModel.vendorExtensions.containsKey("x-discriminator-values")) {
var property = childModel.allVars.stream().filter(prop -> StringUtils.equals(model.discriminator.getPropertyBaseName(), prop.baseName)).findFirst().get();
if (!property.required) {
property.setRequired(true);
childModel.requiredVars.add(property);
childModel.setHasRequired(!childModel.requiredVars.isEmpty());
}

var sb = new StringBuilder().append("(");
for (int i = 0; i < mappings.size(); i++) {
var mapping = mappings.get(i);
if (i > 0) {
sb.append(" && ");
}
if (this.codegenMode.isJava()) {
sb.append("!").append(property.name).append(".equals(\"").append(mapping).append("\")");
} else {
sb.append(property.name).append(" != \"").append(mapping).append("\"");
}
}
childModel.vendorExtensions.put("x-discriminator-values-check", sb.append(")").toString());
}
var separators = this.codegenMode.isJava() ? new String[]{"{\"", "\"}"} : new String[]{"[\"", "\"]"};
var discriminatorValues = mappings.stream().collect(Collectors.joining("\", \"", separators[0], separators[1]));
childModel.vendorExtensions.put("x-discriminator-value", discriminatorValues);
}
}
if (codegenMode.isJava()) {
Expand Down Expand Up @@ -547,7 +587,7 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
var model = (Map<String, Object>) obj;
var models = (List<Map<String, Object>>) model.get("models");
var codegenModel = (CodegenModel) models.get(0).get("model");
var additionalConstructor = codegenModel.getHasVars() && codegenModel.getVars().size() != codegenModel.getRequiredVars().size();
var additionalConstructor = codegenModel.getHasVars() && !codegenModel.getVars().isEmpty() && !codegenModel.getAllVars().isEmpty() && codegenModel.getVars().size() != codegenModel.getRequiredVars().size();
model.put("additionalConstructor", additionalConstructor);
}
return objs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@ import ru.tinkoff.kora.json.common.annotation.*;
{{#discriminator}}
@ru.tinkoff.kora.json.common.annotation.Json
@JsonDiscriminatorField("{{{propertyBaseName}}}")
public sealed interface {{classname}} permits {{#mappedModels}}{{modelName}}{{^-last}}, {{/-last}}{{/mappedModels}} {
public sealed interface {{classname}} permits {{#vendorExtensions.x-unique-mapped-models}}{{.}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-unique-mapped-models}} {
}
{{/discriminator}}
{{^discriminator}}
{{^additionalConstructor}}@ru.tinkoff.kora.json.common.annotation.JsonReader
{{/additionalConstructor}}@ru.tinkoff.kora.json.common.annotation.JsonWriter
@ru.tinkoff.kora.json.common.annotation.JsonWriter
@ru.tinkoff.kora.common.annotation.Generated("openapi generator kora client")
{{#vendorExtensions.x-discriminator-value}}@JsonDiscriminatorValue("{{vendorExtensions.x-discriminator-value}}"){{/vendorExtensions.x-discriminator-value}}
{{#vendorExtensions.x-discriminator-value}}@JsonDiscriminatorValue({{{vendorExtensions.x-discriminator-value}}}){{/vendorExtensions.x-discriminator-value}}
{{#vendorExtensions.x-enable-validation}}@ru.tinkoff.kora.validation.common.annotation.Valid{{/vendorExtensions.x-enable-validation}}
public record {{classname}} (
{{#allVars}}
Expand All @@ -56,11 +55,14 @@ public static String schema = """
{{/requiredVars}} ) {
this({{#allVars}}{{#required}}{{name}}{{/required}}{{^required}}null{{/required}}{{^-last}}, {{/-last}}{{/allVars}});
}

{{/additionalConstructor}}
@ru.tinkoff.kora.json.common.annotation.JsonReader
public {{classname}} {
public {{classname}} { {{#vendorExtensions.x-discriminator-values-check}}
if {{{vendorExtensions.x-discriminator-values-check}}} {
throw new IllegalStateException("Invalid discriminator value");
}
{{/vendorExtensions.x-discriminator-values-check}}
}
{{/additionalConstructor}}


{{#allVars}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ sealed interface {{classname}}
{{^discriminator}}
@ru.tinkoff.kora.json.common.annotation.JsonWriter
@ru.tinkoff.kora.common.annotation.Generated("openapi generator kora client")
{{#vendorExtensions.x-discriminator-value}}@ru.tinkoff.kora.json.common.annotation.JsonDiscriminatorValue("{{vendorExtensions.x-discriminator-value}}"){{/vendorExtensions.x-discriminator-value}}
{{#vendorExtensions.x-discriminator-value}}@ru.tinkoff.kora.json.common.annotation.JsonDiscriminatorValue(value = {{{vendorExtensions.x-discriminator-value}}}){{/vendorExtensions.x-discriminator-value}}
{{#hasVars}}data {{/hasVars}}class {{classname}} @ru.tinkoff.kora.json.common.annotation.JsonReader constructor (
{{#allVars}}
@JsonField("{{baseName}}")
Expand All @@ -50,6 +50,14 @@ sealed interface {{classname}}
{{name}}: {{{datatypeWithEnum}}}{{^-last}},{{/-last}}
{{/requiredVars}} ) : this({{#allVars}}{{#required}}{{name}}{{/required}}{{^required}}null{{/required}}{{^-last}}, {{/-last}}{{/allVars}})
{{/additionalConstructor}}
{{#vendorExtensions.x-discriminator-values-check}}
init {
if {{{vendorExtensions.x-discriminator-values-check}}} {
throw IllegalStateException("Invalid discriminator value");
}
}
{{/vendorExtensions.x-discriminator-values-check}}



{{#allVars}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,35 @@ paths:
description: Updated
components:
schemas:
ValidationErrorDto:
title: ValidationErrorDto
type: object
oneOf:
- $ref: '#/components/schemas/BlockValidationErrorDto'
- $ref: '#/components/schemas/PropValidationErrorDto'
discriminator:
propertyName: type
mapping:
'Block.Error1': '#/components/schemas/BlockValidationErrorDto'
'Block.Error2': '#/components/schemas/BlockValidationErrorDto'
'Prop.Error': '#/components/schemas/PropValidationErrorDto'

PropValidationErrorDto:
title: PropValidationErrorDto
type: object
properties:
type:
type: string

BlockValidationErrorDto:
title: PropValidationErrorDto
type: object
properties:
type:
type: string
key:
type: integer

Pet:
type: object
required:
Expand Down

0 comments on commit f60b30d

Please sign in to comment.