From 2d3bfaf96dad35629453c1b99a3f8efa0a084bee Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sun, 3 Jul 2022 17:46:39 +0800 Subject: [PATCH] Add schema mappings (#12600) * add option schema mappings * add schema mapping support, update tests * minor fix * update other generators, tests --- .../openapitools/codegen/cmd/ConfigHelp.java | 15 +++++++ .../openapitools/codegen/cmd/Generate.java | 8 ++++ .../codegen/config/GeneratorSettings.java | 45 +++++++++++++++++++ .../gradle/plugin/OpenApiGeneratorPlugin.kt | 1 + .../OpenApiGeneratorGenerateExtension.kt | 5 +++ .../gradle/plugin/tasks/GenerateTask.kt | 13 ++++++ .../codegen/plugin/CodeGenMojo.java | 17 +++++++ .../openapitools/codegen/CodegenConfig.java | 4 +- .../openapitools/codegen/DefaultCodegen.java | 44 ++++++++++-------- .../codegen/DefaultGenerator.java | 20 ++++++++- .../codegen/config/CodegenConfigurator.java | 17 +++++++ .../config/CodegenConfiguratorUtils.java | 13 ++++++ .../languages/AbstractCSharpCodegen.java | 6 +-- .../languages/AbstractDartCodegen.java | 2 +- .../languages/AbstractEiffelCodegen.java | 6 +-- .../languages/AbstractJavaCodegen.java | 8 +++- .../languages/AbstractKotlinCodegen.java | 8 +++- .../languages/AbstractScalaCodegen.java | 2 +- .../languages/CppRestSdkClientCodegen.java | 2 +- .../languages/PythonClientCodegen.java | 24 +++++----- .../PythonExperimentalClientCodegen.java | 28 ++++++------ .../languages/TypeScriptClientCodegen.java | 2 +- .../TypeScriptFetchClientCodegen.java | 2 +- .../codegen/utils/ModelUtils.java | 16 +++---- .../codegen/DefaultCodegenTest.java | 15 +++++++ .../codegen/java/AbstractJavaCodegenTest.java | 6 +-- .../codegen/java/JavaClientCodegenTest.java | 14 +++--- .../kotlin/AbstractKotlinCodegenTest.java | 9 +++- .../codegen/utils/ModelUtilsTest.java | 6 +-- 29 files changed, 277 insertions(+), 81 deletions(-) diff --git a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/ConfigHelp.java b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/ConfigHelp.java index 07bf359e9934..d206a6749f94 100644 --- a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/ConfigHelp.java +++ b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/ConfigHelp.java @@ -71,6 +71,9 @@ public class ConfigHelp extends OpenApiGeneratorCommand { @Option(name = {"--import-mappings"}, title = "import mappings", description = "displays the default import mappings (types and aliases, and what imports they will pull into the template)") private Boolean importMappings; + @Option(name = {"--schema-mappings"}, title = "schema mappings", description = "display the schema mappings (none)") + private Boolean schemaMappings; + @Option(name = {"--inline-schema-name-mappings"}, title = "inline schema name mappings", description = "displays the inline schema name mappings (none)") private Boolean inlineSchemaNameMappings; @@ -455,6 +458,18 @@ public class ConfigHelp extends OpenApiGeneratorCommand { sb.append(newline); } + if (Boolean.TRUE.equals(schemaMappings)) { + sb.append(newline).append("SCHEMA MAPPING").append(newline).append(newline); + Map map = config.schemaMapping() + .entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> { + throw new IllegalStateException(String.format(Locale.ROOT, "Duplicated options! %s and %s", a, b)); + }, TreeMap::new)); + writePlainTextFromMap(sb, map, optIndent, optNestedIndent, "Scheme", "Mapped to"); + sb.append(newline); + } + if (Boolean.TRUE.equals(inlineSchemaNameMappings)) { sb.append(newline).append("INLINE SCHEMA NAME MAPPING").append(newline).append(newline); Map map = config.inlineSchemaNameMapping() diff --git a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java index 967fd6192dda..02f6f99f6130 100644 --- a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java +++ b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java @@ -159,6 +159,13 @@ public class Generate extends OpenApiGeneratorCommand { + " You can also have multiple occurrences of this option.") private List importMappings = new ArrayList<>(); + @Option( + name = {"--schema-mappings"}, + title = "schema mappings", + description = "specifies mappings between the schema and the new name in the format of schema_a=Cat,schema_b=Bird." + + " You can also have multiple occurrences of this option.") + private List schemaMappings = new ArrayList<>(); + @Option( name = {"--inline-schema-name-mappings"}, title = "inline schema name mappings", @@ -437,6 +444,7 @@ public class Generate extends OpenApiGeneratorCommand { } applyInstantiationTypesKvpList(instantiationTypes, configurator); applyImportMappingsKvpList(importMappings, configurator); + applySchemaMappingsKvpList(schemaMappings, configurator); applyInlineSchemaNameMappingsKvpList(inlineSchemaNameMappings, configurator); applyInlineSchemaNameDefaultsKvpList(inlineSchemaNameDefaults, configurator); applyTypeMappingsKvpList(typeMappings, configurator); diff --git a/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/config/GeneratorSettings.java b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/config/GeneratorSettings.java index 265fd2f34e16..c14a06721e8d 100644 --- a/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/config/GeneratorSettings.java +++ b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/config/GeneratorSettings.java @@ -50,6 +50,7 @@ public final class GeneratorSettings implements Serializable { private final Map typeMappings; private final Map additionalProperties; private final Map importMappings; + private final Map schemaMappings; private final Map inlineSchemaNameMappings; private final Map inlineSchemaNameDefaults; private final Set languageSpecificPrimitives; @@ -236,6 +237,15 @@ public final class GeneratorSettings implements Serializable { return importMappings; } + /** + * Gets schema mappings between a schema and the new name. + * + * @return the schema mappings + */ + public Map getSchemaMappings() { + return schemaMappings; + } + /** * Gets inline schema name mappings between an inline schema name and the new name. * @@ -369,6 +379,7 @@ public final class GeneratorSettings implements Serializable { instantiationTypes = Collections.unmodifiableMap(builder.instantiationTypes); typeMappings = Collections.unmodifiableMap(builder.typeMappings); importMappings = Collections.unmodifiableMap(builder.importMappings); + schemaMappings = Collections.unmodifiableMap(builder.schemaMappings); inlineSchemaNameMappings = Collections.unmodifiableMap(builder.inlineSchemaNameMappings); inlineSchemaNameDefaults = Collections.unmodifiableMap(builder.inlineSchemaNameDefaults); languageSpecificPrimitives = Collections.unmodifiableSet(builder.languageSpecificPrimitives); @@ -441,6 +452,7 @@ public final class GeneratorSettings implements Serializable { typeMappings = Collections.unmodifiableMap(new HashMap<>(0)); additionalProperties = Collections.unmodifiableMap(new HashMap<>(0)); importMappings = Collections.unmodifiableMap(new HashMap<>(0)); + schemaMappings = Collections.unmodifiableMap(new HashMap<>(0)); inlineSchemaNameMappings = Collections.unmodifiableMap(new HashMap<>(0)); inlineSchemaNameDefaults = Collections.unmodifiableMap(new HashMap<>(0)); languageSpecificPrimitives = Collections.unmodifiableSet(new HashSet<>(0)); @@ -494,6 +506,9 @@ public final class GeneratorSettings implements Serializable { if (copy.getImportMappings() != null) { builder.importMappings.putAll(copy.getImportMappings()); } + if (copy.getSchemaMappings() != null) { + builder.schemaMappings.putAll(copy.getSchemaMappings()); + } if (copy.getInlineSchemaNameMappings() != null) { builder.inlineSchemaNameMappings.putAll(copy.getInlineSchemaNameMappings()); } @@ -539,6 +554,7 @@ public final class GeneratorSettings implements Serializable { private Map typeMappings; private Map additionalProperties; private Map importMappings; + private Map schemaMappings; private Map inlineSchemaNameMappings; private Map inlineSchemaNameDefaults; private Set languageSpecificPrimitives; @@ -558,6 +574,7 @@ public final class GeneratorSettings implements Serializable { typeMappings = new HashMap<>(); additionalProperties = new HashMap<>(); importMappings = new HashMap<>(); + schemaMappings = new HashMap<>(); inlineSchemaNameMappings = new HashMap<>(); inlineSchemaNameDefaults = new HashMap<>(); languageSpecificPrimitives = new HashSet<>(); @@ -776,6 +793,32 @@ public final class GeneratorSettings implements Serializable { return this; } + /** + * Sets the {@code schemaMappings} and returns a reference to this Builder so that the methods can be chained together. + * + * @param schemaMappings the {@code schemaMappings} to set + * @return a reference to this Builder + */ + public Builder withSchemaMappings(Map schemaMappings) { + this.schemaMappings = schemaMappings; + return this; + } + + /** + * Sets a single {@code schemaMappings} and returns a reference to this Builder so that the methods can be chained together. + * + * @param key A key for some schema mapping + * @param value The value of some schema mapping + * @return a reference to this Builder + */ + public Builder withSchemaMapping(String key, String value) { + if (this.schemaMappings == null) { + this.schemaMappings = new HashMap<>(); + } + this.schemaMappings.put(key, value); + return this; + } + /** * Sets the {@code importMappings} and returns a reference to this Builder so that the methods can be chained together. * @@ -1039,6 +1082,7 @@ public final class GeneratorSettings implements Serializable { Objects.equals(getTypeMappings(), that.getTypeMappings()) && Objects.equals(getAdditionalProperties(), that.getAdditionalProperties()) && Objects.equals(getImportMappings(), that.getImportMappings()) && + Objects.equals(getSchemaMappings(), that.getSchemaMappings()) && Objects.equals(getInlineSchemaNameMappings(), that.getInlineSchemaNameMappings()) && Objects.equals(getInlineSchemaNameDefaults(), that.getInlineSchemaNameDefaults()) && Objects.equals(getLanguageSpecificPrimitives(), that.getLanguageSpecificPrimitives()) && @@ -1069,6 +1113,7 @@ public final class GeneratorSettings implements Serializable { getTypeMappings(), getAdditionalProperties(), getImportMappings(), + getSchemaMappings(), getInlineSchemaNameMappings(), getInlineSchemaNameDefaults(), getLanguageSpecificPrimitives(), diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt index c6410ced6e5c..7457ccf98b6b 100644 --- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt +++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt @@ -113,6 +113,7 @@ class OpenApiGeneratorPlugin : Plugin { serverVariables.set(generate.serverVariables) languageSpecificPrimitives.set(generate.languageSpecificPrimitives) importMappings.set(generate.importMappings) + schemaMappings.set(generate.schemaMappings) inlineSchemaNameMappings.set(generate.inlineSchemaNameMappings) inlineSchemaNameDefaults.set(generate.inlineSchemaNameDefaults) invokerPackage.set(generate.invokerPackage) diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt index 6ea8608fd491..6a5ef25cc0a4 100644 --- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt +++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt @@ -141,6 +141,11 @@ open class OpenApiGeneratorGenerateExtension(project: Project) { */ val importMappings = project.objects.mapProperty() + /** + * Specifies mappings between a given schema and the new one + */ + val schemaMappings = project.objects.mapProperty() + /** * Specifies mappings between an inline schema name and the new name */ diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt index 5ebec599e6e0..d81ab68d91b7 100644 --- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt +++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt @@ -219,6 +219,13 @@ open class GenerateTask : DefaultTask() { @Input val importMappings = project.objects.mapProperty() + /** + * Specifies mappings between a given schema and the new one. + */ + @Optional + @Input + val schemaMappings = project.objects.mapProperty() + /** * Specifies mappings between the inline scheme name and the new name */ @@ -692,6 +699,12 @@ open class GenerateTask : DefaultTask() { } } + if (schemaMappings.isPresent) { + schemaMappings.get().forEach { entry -> + configurator.addSchemaMapping(entry.key, entry.value) + } + } + if (inlineSchemaNameMappings.isPresent) { inlineSchemaNameMappings.get().forEach { entry -> configurator.addInlineSchemaNameMapping(entry.key, entry.value) diff --git a/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java b/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java index 56e39b8284c8..44e49ca5211d 100644 --- a/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java +++ b/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java @@ -298,6 +298,12 @@ public class CodeGenMojo extends AbstractMojo { @Parameter(name = "importMappings", property = "openapi.generator.maven.plugin.importMappings") private List importMappings; + /** + * A map of scheme and the new one + */ + @Parameter(name = "schemaMappings", property = "openapi.generator.maven.plugin.schemaMappings") + private List schemaMappings; + /** * A map of inline scheme names and the new names */ @@ -671,6 +677,12 @@ public class CodeGenMojo extends AbstractMojo { configurator); } + // Retained for backwards-compatibility with configOptions -> schema-mappings + if (schemaMappings == null && configOptions.containsKey("schema-mappings")) { + applySchemaMappingsKvp(configOptions.get("schema-mappings").toString(), + configurator); + } + // Retained for backwards-compatibility with configOptions -> inline-schema-name-mappings if (inlineSchemaNameMappings == null && configOptions.containsKey("inline-schema-name-mappings")) { applyInlineSchemaNameMappingsKvp(configOptions.get("inline-schema-name-mappings").toString(), @@ -721,6 +733,11 @@ public class CodeGenMojo extends AbstractMojo { applyImportMappingsKvpList(importMappings, configurator); } + // Apply Schema Mappings + if (schemaMappings != null && (configOptions == null || !configOptions.containsKey("schema-mappings"))) { + applySchemaMappingsKvpList(schemaMappings, configurator); + } + // Apply Inline Schema Name Mappings if (inlineSchemaNameMappings != null && (configOptions == null || !configOptions.containsKey("inline-schema-name-mappings"))) { applyInlineSchemaNameMappingsKvpList(inlineSchemaNameMappings, configurator); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java index 970bbe5a2b50..e18324d541e4 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java @@ -141,6 +141,8 @@ public interface CodegenConfig { Map importMapping(); + Map schemaMapping(); + Map inlineSchemaNameMapping(); Map inlineSchemaNameDefault(); @@ -311,7 +313,7 @@ public interface CodegenConfig { void setRemoveEnumValuePrefix(boolean removeEnumValuePrefix); - Schema unaliasSchema(Schema schema, Map usedImportMappings); + Schema unaliasSchema(Schema schema, Map schemaMappings); String defaultTemplatingEngine(); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index bc93c143f77a..e4c488d3c01f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -153,6 +153,8 @@ public class DefaultCodegen implements CodegenConfig { protected Set reservedWords; protected Set languageSpecificPrimitives = new HashSet<>(); protected Map importMapping = new HashMap<>(); + // a map to store the mappping between a schema and the new one + protected Map schemaMapping = new HashMap<>(); // a map to store the mappping between inline schema and the name provided by the user protected Map inlineSchemaNameMapping = new HashMap<>(); // a map to store the inline schema naming conventions @@ -1060,6 +1062,11 @@ public class DefaultCodegen implements CodegenConfig { return importMapping; } + @Override + public Map schemaMapping() { + return schemaMapping; + } + @Override public Map inlineSchemaNameMapping() { return inlineSchemaNameMapping; @@ -2191,8 +2198,8 @@ public class DefaultCodegen implements CodegenConfig { } @Override - public Schema unaliasSchema(Schema schema, Map usedImportMappings) { - return ModelUtils.unaliasSchema(this.openAPI, schema, usedImportMappings); + public Schema unaliasSchema(Schema schema, Map schemaMappings) { + return ModelUtils.unaliasSchema(this.openAPI, schema, schemaMappings); } /** @@ -2202,13 +2209,13 @@ public class DefaultCodegen implements CodegenConfig { * @return the string representation of the schema type. */ protected String getSingleSchemaType(Schema schema) { - Schema unaliasSchema = unaliasSchema(schema, importMapping); + Schema unaliasSchema = unaliasSchema(schema, schemaMapping); if (StringUtils.isNotBlank(unaliasSchema.get$ref())) { // reference to another definition/schema // get the schema/model name from $ref String schemaName = ModelUtils.getSimpleRef(unaliasSchema.get$ref()); if (StringUtils.isNotEmpty(schemaName)) { - if (importMapping.containsKey(schemaName)) { + if (schemaMapping.containsKey(schemaName)) { return schemaName; } return getAlias(schemaName); @@ -2304,8 +2311,8 @@ public class DefaultCodegen implements CodegenConfig { } else if (ModelUtils.isAnyType(schema)) { return "AnyType"; } else if (StringUtils.isNotEmpty(schema.getType())) { - if (!importMapping.containsKey(schema.getType())) { - LOGGER.warn("Unknown type found in the schema: {}", schema.getType()); + if (!schemaMapping.containsKey(schema.getType())) { + LOGGER.warn("Unknown type found in the schema: {}. To map it, please use the schema mapping option (e.g. --schema-mappings in CLI)", schema.getType()); } return schema.getType(); } @@ -2531,7 +2538,7 @@ public class DefaultCodegen implements CodegenConfig { m.interfaces = new ArrayList<>(); for (Schema interfaceSchema : interfaces) { - interfaceSchema = unaliasSchema(interfaceSchema, importMapping); + interfaceSchema = unaliasSchema(interfaceSchema, schemaMapping); if (StringUtils.isBlank(interfaceSchema.get$ref())) { // primitive type @@ -2759,7 +2766,7 @@ public class DefaultCodegen implements CodegenConfig { } // unalias schema - schema = unaliasSchema(schema, importMapping); + schema = unaliasSchema(schema, schemaMapping); if (schema == null) { LOGGER.warn("Schema {} not found", name); return null; @@ -3432,7 +3439,7 @@ public class DefaultCodegen implements CodegenConfig { property.maxItems = p.getMaxProperties(); // handle inner property - Schema innerSchema = unaliasSchema(getAdditionalProperties(p), importMapping); + Schema innerSchema = unaliasSchema(getAdditionalProperties(p), schemaMapping); if (innerSchema == null) { LOGGER.error("Undefined map inner type for `{}`. Default to String.", p.getName()); innerSchema = new StringSchema().description("//TODO automatically added by openapi-generator due to undefined type"); @@ -3535,7 +3542,7 @@ public class DefaultCodegen implements CodegenConfig { return cpc; } // unalias schema - p = unaliasSchema(p, importMapping); + p = unaliasSchema(p, schemaMapping); CodegenProperty property = CodegenModelFactory.newInstance(CodegenModelType.PROPERTY); ModelUtils.syncValidationProperties(p, property); @@ -3703,7 +3710,7 @@ public class DefaultCodegen implements CodegenConfig { itemName = property.name; } ArraySchema arraySchema = (ArraySchema) p; - Schema innerSchema = unaliasSchema(getSchemaItems(arraySchema), importMapping); + Schema innerSchema = unaliasSchema(getSchemaItems(arraySchema), schemaMapping); CodegenProperty cp = fromProperty(itemName, innerSchema); updatePropertyForArray(property, cp); } else if (ModelUtils.isTypeObjectSchema(p)) { @@ -3942,14 +3949,14 @@ public class DefaultCodegen implements CodegenConfig { * @param schemas a map of the schemas in the openapi spec * @param op endpoint CodegenOperation * @param methodResponse the default ApiResponse for the endpoint - * @param importMappings mappings of external types to be omitted by unaliasing + * @param schemaMappings mappings of external types to be omitted by unaliasing */ protected void handleMethodResponse(Operation operation, Map schemas, CodegenOperation op, ApiResponse methodResponse, - Map importMappings) { - Schema responseSchema = unaliasSchema(ModelUtils.getSchemaFromResponse(methodResponse), importMapping); + Map schemaMappings) { + Schema responseSchema = unaliasSchema(ModelUtils.getSchemaFromResponse(methodResponse), schemaMapping); if (responseSchema != null) { CodegenProperty cm = fromProperty("response", responseSchema); @@ -4388,7 +4395,7 @@ public class DefaultCodegen implements CodegenConfig { Schema responseSchema; if (this.openAPI != null && this.openAPI.getComponents() != null) { - responseSchema = unaliasSchema(ModelUtils.getSchemaFromResponse(response), importMapping); + responseSchema = unaliasSchema(ModelUtils.getSchemaFromResponse(response), schemaMapping); } else { // no model/alias defined responseSchema = ModelUtils.getSchemaFromResponse(response); } @@ -4726,6 +4733,7 @@ public class DefaultCodegen implements CodegenConfig { return codegenParameter; } + // TODO need to reivew replacing empty map with schemaMapping instead parameterSchema = unaliasSchema(parameterSchema, Collections.emptyMap()); if (parameterSchema == null) { LOGGER.warn("warning! Schema not found for parameter \" {} \"", parameter.getName()); @@ -5314,7 +5322,7 @@ public class DefaultCodegen implements CodegenConfig { protected Map unaliasPropertySchema(Map properties) { if (properties != null) { for (String key : properties.keySet()) { - properties.put(key, unaliasSchema(properties.get(key), importMapping())); + properties.put(key, unaliasSchema(properties.get(key), schemaMapping())); } } @@ -6424,7 +6432,7 @@ public class DefaultCodegen implements CodegenConfig { LOGGER.debug("Debugging fromFormProperty {}: {}", name, propertySchema); CodegenProperty codegenProperty = fromProperty(name, propertySchema); - Schema ps = unaliasSchema(propertySchema, importMapping); + Schema ps = unaliasSchema(propertySchema, schemaMapping); ModelUtils.syncValidationProperties(ps, codegenParameter); codegenParameter.setTypeProperties(ps); codegenParameter.setComposedSchemas(getComposedSchemas(ps)); @@ -6935,7 +6943,7 @@ public class DefaultCodegen implements CodegenConfig { name = ModelUtils.getSimpleRef(schema.get$ref()); } - Schema unaliasedSchema = unaliasSchema(schema, importMapping); + Schema unaliasedSchema = unaliasSchema(schema, schemaMapping); schema = ModelUtils.getReferencedSchema(this.openAPI, schema); ModelUtils.syncValidationProperties(unaliasedSchema, codegenParameter); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java index 65f99563cc1f..420ad43698fe 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java @@ -441,6 +441,19 @@ public class DefaultGenerator implements Generator { // process models only for (String name : modelKeys) { try { + //don't generate models that have an import mapping + if (config.schemaMapping().containsKey(name)) { + LOGGER.debug("Model {} not imported due to import mapping", name); + + for (String templateName : config.modelTemplateFiles().keySet()) { + // HACK: Because this returns early, could lead to some invalid model reporting. + String filename = config.modelFilename(templateName, name); + Path path = java.nio.file.Paths.get(filename); + this.templateProcessor.skip(path,"Skipped prior to model processing due to schema mapping." ); + } + continue; + } + // don't generate models that are not used as object (e.g. form parameters) if (unusedModels.contains(name)) { if (Boolean.FALSE.equals(skipFormModel)) { @@ -464,7 +477,7 @@ public class DefaultGenerator implements Generator { // generators may choose to make models for use case 2 + 3 Schema refSchema = new Schema(); refSchema.set$ref("#/components/schemas/" + name); - Schema unaliasedSchema = config.unaliasSchema(refSchema, config.importMapping()); + Schema unaliasedSchema = config.unaliasSchema(refSchema, config.schemaMapping()); if (unaliasedSchema.get$ref() == null) { LOGGER.info("Model {} not generated since it's a free-form object", name); continue; @@ -508,6 +521,11 @@ public class DefaultGenerator implements Generator { ModelsMap models = allProcessedModels.get(modelName); models.put("modelPackage", config.modelPackage()); try { + //don't generate models that have a schema mapping + if (config.schemaMapping().containsKey(modelName)) { + continue; + } + // TODO revise below as we've already performed unaliasing so that the isAlias check may be removed List modelList = models.getModels(); if (modelList != null && !modelList.isEmpty()) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfigurator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfigurator.java index 374ee3116dab..3d2d9c3aaacc 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfigurator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfigurator.java @@ -68,6 +68,7 @@ public class CodegenConfigurator { private Map typeMappings = new HashMap<>(); private Map additionalProperties = new HashMap<>(); private Map importMappings = new HashMap<>(); + private Map schemaMappings = new HashMap<>(); private Map inlineSchemaNameMappings = new HashMap<>(); private Map inlineSchemaNameDefaults = new HashMap<>(); private Set languageSpecificPrimitives = new HashSet<>(); @@ -113,6 +114,9 @@ public class CodegenConfigurator { if(generatorSettings.getImportMappings() != null) { configurator.importMappings.putAll(generatorSettings.getImportMappings()); } + if(generatorSettings.getSchemaMappings() != null) { + configurator.schemaMappings.putAll(generatorSettings.getSchemaMappings()); + } if(generatorSettings.getInlineSchemaNameMappings() != null) { configurator.inlineSchemaNameMappings.putAll(generatorSettings.getInlineSchemaNameMappings()); } @@ -188,6 +192,12 @@ public class CodegenConfigurator { return this; } + public CodegenConfigurator addSchemaMapping(String key, String value) { + this.schemaMappings.put(key, value); + generatorSettingsBuilder.withSchemaMapping(key, value); + return this; + } + public CodegenConfigurator addInlineSchemaNameMapping(String key, String value) { this.inlineSchemaNameMappings.put(key, value); generatorSettingsBuilder.withInlineSchemaNameMapping(key, value); @@ -354,6 +364,12 @@ public class CodegenConfigurator { return this; } + public CodegenConfigurator setSchemaMappings(Map schemaMappings) { + this.schemaMappings = schemaMappings; + generatorSettingsBuilder.withSchemaMappings(schemaMappings); + return this; + } + public CodegenConfigurator setInlineSchemaNameMappings(Map inlineSchemaNameMappings) { this.inlineSchemaNameMappings = inlineSchemaNameMappings; generatorSettingsBuilder.withInlineSchemaNameMappings(inlineSchemaNameMappings); @@ -642,6 +658,7 @@ public class CodegenConfigurator { config.instantiationTypes().putAll(generatorSettings.getInstantiationTypes()); config.typeMapping().putAll(generatorSettings.getTypeMappings()); config.importMapping().putAll(generatorSettings.getImportMappings()); + config.schemaMapping().putAll(generatorSettings.getSchemaMappings()); config.inlineSchemaNameMapping().putAll(generatorSettings.getInlineSchemaNameMappings()); config.inlineSchemaNameDefault().putAll(generatorSettings.getInlineSchemaNameDefaults()); config.languageSpecificPrimitives().addAll(generatorSettings.getLanguageSpecificPrimitives()); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfiguratorUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfiguratorUtils.java index 15a516a65586..fb708d4b2f55 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfiguratorUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfiguratorUtils.java @@ -81,6 +81,19 @@ public final class CodegenConfiguratorUtils { } } + public static void applySchemaMappingsKvpList(List schemaMappings, CodegenConfigurator configurator) { + for (String propString : schemaMappings) { + applySchemaMappingsKvp(propString, configurator); + } + } + + public static void applySchemaMappingsKvp(String schemaMappings, CodegenConfigurator configurator) { + final Map map = createMapFromKeyValuePairs(schemaMappings); + for (Map.Entry entry : map.entrySet()) { + configurator.addSchemaMapping(entry.getKey().trim(), entry.getValue().trim()); + } + } + public static void applyInlineSchemaNameMappingsKvpList(List inlineSchemaNameMappings, CodegenConfigurator configurator) { for (String propString : inlineSchemaNameMappings) { applyInlineSchemaNameMappingsKvp(propString, configurator); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java index dbc934e0bb04..960a6ae7f330 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java @@ -1070,10 +1070,10 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co @Override public String toModelName(String name) { - // We need to check if import-mapping has a different model for this class, so we use it + // We need to check if schema-mapping has a different model for this class, so we use it // instead of the auto-generated one. - if (importMapping.containsKey(name)) { - return importMapping.get(name); + if (schemaMapping.containsKey(name)) { + return schemaMapping.get(name); } // memoization and lookup in the cache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java index 544d6d690890..bc42591cb25d 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java @@ -488,7 +488,7 @@ public abstract class AbstractDartCodegen extends DefaultCodegen { @Override public String getTypeDeclaration(Schema p) { - Schema schema = ModelUtils.unaliasSchema(this.openAPI, p, importMapping); + Schema schema = ModelUtils.unaliasSchema(this.openAPI, p, schemaMapping); Schema target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { Schema items = getSchemaItems((ArraySchema) schema); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java index 7e3846981f28..5e179068c5d5 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractEiffelCodegen.java @@ -177,10 +177,10 @@ public abstract class AbstractEiffelCodegen extends DefaultCodegen implements Co @Override public String toModelFilename(String name) { - // We need to check if import-mapping has a different model for this class, so we use it + // We need to check if schema-mapping has a different model for this class, so we use it // instead of the auto-generated one. - if (importMapping.containsKey(name)) { - return importMapping.get(name); + if (schemaMapping.containsKey(name)) { + return schemaMapping.get(name); } if (!StringUtils.isEmpty(modelNamePrefix)) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index 357bc078f437..3102703b8339 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -824,6 +824,12 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code @Override public String toModelName(final String name) { + // We need to check if schema-mapping has a different model for this class, so we use it + // instead of the auto-generated one. + if (schemaMapping.containsKey(name)) { + return schemaMapping.get(name); + } + final String sanitizedName = sanitizeName(name); String nameWithPrefixSuffix = sanitizedName; @@ -867,7 +873,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code @Override public String getTypeDeclaration(Schema p) { - Schema schema = ModelUtils.unaliasSchema(this.openAPI, p, importMapping); + Schema schema = ModelUtils.unaliasSchema(this.openAPI, p, schemaMapping); Schema target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { Schema items = getSchemaItems((ArraySchema) schema); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java index 0c00eca3ef54..59a9af6e8bc5 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractKotlinCodegen.java @@ -365,7 +365,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co */ @Override public String getTypeDeclaration(Schema p) { - Schema schema = ModelUtils.unaliasSchema(this.openAPI, p, importMapping); + Schema schema = ModelUtils.unaliasSchema(this.openAPI, p, schemaMapping); Schema target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { Schema items = getSchemaItems((ArraySchema) schema); @@ -674,6 +674,12 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co return name; } + // If schemaMapping contains name, assume this is a legitimate model name. + if (schemaMapping.containsKey(name)) { + return schemaMapping.get(name); + } + + // TODO review importMapping below as we've added schema mapping support // If importMapping contains name, assume this is a legitimate model name. if (importMapping.containsKey(name)) { return importMapping.get(name); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java index 10ddac83e569..f0dbaed17af1 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java @@ -357,7 +357,7 @@ public abstract class AbstractScalaCodegen extends DefaultCodegen { @Override public String getTypeDeclaration(Schema p) { - Schema schema = ModelUtils.unaliasSchema(this.openAPI, p, importMapping); + Schema schema = ModelUtils.unaliasSchema(this.openAPI, p, schemaMapping); Schema target = ModelUtils.isGenerateAliasAsModel() ? p : schema; if (ModelUtils.isArraySchema(target)) { Schema items = getSchemaItems((ArraySchema) schema); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java index 8810aefabc23..13be5ab41396 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java @@ -295,7 +295,7 @@ public class CppRestSdkClientCodegen extends AbstractCppCodegen { if (methodResponse != null) { Schema response = ModelUtils.getSchemaFromResponse(methodResponse); - response = ModelUtils.unaliasSchema(this.openAPI, response, importMapping); + response = ModelUtils.unaliasSchema(this.openAPI, response, schemaMapping); if (response != null) { CodegenProperty cm = fromProperty("response", response); op.vendorExtensions.put("x-codegen-response", cm); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java index 942358eac042..b6f7eef4076e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java @@ -215,7 +215,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen { } @Override - public Schema unaliasSchema(Schema schema, Map usedImportMappings) { + public Schema unaliasSchema(Schema schema, Map schemaMappings) { Map allSchemas = ModelUtils.getSchemas(openAPI); if (allSchemas == null || allSchemas.isEmpty()) { // skip the warning as the spec can have no model defined @@ -225,8 +225,8 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen { if (schema != null && StringUtils.isNotEmpty(schema.get$ref())) { String simpleRef = ModelUtils.getSimpleRef(schema.get$ref()); - if (usedImportMappings.containsKey(simpleRef)) { - LOGGER.debug("Schema unaliasing of {} omitted because aliased class is to be mapped to {}", simpleRef, usedImportMappings.get(simpleRef)); + if (schemaMappings.containsKey(simpleRef)) { + LOGGER.debug("Schema unaliasing of {} omitted because aliased class is to be mapped to {}", simpleRef, schemaMappings.get(simpleRef)); return schema; } Schema ref = allSchemas.get(simpleRef); @@ -241,7 +241,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen { return schema; // generate a model extending array } else { return unaliasSchema(allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), - usedImportMappings); + schemaMappings); } } else if (ModelUtils.isComposedSchema(ref)) { return schema; @@ -254,7 +254,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen { } else { // treat it as a typical map return unaliasSchema(allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), - usedImportMappings); + schemaMappings); } } } else if (ModelUtils.isObjectSchema(ref)) { // model @@ -268,7 +268,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen { return schema; } else { return unaliasSchema(allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), - usedImportMappings); + schemaMappings); } } } else if (ModelUtils.hasValidation(ref)) { @@ -279,7 +279,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen { // - use those validations when we use this schema in composed oneOf schemas return schema; } else { - return unaliasSchema(allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), usedImportMappings); + return unaliasSchema(allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), schemaMappings); } } return schema; @@ -407,7 +407,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen { Map allDefinitions = ModelUtils.getSchemas(this.openAPI); for (String schemaName : allDefinitions.keySet()) { Schema refSchema = new Schema().$ref("#/components/schemas/" + schemaName); - Schema unaliasedSchema = unaliasSchema(refSchema, importMapping); + Schema unaliasedSchema = unaliasSchema(refSchema, schemaMapping); String modelName = toModelName(schemaName); if (unaliasedSchema.get$ref() == null) { modelsToRemove.add(modelName); @@ -517,7 +517,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen { if (schema.get$ref() == null) { return cp; } - Schema unaliasedSchema = unaliasSchema(schema, importMapping); + Schema unaliasedSchema = unaliasSchema(schema, schemaMapping); CodegenProperty unaliasedProp = fromProperty("body", unaliasedSchema); Boolean dataTypeMismatch = !cp.dataType.equals(unaliasedProp.dataType); Boolean baseTypeMismatch = !cp.baseType.equals(unaliasedProp.complexType) && unaliasedProp.complexType != null; @@ -547,7 +547,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen { protected void addBodyModelSchema(CodegenParameter codegenParameter, String name, Schema schema, Set imports, String bodyParameterName, boolean forceSimpleRef) { if (name != null) { Schema bodySchema = new Schema().$ref("#/components/schemas/" + name); - Schema unaliased = unaliasSchema(bodySchema, importMapping); + Schema unaliased = unaliasSchema(bodySchema, schemaMapping); if (unaliased.get$ref() != null) { forceSimpleRef = true; } @@ -758,7 +758,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen { public String getModelName(Schema sc) { if (sc.get$ref() != null) { - Schema unaliasedSchema = unaliasSchema(sc, importMapping); + Schema unaliasedSchema = unaliasSchema(sc, schemaMapping); if (unaliasedSchema.get$ref() != null) { return toModelName(ModelUtils.getSimpleRef(sc.get$ref())); } @@ -851,7 +851,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen { if (StringUtils.isNotEmpty(p.get$ref())) { // The input schema is a reference. If the resolved schema is // a composed schema, convert the name to a Python class. - Schema unaliasedSchema = unaliasSchema(p, importMapping); + Schema unaliasedSchema = unaliasSchema(p, schemaMapping); if (unaliasedSchema.get$ref() != null) { String modelName = toModelName(ModelUtils.getSimpleRef(p.get$ref())); if (referencedModelNames != null) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonExperimentalClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonExperimentalClientCodegen.java index 19d2f6db89da..3be88480dd17 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonExperimentalClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonExperimentalClientCodegen.java @@ -561,7 +561,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { } @Override - public Schema unaliasSchema(Schema schema, Map usedImportMappings) { + public Schema unaliasSchema(Schema schema, Map schemaMappings) { Map allSchemas = ModelUtils.getSchemas(openAPI); if (allSchemas == null || allSchemas.isEmpty()) { // skip the warning as the spec can have no model defined @@ -571,8 +571,8 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { if (schema != null && StringUtils.isNotEmpty(schema.get$ref())) { String simpleRef = ModelUtils.getSimpleRef(schema.get$ref()); - if (usedImportMappings.containsKey(simpleRef)) { - LOGGER.debug("Schema unaliasing of {} omitted because aliased class is to be mapped to {}", simpleRef, usedImportMappings.get(simpleRef)); + if (schemaMappings.containsKey(simpleRef)) { + LOGGER.debug("Schema unaliasing of {} omitted because aliased class is to be mapped to {}", simpleRef, schemaMappings.get(simpleRef)); return schema; } Schema ref = allSchemas.get(simpleRef); @@ -587,7 +587,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { return schema; // generate a model extending array } else { return unaliasSchema(allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), - usedImportMappings); + schemaMappings); } } else if (ModelUtils.isComposedSchema(ref)) { return schema; @@ -600,7 +600,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { } else { // treat it as a typical map return unaliasSchema(allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), - usedImportMappings); + schemaMappings); } } } else if (ModelUtils.isObjectSchema(ref)) { // model @@ -614,7 +614,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { return schema; } return unaliasSchema(allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), - usedImportMappings); + schemaMappings); } } else if (ModelUtils.hasValidation(ref)) { // non object non array non map schemas that have validations @@ -628,7 +628,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { // we make these models so instances of this will be subclasses of this model return schema; } else { - return unaliasSchema(allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), usedImportMappings); + return unaliasSchema(allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), schemaMappings); } } return schema; @@ -751,7 +751,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { Map allDefinitions = ModelUtils.getSchemas(this.openAPI); for (String schemaName : allDefinitions.keySet()) { Schema refSchema = new Schema().$ref("#/components/schemas/" + schemaName); - Schema unaliasedSchema = unaliasSchema(refSchema, importMapping); + Schema unaliasedSchema = unaliasSchema(refSchema, schemaMapping); String modelName = toModelName(schemaName); if (unaliasedSchema.get$ref() == null) { continue; @@ -856,7 +856,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { if (cp.isEnum) { updateCodegenPropertyEnum(cp); } - Schema unaliasedSchema = unaliasSchema(p, importMapping); + Schema unaliasedSchema = unaliasSchema(p, schemaMapping); if (cp.isPrimitiveType && unaliasedSchema.get$ref() != null) { cp.complexType = cp.dataType; } @@ -944,7 +944,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { if (schema.get$ref() == null) { return cp; } - Schema unaliasedSchema = unaliasSchema(schema, importMapping); + Schema unaliasedSchema = unaliasSchema(schema, schemaMapping); CodegenProperty unaliasedProp = fromProperty("body", unaliasedSchema); Boolean dataTypeMismatch = !cp.dataType.equals(unaliasedProp.dataType); Boolean baseTypeMismatch = !cp.baseType.equals(unaliasedProp.complexType) && unaliasedProp.complexType != null; @@ -975,7 +975,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { protected void addBodyModelSchema(CodegenParameter codegenParameter, String name, Schema schema, Set imports, String bodyParameterName, boolean forceSimpleRef) { if (name != null) { Schema bodySchema = new Schema().$ref("#/components/schemas/" + name); - Schema unaliased = unaliasSchema(bodySchema, importMapping); + Schema unaliased = unaliasSchema(bodySchema, schemaMapping); if (unaliased.get$ref() != null) { forceSimpleRef = true; } @@ -1229,7 +1229,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { @Override public CodegenModel fromModel(String name, Schema sc) { CodegenModel cm = super.fromModel(name, sc); - Schema unaliasedSchema = unaliasSchema(sc, importMapping); + Schema unaliasedSchema = unaliasSchema(sc, schemaMapping); if (unaliasedSchema != null) { if (ModelUtils.isDecimalSchema(unaliasedSchema)) { // type: string, format: number cm.isString = false; @@ -1280,7 +1280,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { public String getModelName(Schema sc) { if (sc.get$ref() != null) { - Schema unaliasedSchema = unaliasSchema(sc, importMapping); + Schema unaliasedSchema = unaliasSchema(sc, schemaMapping); if (unaliasedSchema.get$ref() != null) { return toModelName(ModelUtils.getSimpleRef(sc.get$ref())); } @@ -1317,7 +1317,7 @@ public class PythonExperimentalClientCodegen extends AbstractPythonCodegen { if (StringUtils.isNotEmpty(p.get$ref())) { // The input schema is a reference. If the resolved schema is // a composed schema, convert the name to a Python class. - Schema unaliasedSchema = unaliasSchema(p, importMapping); + Schema unaliasedSchema = unaliasSchema(p, schemaMapping); if (unaliasedSchema.get$ref() != null) { String modelName = toModelName(ModelUtils.getSimpleRef(p.get$ref())); if (referencedModelNames != null) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java index 3d84fb3c948c..e0bd61d53a91 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java @@ -940,7 +940,7 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo public String getModelName(Schema sc) { if (sc.get$ref() != null) { - Schema unaliasedSchema = unaliasSchema(sc, importMapping); + Schema unaliasedSchema = unaliasSchema(sc, schemaMapping); if (unaliasedSchema.get$ref() != null) { return toModelName(ModelUtils.getSimpleRef(sc.get$ref())); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java index 0fa0ba05984e..38a75efd9de5 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java @@ -510,7 +510,7 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege } if (!op.hasReturnPassthroughVoid) { - Schema responseSchema = unaliasSchema(ModelUtils.getSchemaFromResponse(methodResponse), importMapping); + Schema responseSchema = unaliasSchema(ModelUtils.getSchemaFromResponse(methodResponse), schemaMapping); ExtendedCodegenProperty cp = null; if (op.returnPassthrough instanceof String && cm != null) { cp = (ExtendedCodegenProperty) this.processCodeGenModel(cm).vars.get(1); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java index cb475a64c203..09bc8dc2c81b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java @@ -1191,12 +1191,12 @@ public class ModelUtils { * * @param openAPI OpenAPI document containing the schemas. * @param schema schema (alias or direct reference) - * @param importMappings mappings of external types to be omitted by unaliasing + * @param schemaMappings mappings of external types to be omitted by unaliasing * @return actual schema */ public static Schema unaliasSchema(OpenAPI openAPI, Schema schema, - Map importMappings) { + Map schemaMappings) { Map allSchemas = getSchemas(openAPI); if (allSchemas == null || allSchemas.isEmpty()) { // skip the warning as the spec can have no model defined @@ -1206,8 +1206,8 @@ public class ModelUtils { if (schema != null && StringUtils.isNotEmpty(schema.get$ref())) { String simpleRef = ModelUtils.getSimpleRef(schema.get$ref()); - if (importMappings.containsKey(simpleRef)) { - LOGGER.debug("Schema unaliasing of {} omitted because aliased class is to be mapped to {}", simpleRef, importMappings.get(simpleRef)); + if (schemaMappings.containsKey(simpleRef)) { + LOGGER.debug("Schema unaliasing of {} omitted because aliased class is to be mapped to {}", simpleRef, schemaMappings.get(simpleRef)); return schema; } Schema ref = allSchemas.get(simpleRef); @@ -1222,7 +1222,7 @@ public class ModelUtils { return schema; // generate a model extending array } else { return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), - importMappings); + schemaMappings); } } else if (isComposedSchema(ref)) { return schema; @@ -1235,7 +1235,7 @@ public class ModelUtils { } else { // treat it as a typical map return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), - importMappings); + schemaMappings); } } } else if (isObjectSchema(ref)) { // model @@ -1250,10 +1250,10 @@ public class ModelUtils { } } else { // free form object (type: object) return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), - importMappings); + schemaMappings); } } else { - return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), importMappings); + return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), schemaMappings); } } return schema; diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index 29c7066193d7..4005601df8b5 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -2120,6 +2120,21 @@ public class DefaultCodegenTest { CodegenModel codegenModel = codegen.fromModel("ParentType", openAPI.getComponents().getSchemas().get("ParentType")); + Assert.assertEquals(codegenModel.vars.size(), 1); + Assert.assertEquals(codegenModel.vars.get(0).getBaseType(), "string"); + } + + @Test + public void schemaMapping() { + DefaultCodegen codegen = new DefaultCodegen(); + codegen.schemaMapping.put("TypeAlias", "foo.bar.TypeAlias"); + + OpenAPI openAPI = new OpenAPIParser() + .readLocation("src/test/resources/3_0/type-alias.yaml", null, new ParseOptions()).getOpenAPI(); + codegen.setOpenAPI(openAPI); + + CodegenModel codegenModel = codegen.fromModel("ParentType", openAPI.getComponents().getSchemas().get("ParentType")); + Assert.assertEquals(codegenModel.vars.size(), 1); Assert.assertEquals(codegenModel.vars.get(0).getBaseType(), "TypeAlias"); } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java index d3e45b52fcf2..64b6c1cf383d 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/AbstractJavaCodegenTest.java @@ -674,13 +674,13 @@ public class AbstractJavaCodegenTest { } @Test - public void getTypeDeclarationGivenImportMappingTest() { + public void getTypeDeclarationGivenSchemaMappingTest() { final P_AbstractJavaCodegen codegen = new P_AbstractJavaCodegen(); - codegen.importMapping().put("MyStringType", "com.example.foo"); + codegen.schemaMapping().put("MyStringType", "com.example.foo"); codegen.setOpenAPI(new OpenAPI().components(new Components().addSchemas("MyStringType", new StringSchema()))); Schema schema = new ArraySchema().items(new Schema().$ref("#/components/schemas/MyStringType")); String defaultValue = codegen.getTypeDeclaration(schema); - Assert.assertEquals(defaultValue, "List"); + Assert.assertEquals(defaultValue, "List"); } @Test diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java index caec1aaf00b2..71ba4734ddb7 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java @@ -652,13 +652,13 @@ public class JavaClientCodegenTest { * See https://github.com/OpenAPITools/openapi-generator/issues/3589 */ @Test - public void testImportMapping() throws IOException { + public void testSchemaMapping() throws IOException { Map properties = new HashMap<>(); properties.put(CodegenConstants.API_PACKAGE, "xyz.abcdef.api"); - Map importMappings = new HashMap<>(); - importMappings.put("TypeAlias", "foo.bar.TypeAlias"); + Map schemaMappings = new HashMap<>(); + schemaMappings.put("TypeAlias", "foo.bar.TypeAlias"); File output = Files.createTempDirectory("test").toFile(); output.deleteOnExit(); @@ -667,13 +667,13 @@ public class JavaClientCodegenTest { .setGeneratorName("java") .setLibrary(JavaClientCodegen.RESTEASY) .setAdditionalProperties(properties) - .setImportMappings(importMappings) + .setSchemaMappings(schemaMappings) .setGenerateAliasAsModel(true) .setInputSpec("src/test/resources/3_0/type-alias.yaml") .setOutputDir(output.getAbsolutePath().replace("\\", "/")); final ClientOptInput clientOptInput = configurator.toClientOptInput(); - Assert.assertEquals(clientOptInput.getConfig().importMapping().get("TypeAlias"), "foo.bar.TypeAlias"); + Assert.assertEquals(clientOptInput.getConfig().schemaMapping().get("TypeAlias"), "foo.bar.TypeAlias"); DefaultGenerator generator = new DefaultGenerator(); generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true"); @@ -702,9 +702,9 @@ public class JavaClientCodegenTest { Matcher fieldMatcher = FIELD_PATTERN.matcher(parentTypeContents); Assert.assertTrue(fieldMatcher.matches()); - // this is the type of the field 'typeAlias'. With a working importMapping it should + // this is the type of the field 'typeAlias'. With a working schemaMapping it should // be 'foo.bar.TypeAlias' or just 'TypeAlias' - Assert.assertEquals(fieldMatcher.group(1), "TypeAlias"); + Assert.assertEquals(fieldMatcher.group(1), "foo.bar.TypeAlias"); } @Test diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java index d3698e7ab533..7873dff7cbe3 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/AbstractKotlinCodegenTest.java @@ -102,7 +102,14 @@ public class AbstractKotlinCodegenTest { } @Test - public void toModelNameShouldUseProvidedMapping() { + public void toModelNameShouldUseProvideSchemaMapping() { + codegen.schemaMapping().put("json_myclass", "com.test.MyClass"); + assertEquals("com.test.MyClass", codegen.toModelName("json_myclass")); + } + + @Test + public void toModelNameShouldUseProvideImportMapping() { + // TODO review this test to see if it's still needed after adding scheme mapping support codegen.importMapping().put("json_myclass", "com.test.MyClass"); assertEquals("com.test.MyClass", codegen.toModelName("json_myclass")); } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java index 6ef8d716e804..f962efee4eb4 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java @@ -221,12 +221,12 @@ public class ModelUtilsTest { public void testAliasedTypeIsNotUnaliasedIfUsedForImportMapping() { Schema emailSchema = new Schema().$ref("#/components/schemas/Email").type("string"); StringSchema stringSchema = new StringSchema(); - HashMap importMappings = new HashMap<>(); - importMappings.put("Email", "foo.bar.Email"); + HashMap schemaMappings = new HashMap<>(); + schemaMappings.put("Email", "foo.bar.Email"); OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("Email", stringSchema); - Assert.assertEquals(emailSchema, ModelUtils.unaliasSchema(openAPI, emailSchema, importMappings)); + Assert.assertEquals(emailSchema, ModelUtils.unaliasSchema(openAPI, emailSchema, schemaMappings)); Assert.assertEquals(stringSchema, ModelUtils.unaliasSchema(openAPI, emailSchema, new HashMap<>())); }