From eecd8c056a730e7043c75c12dfe5810c087ad126 Mon Sep 17 00:00:00 2001 From: Peter Steiner Date: Thu, 13 Feb 2020 15:05:53 +0100 Subject: [PATCH] Java importmapping 3589 (#4350) * type aliasing issue * Add example OpenAPI document from issue 3589 https://github.com/OpenAPITools/openapi-generator/issues/3589 * Add test to reproduce the issue - type of TypeAlias changed from 'string' to 'object' (not sure if importMapping is supposed also for 'string' types...) - there might be better ways to write the test, it's kind of a brute force test (generate a file and parse it with a regexp) * Remove duplicate test file * Add new method override handleMethodResponse Fixes broken unit test after merge from master Co-authored-by: bkoziak Co-authored-by: William Cheng --- .../codegen/plugin/CodeGenMojo.java | 3 +- .../openapitools/codegen/DefaultCodegen.java | 58 ++++++++---- .../languages/CppRestSdkClientCodegen.java | 2 +- .../PythonClientExperimentalCodegen.java | 22 ++++- .../TypeScriptNodeClientCodegen.java | 11 ++- .../codegen/utils/ModelUtils.java | 38 ++++++-- .../codegen/DefaultCodegenTest.java | 15 +++ .../codegen/java/JavaClientCodegenTest.java | 92 ++++++++++++------- .../codegen/utils/ModelUtilsTest.java | 15 ++- .../src/test/resources/3_0/type-alias.yaml | 26 ++++++ 10 files changed, 220 insertions(+), 62 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/3_0/type-alias.yaml 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 c0445b32d85..8e17356e460 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 @@ -641,7 +641,7 @@ public class CodeGenMojo extends AbstractMojo { configurator); } - // Retained for backwards-compataibility with configOptions -> import-mappings + // Retained for backwards-compatibility with configOptions -> import-mappings if (importMappings == null && configOptions.containsKey("import-mappings")) { applyImportMappingsKvp(configOptions.get("import-mappings").toString(), configurator); @@ -869,6 +869,7 @@ public class CodeGenMojo extends AbstractMojo { } } } + /** * This method enables conversion of true/false strings in * config.additionalProperties (configuration/configOptions) to proper booleans. 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 5a98f1da2aa..41fef60a4cc 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 @@ -1798,12 +1798,15 @@ public class DefaultCodegen implements CodegenConfig { * @return the string representation of the schema type. */ private String getSingleSchemaType(Schema schema) { - Schema unaliasSchema = ModelUtils.unaliasSchema(this.openAPI, schema); + Schema unaliasSchema = ModelUtils.unaliasSchema(this.openAPI, schema, importMapping); 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)) { + return schemaName; + } return getAlias(schemaName); } else { LOGGER.warn("Error obtaining the datatype from ref:" + unaliasSchema.get$ref() + ". Default to 'object'"); @@ -1903,7 +1906,6 @@ public class DefaultCodegen implements CodegenConfig { return (name.length() > 0) ? (Character.toLowerCase(name.charAt(0)) + name.substring(1)) : ""; } - /** * Output the type declaration of a given name * @@ -2021,7 +2023,7 @@ public class DefaultCodegen implements CodegenConfig { } // unalias schema - schema = ModelUtils.unaliasSchema(this.openAPI, schema); + schema = ModelUtils.unaliasSchema(this.openAPI, schema, importMapping); if (schema == null) { LOGGER.warn("Schema {} not found", name); return null; @@ -2372,7 +2374,7 @@ public class DefaultCodegen implements CodegenConfig { LOGGER.debug("debugging fromProperty for " + name + " : " + p); // unalias schema - p = ModelUtils.unaliasSchema(this.openAPI, p); + p = ModelUtils.unaliasSchema(this.openAPI, p, importMapping); CodegenProperty property = CodegenModelFactory.newInstance(CodegenModelType.PROPERTY); @@ -2526,12 +2528,13 @@ public class DefaultCodegen implements CodegenConfig { } else if (ModelUtils.isArraySchema(p)) { // default to string if inner item is undefined ArraySchema arraySchema = (ArraySchema) p; - Schema innerSchema = ModelUtils.unaliasSchema(this.openAPI, getSchemaItems(arraySchema)); + Schema innerSchema = ModelUtils.unaliasSchema(this.openAPI, getSchemaItems(arraySchema), importMapping); if (arraySchema.getItems() == null) { arraySchema.setItems(innerSchema); } } else if (ModelUtils.isMapSchema(p)) { - Schema innerSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getAdditionalProperties(p)); + Schema innerSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getAdditionalProperties(p), + importMapping); 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"); @@ -2607,7 +2610,7 @@ public class DefaultCodegen implements CodegenConfig { itemName = property.name; } ArraySchema arraySchema = (ArraySchema) p; - Schema innerSchema = ModelUtils.unaliasSchema(this.openAPI, getSchemaItems(arraySchema)); + Schema innerSchema = ModelUtils.unaliasSchema(this.openAPI, getSchemaItems(arraySchema), importMapping); if (arraySchema.getItems() == null) { arraySchema.setItems(innerSchema); } @@ -2622,7 +2625,8 @@ public class DefaultCodegen implements CodegenConfig { property.maxItems = p.getMaxProperties(); // handle inner property - Schema innerSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getAdditionalProperties(p)); + Schema innerSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getAdditionalProperties(p), + importMapping); 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"); @@ -2841,7 +2845,24 @@ public class DefaultCodegen implements CodegenConfig { Map schemas, CodegenOperation op, ApiResponse methodResponse) { - Schema responseSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getSchemaFromResponse(methodResponse)); + handleMethodResponse(operation, schemas, op, methodResponse, Collections.emptyMap()); + } + + /** + * Set op's returnBaseType, returnType, examples etc. + * + * @param operation endpoint Operation + * @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 + */ + protected void handleMethodResponse(Operation operation, + Map schemas, + CodegenOperation op, + ApiResponse methodResponse, + Map importMappings) { + Schema responseSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getSchemaFromResponse(methodResponse), importMappings); if (responseSchema != null) { CodegenProperty cm = fromProperty("response", responseSchema); @@ -2996,7 +3017,7 @@ public class DefaultCodegen implements CodegenConfig { op.responses.get(op.responses.size() - 1).hasMore = false; if (methodResponse != null) { - handleMethodResponse(operation, schemas, op, methodResponse); + handleMethodResponse(operation, schemas, op, methodResponse, importMapping); } } @@ -3130,9 +3151,12 @@ public class DefaultCodegen implements CodegenConfig { Collections.sort(allParams, new Comparator() { @Override public int compare(CodegenParameter one, CodegenParameter another) { - if (one.required == another.required) return 0; - else if (one.required) return -1; - else return 1; + if (one.required == another.required) + return 0; + else if (one.required) + return -1; + else + return 1; } }); } @@ -3211,7 +3235,8 @@ public class DefaultCodegen implements CodegenConfig { } Schema responseSchema; if (this.openAPI != null && this.openAPI.getComponents() != null) { - responseSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getSchemaFromResponse(response)); + responseSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getSchemaFromResponse(response), + importMapping); } else { // no model/alias defined responseSchema = ModelUtils.getSchemaFromResponse(response); } @@ -3443,7 +3468,7 @@ public class DefaultCodegen implements CodegenConfig { } if (s != null) { - Schema parameterSchema = ModelUtils.unaliasSchema(this.openAPI, s); + Schema parameterSchema = ModelUtils.unaliasSchema(this.openAPI, s, importMapping); if (parameterSchema == null) { LOGGER.warn("warning! Schema not found for parameter \"" + parameter.getName() + "\", using String"); parameterSchema = new StringSchema().description("//TODO automatically added by openapi-generator due to missing type definition."); @@ -4047,7 +4072,7 @@ public class DefaultCodegen implements CodegenConfig { private Map unaliasPropertySchema(Map properties) { if (properties != null) { for (String key : properties.keySet()) { - properties.put(key, ModelUtils.unaliasSchema(this.openAPI, properties.get(key))); + properties.put(key, ModelUtils.unaliasSchema(this.openAPI, properties.get(key), importMapping())); } } @@ -5422,7 +5447,6 @@ public class DefaultCodegen implements CodegenConfig { codegenParameter.maxLength = codegenProperty.maxLength; codegenParameter.pattern = codegenProperty.pattern; - if (codegenProperty.complexType != null) { imports.add(codegenProperty.complexType); } 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 8058932f911..cd9aa946d20 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 @@ -261,7 +261,7 @@ public class CppRestSdkClientCodegen extends AbstractCppCodegen { if (methodResponse != null) { Schema response = ModelUtils.getSchemaFromResponse(methodResponse); - response = ModelUtils.unaliasSchema(this.openAPI, response); + response = ModelUtils.unaliasSchema(this.openAPI, response, importMapping); 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/PythonClientExperimentalCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientExperimentalCodegen.java index 2569ec2529f..a9c57e3f07a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientExperimentalCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientExperimentalCodegen.java @@ -529,7 +529,7 @@ public class PythonClientExperimentalCodegen extends PythonClientCodegen { // When we serialize/deserialize ModelSimple models, validations and enums will be checked. Schema responseSchema; if (this.openAPI != null && this.openAPI.getComponents() != null) { - responseSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getSchemaFromResponse(response)); + responseSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getSchemaFromResponse(response), importMapping); } else { // no model/alias defined responseSchema = ModelUtils.getSchemaFromResponse(response); } @@ -582,12 +582,30 @@ public class PythonClientExperimentalCodegen extends PythonClientCodegen { Map schemas, CodegenOperation op, ApiResponse methodResponse) { + handleMethodResponse(operation, schemas, op, methodResponse, Collections.emptyMap()); + } + + /** + * Set op's returnBaseType, returnType, examples etc. + * + * @param operation endpoint Operation + * @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 + */ + @Override + protected void handleMethodResponse(Operation operation, + Map schemas, + CodegenOperation op, + ApiResponse methodResponse, + Map importMappings) { // we have a custom version of this method to handle endpoints that return models where // type != object the model has validations and/or enums // we do this by invoking our custom fromResponse method to create defaultResponse // which we then use to set op.returnType and op.returnBaseType CodegenResponse defaultResponse = fromResponse("defaultResponse", methodResponse); - Schema responseSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getSchemaFromResponse(methodResponse)); + Schema responseSchema = ModelUtils.unaliasSchema(this.openAPI, ModelUtils.getSchemaFromResponse(methodResponse), importMappings); if (responseSchema != null) { op.returnBaseType = defaultResponse.baseType; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java index 499fb0f309b..a56ae5ce7c9 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java @@ -101,7 +101,16 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen @Override protected void handleMethodResponse(Operation operation, Map schemas, CodegenOperation op, ApiResponse methodResponse) { - super.handleMethodResponse(operation, schemas, op, methodResponse); + handleMethodResponse(operation, schemas, op, methodResponse, Collections.emptyMap()); + } + + @Override + protected void handleMethodResponse(Operation operation, + Map schemas, + CodegenOperation op, + ApiResponse methodResponse, + Map importMappings) { + super.handleMethodResponse(operation, schemas, op, methodResponse, importMappings); // see comment in getTypeDeclaration if (op.isResponseFile) { 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 27aa602df08..9ed6afb54b7 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 @@ -47,6 +47,7 @@ public class ModelUtils { private static final String URI_FORMAT = "uri"; private static final String generateAliasAsModelKey = "generateAliasAsModel"; + public static void setGenerateAliasAsModel(boolean value) { GlobalSettings.setProperty(generateAliasAsModelKey, Boolean.toString(value)); } @@ -240,7 +241,7 @@ public class ModelUtils { } private static void visitParameters(OpenAPI openAPI, List parameters, OpenAPISchemaVisitor visitor, - List visitedSchemas) { + List visitedSchemas) { if (parameters != null) { for (Parameter p : parameters) { Parameter parameter = getReferencedParameter(openAPI, p); @@ -870,7 +871,22 @@ public class ModelUtils { * @param schema schema (alias or direct reference) * @return actual schema */ - public static Schema unaliasSchema(OpenAPI openAPI, Schema schema) { + public static Schema unaliasSchema(OpenAPI openAPI, + Schema schema) { + return unaliasSchema(openAPI, schema, Collections.emptyMap()); + } + + /** + * Get the actual schema from aliases. If the provided schema is not an alias, the schema itself will be returned. + * + * @param openAPI specification being checked + * @param schema schema (alias or direct reference) + * @param importMappings mappings of external types to be omitted by unaliasing + * @return actual schema + */ + public static Schema unaliasSchema(OpenAPI openAPI, + Schema schema, + Map importMappings) { Map allSchemas = getSchemas(openAPI); if (allSchemas == null || allSchemas.isEmpty()) { // skip the warning as the spec can have no model defined @@ -879,7 +895,12 @@ public class ModelUtils { } if (schema != null && StringUtils.isNotEmpty(schema.get$ref())) { - Schema ref = allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())); + String simpleRef = ModelUtils.getSimpleRef(schema.get$ref()); + if (importMappings.containsKey(simpleRef)) { + LOGGER.info("Schema unaliasing of {} omitted because aliased class is to be mapped to {}", simpleRef, importMappings.get(simpleRef)); + return schema; + } + Schema ref = allSchemas.get(simpleRef); if (ref == null) { once(LOGGER).warn("{} is not defined", schema.get$ref()); return schema; @@ -890,7 +911,8 @@ public class ModelUtils { if (isGenerateAliasAsModel()) { return schema; // generate a model extending array } else { - return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref()))); + return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), + importMappings); } } else if (isComposedSchema(ref)) { return schema; @@ -902,17 +924,19 @@ public class ModelUtils { return schema; // generate a model extending map } else { // treat it as a typical map - return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref()))); + return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), + importMappings); } } } else if (isObjectSchema(ref)) { // model if (ref.getProperties() != null && !ref.getProperties().isEmpty()) { // has at least one property return schema; } else { // free form object (type: object) - return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref()))); + return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), + importMappings); } } else { - return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref()))); + return unaliasSchema(openAPI, allSchemas.get(ModelUtils.getSimpleRef(schema.get$ref())), importMappings); } } 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 c2dc650ed86..d2118046372 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 @@ -1073,6 +1073,21 @@ public class DefaultCodegenTest { Assert.assertEquals(codegenModel.vars.size(), 1); } + @Test + public void importMapping() { + DefaultCodegen codegen = new DefaultCodegen(); + codegen.importMapping.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"); + } + @Test public void modelWithPrefixDoNotContainInheritedVars() { DefaultCodegen codegen = new DefaultCodegen(); 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 bfddd681abd..5afe39ea454 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 @@ -17,38 +17,16 @@ package org.openapitools.codegen.java; -import static org.openapitools.codegen.TestUtils.validateJavaSourceFiles; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - import com.google.common.collect.ImmutableMap; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; -import io.swagger.v3.oas.models.media.ArraySchema; -import io.swagger.v3.oas.models.media.ComposedSchema; -import io.swagger.v3.oas.models.media.Content; -import io.swagger.v3.oas.models.media.IntegerSchema; -import io.swagger.v3.oas.models.media.MediaType; -import io.swagger.v3.oas.models.media.ObjectSchema; -import io.swagger.v3.oas.models.media.Schema; -import io.swagger.v3.oas.models.media.StringSchema; +import io.swagger.v3.oas.models.media.*; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.parser.util.SchemaTypeUtil; - -import org.openapitools.codegen.ClientOptInput; -import org.openapitools.codegen.CodegenConstants; -import org.openapitools.codegen.CodegenModel; -import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.CodegenParameter; -import org.openapitools.codegen.CodegenProperty; -import org.openapitools.codegen.CodegenResponse; -import org.openapitools.codegen.CodegenSecurity; -import org.openapitools.codegen.DefaultGenerator; -import org.openapitools.codegen.MockDefaultGenerator; +import org.openapitools.codegen.*; import org.openapitools.codegen.MockDefaultGenerator.WrittenTemplateBasedFile; -import org.openapitools.codegen.TestUtils; import org.openapitools.codegen.config.CodegenConfigurator; import org.openapitools.codegen.languages.AbstractJavaCodegen; import org.openapitools.codegen.languages.JavaClientCodegen; @@ -56,16 +34,17 @@ import org.testng.Assert; import org.testng.annotations.Test; import java.io.File; +import java.io.IOException; import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.openapitools.codegen.TestUtils.validateJavaSourceFiles; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + public class JavaClientCodegenTest { @Test @@ -544,11 +523,60 @@ public class JavaClientCodegenTest { Assert.assertEquals(cm.getClassname(), "OtherObj"); } + /** + * See https://github.com/OpenAPITools/openapi-generator/issues/3589 + */ + @Test + public void testImportMapping() throws IOException { + + Map properties = new HashMap<>(); + properties.put(JavaClientCodegen.JAVA8_MODE, true); + properties.put(CodegenConstants.API_PACKAGE, "xyz.abcdef.api"); + + Map importMappings = new HashMap<>(); + importMappings.put("TypeAlias", "foo.bar.TypeAlias"); + + File output = Files.createTempDirectory("test").toFile(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("java") + .setLibrary(JavaClientCodegen.RESTEASY) + .setAdditionalProperties(properties) + .setImportMappings(importMappings) + .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"); + + MockDefaultGenerator generator = new MockDefaultGenerator(); + generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true"); + generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false"); + generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false"); + generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "false"); + generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false"); + generator.opts(clientOptInput).generate(); + + Map generatedFiles = generator.getFiles(); + Assert.assertEquals(generatedFiles.size(), 1); + TestUtils.ensureContainsFile(generatedFiles, output, "src/main/java/org/openapitools/client/model/ParentType.java"); + + final String parentTypeContents = generatedFiles.values().iterator().next(); + + final Pattern FIELD_PATTERN = Pattern.compile(".* private (.*?) typeAlias;.*", Pattern.DOTALL); + Matcher fieldMatcher = FIELD_PATTERN.matcher(parentTypeContents); + Assert.assertTrue(fieldMatcher.matches()); + + // this is the type of the field 'typeAlias'. With a working importMapping it should + // be 'foo.bar.TypeAlias' or just 'TypeAlias' + Assert.assertEquals(fieldMatcher.group(1), "foo.bar.TypeAlias"); + } + @Test public void testBearerAuth() { final OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/pingBearerAuth.yaml"); JavaClientCodegen codegen = new JavaClientCodegen(); - + List security = codegen.fromSecurity(openAPI.getComponents().getSecuritySchemes()); Assert.assertEquals(security.size(), 1); Assert.assertEquals(security.get(0).isBasic, Boolean.TRUE); 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 f1c5366d77a..b51dc54a3ef 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 @@ -205,7 +205,20 @@ public class ModelUtilsTest { OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("SomeComposedSchema", composedSchema); - Assert.assertEquals(refToComposedSchema, ModelUtils.unaliasSchema(openAPI, refToComposedSchema)); + Assert.assertEquals(refToComposedSchema, ModelUtils.unaliasSchema(openAPI, refToComposedSchema, new HashMap<>())); + } + + @Test + 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"); + + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("Email", stringSchema); + + Assert.assertEquals(emailSchema, ModelUtils.unaliasSchema(openAPI, emailSchema, importMappings)); + Assert.assertEquals(stringSchema, ModelUtils.unaliasSchema(openAPI, emailSchema, new HashMap<>())); } /** diff --git a/modules/openapi-generator/src/test/resources/3_0/type-alias.yaml b/modules/openapi-generator/src/test/resources/3_0/type-alias.yaml new file mode 100644 index 00000000000..5ae62c68bc9 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/type-alias.yaml @@ -0,0 +1,26 @@ +openapi: 3.0.0 +info: + title: API using a typeAlias mapped with importMapping + description: See https://github.com/OpenAPITools/openapi-generator/issues/3589 + version: 1.0.0 +paths: + /type-alias: + get: + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ParentType' + +components: + schemas: + ParentType: + title: ParentType + type: object + properties: + typeAlias: + $ref: '#/components/schemas/TypeAlias' + TypeAlias: + type: string \ No newline at end of file