From 6e7ad13e1b327b45ce9cdafdfb6c1b46fe8b8b32 Mon Sep 17 00:00:00 2001 From: Benjamin Douglas Date: Sun, 1 Oct 2017 19:54:41 -0700 Subject: [PATCH] Pre-calculate type aliases before processing models (#6559) A type alias in this context is where a model is simply another name for a primitive type, such as `MyString` in the following model definitions: MyList: type: array items: $ref: '#/definitions/MyString' MyString: type: string It is valid to use a type alias as a property in another object or array model, even if the object/array is defined before the alias is, as in the example above. However, the current alias logic only looks "back" in list of previously defined models, meaning that `MyList` would not know that `MyString` is an alias. This change fixes the incorrect behavior by pre-calculating the list of aliases before any models are processed. It also changes the test endpoint to verify the correct behavior even when an object is defined before an alias it uses. --- .../io/swagger/codegen/DefaultCodegen.java | 36 ++++++++++++++++--- .../languages/AbstractJavaCodegen.java | 2 +- ...ith-fake-endpoints-models-for-testing.yaml | 12 +++---- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java index 63e42e82f10..6ebda3dccc5 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java @@ -119,7 +119,7 @@ public class DefaultCodegen { // Then translated back during JSON encoding and decoding protected Map specialCharReplacements = new HashMap(); // When a model is an alias for a simple type - protected Map typeAliases = new HashMap<>(); + protected Map typeAliases = null; protected String ignoreFilePathOverride; @@ -1312,6 +1312,10 @@ public class DefaultCodegen { * @return Codegen Model object */ public CodegenModel fromModel(String name, Model model, Map allDefinitions) { + if (typeAliases == null) { + // Only do this once during first call + typeAliases = getAllAliases(allDefinitions); + } CodegenModel m = CodegenModelFactory.newInstance(CodegenModelType.MODEL); if (reservedWords.contains(name)) { m.name = escapeReservedWord(name); @@ -1327,6 +1331,7 @@ public class DefaultCodegen { m.modelJson = Json.pretty(model); m.externalDocs = model.getExternalDocs(); m.vendorExtensions = model.getVendorExtensions(); + m.isAlias = typeAliases.containsKey(name); if (model instanceof ModelImpl) { ModelImpl modelImpl = (ModelImpl) model; @@ -1444,10 +1449,6 @@ public class DefaultCodegen { ModelImpl impl = (ModelImpl) model; if (impl.getType() != null) { Property p = PropertyBuilder.build(impl.getType(), impl.getFormat(), null); - if (!impl.getType().equals("object") && impl.getEnum() == null) { - typeAliases.put(name, impl.getType()); - m.isAlias = true; - } m.dataType = getSwaggerType(p); } if(impl.getEnum() != null && impl.getEnum().size() > 0) { @@ -3166,6 +3167,31 @@ public class DefaultCodegen { } } + /** + * Determine all of the types in the model definitions that are aliases of + * simple types. + * @param allDefinitions The complete set of model definitions. + * @return A mapping from model name to type alias + */ + private static Map getAllAliases(Map allDefinitions) { + Map aliases = new HashMap<>(); + if (allDefinitions != null) { + for (Map.Entry entry : allDefinitions.entrySet()) { + String swaggerName = entry.getKey(); + Model m = entry.getValue(); + if (m instanceof ModelImpl) { + ModelImpl impl = (ModelImpl) m; + if (impl.getType() != null && + !impl.getType().equals("object") && + impl.getEnum() == null) { + aliases.put(swaggerName, impl.getType()); + } + } + } + } + return aliases; + } + /** * Remove characters not suitable for variable or method name from the input and camelize it * diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java index 64460b2f5fc..a83acffcb25 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java @@ -619,7 +619,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code @Override public String getAlias(String name) { - if (typeAliases.containsKey(name)) { + if (typeAliases != null && typeAliases.containsKey(name)) { return typeAliases.get(name); } return name; diff --git a/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml index 19db9dcbf51..059a5ef4980 100644 --- a/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml +++ b/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml @@ -1402,12 +1402,6 @@ definitions: - "placed" - "approved" - "delivered" - OuterNumber: - type: number - OuterString: - type: string - OuterBoolean: - type: boolean OuterComposite: type: object properties: @@ -1417,6 +1411,12 @@ definitions: $ref: '#/definitions/OuterString' my_boolean: $ref: '#/definitions/OuterBoolean' + OuterNumber: + type: number + OuterString: + type: string + OuterBoolean: + type: boolean externalDocs: description: Find out more about Swagger url: 'http://swagger.io'