From 28e92f9e32987905a390a205f36a6e14d37c6a8d Mon Sep 17 00:00:00 2001 From: Justin Black Date: Tue, 20 Oct 2020 12:19:13 -0700 Subject: [PATCH] Adds additionalProperties to core schema classes (#7761) * Implements additionalProperties in CodegenParameter * Implements additionalProperties in CodegenProperty * Adds additionalProperties to CodegenModel * Adds additionalProperties to CodegenResponse * Adds additionalProperties examples for CodegenModel and CodegenProperty * Adds test cases for CodegenParameter and CodegenResponse * Adds testAdditionalPropertiesPresentInModelProperties * Adds testAdditionalPropertiesPresentInResponses * Adds underscore name for additionalProperties property, needed for CppTizenClientCodegen * Changes prop name back to empty string, fixes CppTizenClientCodegen --- .../openapitools/codegen/CodegenModel.java | 13 +- .../codegen/CodegenParameter.java | 14 +- .../openapitools/codegen/CodegenProperty.java | 17 +- .../openapitools/codegen/CodegenResponse.java | 13 +- .../openapitools/codegen/DefaultCodegen.java | 60 +++++++ .../IJsonSchemaValidationProperties.java | 4 + .../languages/CppTizenClientCodegen.java | 5 +- .../codegen/DefaultCodegenTest.java | 162 ++++++++++++++++++ .../src/test/resources/3_0/issue_7613.yaml | 148 ++++++++++++++++ 9 files changed, 431 insertions(+), 5 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenModel.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenModel.java index dfd9f1a470e..624bdf6f76b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenModel.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenModel.java @@ -150,6 +150,7 @@ public class CodegenModel implements IJsonSchemaValidationProperties { private String pattern; private Number multipleOf; private CodegenProperty items; + private CodegenProperty additionalProperties; private boolean isModel; public String getAdditionalPropertiesType() { @@ -602,6 +603,14 @@ public class CodegenModel implements IJsonSchemaValidationProperties { this.isArray = isArray; } + @Override + public CodegenProperty getAdditionalProperties() { return additionalProperties; } + + @Override + public void setAdditionalProperties(CodegenProperty additionalProperties) { + this.additionalProperties = additionalProperties; + } + // indicates if the model component has validation on the root level schema // this will be true when minItems or minProperties is set public boolean hasValidation() { @@ -769,6 +778,7 @@ public class CodegenModel implements IJsonSchemaValidationProperties { Objects.equals(getMaximum(), that.getMaximum()) && Objects.equals(getPattern(), that.getPattern()) && Objects.equals(getItems(), that.getItems()) && + Objects.equals(getAdditionalProperties(), that.getAdditionalProperties()) && Objects.equals(getIsModel(), that.getIsModel()) && Objects.equals(getMultipleOf(), that.getMultipleOf()); } @@ -787,7 +797,7 @@ public class CodegenModel implements IJsonSchemaValidationProperties { hasChildren, isMap, isDeprecated, hasOnlyReadOnly, getExternalDocumentation(), getVendorExtensions(), getAdditionalPropertiesType(), getMaxProperties(), getMinProperties(), getUniqueItems(), getMaxItems(), getMinItems(), getMaxLength(), getMinLength(), getExclusiveMinimum(), getExclusiveMaximum(), getMinimum(), - getMaximum(), getPattern(), getMultipleOf(), getItems(), getIsModel()); + getMaximum(), getPattern(), getMultipleOf(), getItems(), getAdditionalProperties(), getIsModel()); } @Override @@ -869,6 +879,7 @@ public class CodegenModel implements IJsonSchemaValidationProperties { sb.append(", pattern='").append(pattern).append('\''); sb.append(", multipleOf='").append(multipleOf).append('\''); sb.append(", items='").append(items).append('\''); + sb.append(", additionalProperties='").append(additionalProperties).append('\''); sb.append(", isModel='").append(isModel).append('\''); sb.append('}'); return sb.toString(); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenParameter.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenParameter.java index f7a7c92c364..61fa928c20e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenParameter.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenParameter.java @@ -42,6 +42,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties { public List _enum; public Map allowableValues; public CodegenProperty items; + public CodegenProperty additionalProperties; public CodegenProperty mostInnerItems; public Map vendorExtensions = new HashMap(); public boolean hasValidation; @@ -145,6 +146,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties { output.maximum = this.maximum; output.minimum = this.minimum; output.pattern = this.pattern; + output.additionalProperties = this.additionalProperties; if (this._enum != null) { output._enum = new ArrayList(this._enum); @@ -191,7 +193,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties { @Override public int hashCode() { - return Objects.hash(isFormParam, isQueryParam, isPathParam, isHeaderParam, isCookieParam, isBodyParam, hasMore, isContainer, secondaryParam, isCollectionFormatMulti, isPrimitiveType, isModel, isExplode, baseName, paramName, dataType, datatypeWithEnum, dataFormat, collectionFormat, description, unescapedDescription, baseType, defaultValue, enumName, style, example, jsonSchema, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isFreeFormObject, isAnyType, isArray, isMap, isFile, isEnum, _enum, allowableValues, items, mostInnerItems, vendorExtensions, hasValidation, getMaxProperties(), getMinProperties(), isNullable, required, getMaximum(), getExclusiveMaximum(), getMinimum(), getExclusiveMinimum(), getMaxLength(), getMinLength(), getPattern(), getMaxItems(), getMinItems(), getUniqueItems(), contentType, multipleOf); + return Objects.hash(isFormParam, isQueryParam, isPathParam, isHeaderParam, isCookieParam, isBodyParam, hasMore, isContainer, secondaryParam, isCollectionFormatMulti, isPrimitiveType, isModel, isExplode, baseName, paramName, dataType, datatypeWithEnum, dataFormat, collectionFormat, description, unescapedDescription, baseType, defaultValue, enumName, style, example, jsonSchema, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isFreeFormObject, isAnyType, isArray, isMap, isFile, isEnum, _enum, allowableValues, items, mostInnerItems, additionalProperties, vendorExtensions, hasValidation, getMaxProperties(), getMinProperties(), isNullable, required, getMaximum(), getExclusiveMaximum(), getMinimum(), getExclusiveMinimum(), getMaxLength(), getMinLength(), getPattern(), getMaxItems(), getMinItems(), getUniqueItems(), contentType, multipleOf); } @Override @@ -256,6 +258,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties { Objects.equals(_enum, that._enum) && Objects.equals(allowableValues, that.allowableValues) && Objects.equals(items, that.items) && + Objects.equals(additionalProperties, that.additionalProperties) && Objects.equals(mostInnerItems, that.mostInnerItems) && Objects.equals(vendorExtensions, that.vendorExtensions) && Objects.equals(getMaxProperties(), that.getMaxProperties()) && @@ -326,6 +329,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties { sb.append(", allowableValues=").append(allowableValues); sb.append(", items=").append(items); sb.append(", mostInnerItems=").append(mostInnerItems); + sb.append(", additionalProperties=").append(additionalProperties); sb.append(", vendorExtensions=").append(vendorExtensions); sb.append(", hasValidation=").append(hasValidation); sb.append(", maxProperties=").append(maxProperties); @@ -527,5 +531,13 @@ public class CodegenParameter implements IJsonSchemaValidationProperties { public void setIsArray(boolean isArray) { this.isArray = isArray; } + + @Override + public CodegenProperty getAdditionalProperties() { return additionalProperties; } + + @Override + public void setAdditionalProperties(CodegenProperty additionalProperties) { + this.additionalProperties = additionalProperties; + } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java index e37e1147229..efabd68731b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java @@ -159,6 +159,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti // If 'additionalProperties' is set to a type or refers to a type, 'items' provides the type information for // the undeclared properties. public CodegenProperty items; + public CodegenProperty additionalProperties; public CodegenProperty mostInnerItems; public Map vendorExtensions = new HashMap(); public boolean hasValidation; // true if pattern, maximum, etc are set (only used in the mustache template) @@ -461,6 +462,14 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti this.items = items; } + @Override + public CodegenProperty getAdditionalProperties() { return additionalProperties; } + + @Override + public void setAdditionalProperties(CodegenProperty additionalProperties) { + this.additionalProperties = additionalProperties; + } + @Override public boolean getIsModel() { return isModel; } @@ -594,6 +603,9 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti if (this.items != null) { cp.items = this.items; } + if (this.additionalProperties != null) { + cp.additionalProperties = this.additionalProperties; + } if (this.mostInnerItems != null) { cp.mostInnerItems = this.mostInnerItems; } @@ -712,6 +724,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti sb.append(", _enum=").append(_enum); sb.append(", allowableValues=").append(allowableValues); sb.append(", items=").append(items); + sb.append(", additionalProperties=").append(additionalProperties); sb.append(", mostInnerItems=").append(mostInnerItems); sb.append(", vendorExtensions=").append(vendorExtensions); sb.append(", hasValidation=").append(hasValidation); @@ -808,6 +821,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti Objects.equals(_enum, that._enum) && Objects.equals(allowableValues, that.allowableValues) && Objects.equals(items, that.items) && + Objects.equals(additionalProperties, that.additionalProperties) && Objects.equals(mostInnerItems, that.mostInnerItems) && Objects.equals(vendorExtensions, that.vendorExtensions) && Objects.equals(discriminatorValue, that.discriminatorValue) && @@ -834,7 +848,8 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBinary, isFile, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isFreeFormObject, isArray, isMap, isEnum, isReadOnly, isWriteOnly, isNullable, - isSelfReference, isCircularReference, isDiscriminator, _enum, allowableValues, items, mostInnerItems, + isSelfReference, isCircularReference, isDiscriminator, _enum, allowableValues, + items, mostInnerItems, additionalProperties, vendorExtensions, hasValidation, isInherited, discriminatorValue, nameInCamelCase, nameInSnakeCase, enumName, maxItems, minItems, isXmlAttribute, xmlPrefix, xmlName, xmlNamespace, isXmlWrapped); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenResponse.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenResponse.java index cc8397e95a8..b0e79592c00 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenResponse.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenResponse.java @@ -74,13 +74,14 @@ public class CodegenResponse implements IJsonSchemaValidationProperties { public String pattern; public Number multipleOf; public CodegenProperty items; + public CodegenProperty additionalProperties; @Override public int hashCode() { return Objects.hash(headers, code, message, hasMore, examples, dataType, baseType, containerType, hasHeaders, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBoolean, isDate, isDateTime, isUuid, isEmail, isModel, isFreeFormObject, isAnyType, isDefault, simpleType, primitiveType, - isMap, isArray, isBinary, isFile, schema, jsonSchema, vendorExtensions, items, + isMap, isArray, isBinary, isFile, schema, jsonSchema, vendorExtensions, items, additionalProperties, getMaxProperties(), getMinProperties(), uniqueItems, getMaxItems(), getMinItems(), getMaxLength(), getMinLength(), exclusiveMinimum, exclusiveMaximum, getMinimum(), getMaximum(), getPattern()); } @@ -116,6 +117,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties { isBinary == that.isBinary && isFile == that.isFile && items == that.items && + additionalProperties == that.additionalProperties && Objects.equals(headers, that.headers) && Objects.equals(code, that.code) && Objects.equals(message, that.message) && @@ -322,6 +324,14 @@ public class CodegenResponse implements IJsonSchemaValidationProperties { this.isMap = isMap; } + @Override + public CodegenProperty getAdditionalProperties() { return additionalProperties; } + + @Override + public void setAdditionalProperties(CodegenProperty additionalProperties) { + this.additionalProperties = additionalProperties; + } + @Override public String toString() { final StringBuilder sb = new StringBuilder("CodegenResponse{"); @@ -374,6 +384,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties { sb.append(", pattern='").append(pattern).append('\''); sb.append(", multipleOf='").append(multipleOf).append('\''); sb.append(", items='").append(items).append('\''); + sb.append(", additionalProperties='").append(additionalProperties).append('\''); sb.append('}'); return sb.toString(); } 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 ebec1118c14..97feb4238ad 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 @@ -2598,15 +2598,21 @@ public class DefaultCodegen implements CodegenConfig { m.isAdditionalPropertiesTrue = false; } else { m.isAdditionalPropertiesTrue = true; + CodegenProperty cp = fromProperty("", new Schema()); + m.setAdditionalProperties(cp); } } else if (schema.getAdditionalProperties() instanceof Boolean) { if (Boolean.TRUE.equals(schema.getAdditionalProperties())) { m.isAdditionalPropertiesTrue = true; + CodegenProperty cp = fromProperty("", new Schema()); + m.setAdditionalProperties(cp); } else { m.isAdditionalPropertiesTrue = false; } } else { m.isAdditionalPropertiesTrue = false; + CodegenProperty cp = fromProperty("", (Schema) schema.getAdditionalProperties()); + m.setAdditionalProperties(cp); } // post process model properties @@ -3366,6 +3372,24 @@ public class DefaultCodegen implements CodegenConfig { property.isModel = (ModelUtils.isComposedSchema(refOrCurrent) || ModelUtils.isObjectSchema(refOrCurrent)) && ModelUtils.isModel(refOrCurrent); } + // process 'additionalProperties' + if ("object".equals(p.getType())) { + if (p.getAdditionalProperties() == null) { + if (!disallowAdditionalPropertiesIfNotPresent) { + CodegenProperty cp = fromProperty("", new Schema()); + property.setAdditionalProperties(cp); + } + } else if (p.getAdditionalProperties() instanceof Boolean) { + if (Boolean.TRUE.equals(p.getAdditionalProperties())) { + CodegenProperty cp = fromProperty("", new Schema()); + property.setAdditionalProperties(cp); + } + } else { + CodegenProperty cp = fromProperty("", (Schema) p.getAdditionalProperties()); + property.setAdditionalProperties(cp); + } + } + LOGGER.debug("debugging from property return: " + property); schemaCodegenPropertyCache.put(ns, property); return property; @@ -4090,6 +4114,24 @@ public class DefaultCodegen implements CodegenConfig { } r.primitiveType = (r.baseType == null || languageSpecificPrimitives().contains(r.baseType)); + + // process 'additionalProperties' + if ("object".equals(responseSchema.getType())) { + if (responseSchema.getAdditionalProperties() == null) { + if (!disallowAdditionalPropertiesIfNotPresent) { + CodegenProperty addPropProp = fromProperty("", new Schema()); + r.setAdditionalProperties(addPropProp); + } + } else if (responseSchema.getAdditionalProperties() instanceof Boolean) { + if (Boolean.TRUE.equals(responseSchema.getAdditionalProperties())) { + CodegenProperty addPropProp = fromProperty("", new Schema()); + r.setAdditionalProperties(addPropProp); + } + } else { + CodegenProperty addPropProp = fromProperty("", (Schema) responseSchema.getAdditionalProperties()); + r.setAdditionalProperties(addPropProp); + } + } } if (r.baseType == null) { @@ -4379,6 +4421,24 @@ public class DefaultCodegen implements CodegenConfig { codegenParameter.hasValidation = true; } + // process 'additionalProperties' + if ("object".equals(parameterSchema.getType())) { + if (parameterSchema.getAdditionalProperties() == null) { + if (!disallowAdditionalPropertiesIfNotPresent) { + CodegenProperty cp = fromProperty("", new Schema()); + codegenParameter.setAdditionalProperties(cp); + } + } else if (parameterSchema.getAdditionalProperties() instanceof Boolean) { + if (Boolean.TRUE.equals(parameterSchema.getAdditionalProperties())) { + CodegenProperty cp = fromProperty("", new Schema()); + codegenParameter.setAdditionalProperties(cp); + } + } else { + CodegenProperty cp = fromProperty("", (Schema) parameterSchema.getAdditionalProperties()); + codegenParameter.setAdditionalProperties(cp); + } + } + } else { LOGGER.error("ERROR! Not handling " + parameter + " as Body Parameter at the moment"); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/IJsonSchemaValidationProperties.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/IJsonSchemaValidationProperties.java index fe451e62471..e0ee277fd0f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/IJsonSchemaValidationProperties.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/IJsonSchemaValidationProperties.java @@ -76,4 +76,8 @@ public interface IJsonSchemaValidationProperties { boolean getIsArray(); void setIsArray(boolean isArray); + + CodegenProperty getAdditionalProperties(); + + void setAdditionalProperties(CodegenProperty additionalProperties); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppTizenClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppTizenClientCodegen.java index c0db6bec907..16bd058996f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppTizenClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppTizenClientCodegen.java @@ -288,7 +288,10 @@ public class CppTizenClientCodegen extends AbstractCppCodegen implements Codegen @Override public String toVarName(String name) { String paramName = name.replaceAll("[^a-zA-Z0-9_]", ""); - paramName = Character.toLowerCase(paramName.charAt(0)) + paramName.substring(1); + if (name.length() > 0 ) { + // additionalProperties name is "" so name.length() == 0 + paramName = Character.toLowerCase(paramName.charAt(0)) + paramName.substring(1); + } if (isReservedWord(paramName)) { return escapeReservedWord(paramName); } 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 1899afb9fc3..c100f5ce91e 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 @@ -2341,6 +2341,168 @@ public class DefaultCodegenTest { assertEquals(co.responses.get(0).getItems().getMaximum(), "7"); } + @Test + public void testAdditionalPropertiesPresentInModels() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_7613.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + codegen.setDisallowAdditionalPropertiesIfNotPresent(false); + + String modelName; + Schema sc; + CodegenModel cm; + CodegenProperty anyTypeSchema = codegen.fromProperty("", new Schema()); + + modelName = "AdditionalPropertiesUnset"; + sc = openAPI.getComponents().getSchemas().get(modelName); + cm = codegen.fromModel(modelName, sc); + assertEquals(cm.getAdditionalProperties(), anyTypeSchema); + + modelName = "AdditionalPropertiesTrue"; + sc = openAPI.getComponents().getSchemas().get(modelName); + cm = codegen.fromModel(modelName, sc); + assertEquals(cm.getAdditionalProperties(), anyTypeSchema); + + modelName = "AdditionalPropertiesFalse"; + sc = openAPI.getComponents().getSchemas().get(modelName); + cm = codegen.fromModel(modelName, sc); + assertEquals(cm.getAdditionalProperties(), null); + + modelName = "AdditionalPropertiesSchema"; + sc = openAPI.getComponents().getSchemas().get(modelName); + cm = codegen.fromModel(modelName, sc); + CodegenProperty stringCp = codegen.fromProperty("", new Schema().type("string")); + assertEquals(cm.getAdditionalProperties(), stringCp); + } + + @Test + public void testAdditionalPropertiesPresentInModelProperties() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_7613.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + codegen.setDisallowAdditionalPropertiesIfNotPresent(false); + + String modelName; + Schema sc; + CodegenModel cm; + CodegenProperty anyTypeSchema = codegen.fromProperty("", new Schema()); + CodegenProperty stringCp = codegen.fromProperty("", new Schema().type("string")); + CodegenProperty mapWithAddPropsUnset; + CodegenProperty mapWithAddPropsTrue; + CodegenProperty mapWithAddPropsFalse; + CodegenProperty mapWithAddPropsSchema; + + modelName = "ObjectModelWithRefAddPropsInProps"; + sc = openAPI.getComponents().getSchemas().get(modelName); + cm = codegen.fromModel(modelName, sc); + mapWithAddPropsUnset = cm.getVars().get(0); + assertEquals(mapWithAddPropsUnset.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsTrue = cm.getVars().get(1); + assertEquals(mapWithAddPropsTrue.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsFalse = cm.getVars().get(2); + assertEquals(mapWithAddPropsFalse.getAdditionalProperties(), null); + mapWithAddPropsSchema = cm.getVars().get(3); + assertEquals(mapWithAddPropsSchema.getAdditionalProperties(), stringCp); + + modelName = "ObjectModelWithAddPropsInProps"; + sc = openAPI.getComponents().getSchemas().get(modelName); + cm = codegen.fromModel(modelName, sc); + mapWithAddPropsUnset = cm.getVars().get(0); + assertEquals(mapWithAddPropsUnset.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsTrue = cm.getVars().get(1); + assertEquals(mapWithAddPropsTrue.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsFalse = cm.getVars().get(2); + assertEquals(mapWithAddPropsFalse.getAdditionalProperties(), null); + mapWithAddPropsSchema = cm.getVars().get(3); + assertEquals(mapWithAddPropsSchema.getAdditionalProperties(), stringCp); + } + + @Test + public void testAdditionalPropertiesPresentInParameters() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_7613.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + codegen.setDisallowAdditionalPropertiesIfNotPresent(false); + + String path; + Operation operation; + CodegenOperation co; + + CodegenProperty anyTypeSchema = codegen.fromProperty("", new Schema()); + CodegenProperty stringCp = codegen.fromProperty("", new Schema().type("string")); + CodegenParameter mapWithAddPropsUnset; + CodegenParameter mapWithAddPropsTrue; + CodegenParameter mapWithAddPropsFalse; + CodegenParameter mapWithAddPropsSchema; + + path = "/ref_additional_properties/"; + operation = openAPI.getPaths().get(path).getPost(); + co = codegen.fromOperation(path, "POST", operation, null); + mapWithAddPropsUnset = co.queryParams.get(0); + assertEquals(mapWithAddPropsUnset.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsTrue = co.queryParams.get(1); + assertEquals(mapWithAddPropsTrue.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsFalse = co.queryParams.get(2); + assertEquals(mapWithAddPropsFalse.getAdditionalProperties(), null); + mapWithAddPropsSchema = co.queryParams.get(3); + assertEquals(mapWithAddPropsSchema.getAdditionalProperties(), stringCp); + + path = "/additional_properties/"; + operation = openAPI.getPaths().get(path).getPost(); + co = codegen.fromOperation(path, "POST", operation, null); + mapWithAddPropsUnset = co.queryParams.get(0); + assertEquals(mapWithAddPropsUnset.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsTrue = co.queryParams.get(1); + assertEquals(mapWithAddPropsTrue.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsFalse = co.queryParams.get(2); + assertEquals(mapWithAddPropsFalse.getAdditionalProperties(), null); + mapWithAddPropsSchema = co.queryParams.get(3); + assertEquals(mapWithAddPropsSchema.getAdditionalProperties(), stringCp); + } + + @Test + public void testAdditionalPropertiesPresentInResponses() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_7613.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + codegen.setDisallowAdditionalPropertiesIfNotPresent(false); + + String path; + Operation operation; + CodegenOperation co; + + CodegenProperty anyTypeSchema = codegen.fromProperty("", new Schema()); + CodegenProperty stringCp = codegen.fromProperty("", new Schema().type("string")); + CodegenResponse mapWithAddPropsUnset; + CodegenResponse mapWithAddPropsTrue; + CodegenResponse mapWithAddPropsFalse; + CodegenResponse mapWithAddPropsSchema; + + path = "/ref_additional_properties/"; + operation = openAPI.getPaths().get(path).getPost(); + co = codegen.fromOperation(path, "POST", operation, null); + mapWithAddPropsUnset = co.responses.get(0); + assertEquals(mapWithAddPropsUnset.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsTrue = co.responses.get(1); + assertEquals(mapWithAddPropsTrue.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsFalse = co.responses.get(2); + assertEquals(mapWithAddPropsFalse.getAdditionalProperties(), null); + mapWithAddPropsSchema = co.responses.get(3); + assertEquals(mapWithAddPropsSchema.getAdditionalProperties(), stringCp); + + path = "/additional_properties/"; + operation = openAPI.getPaths().get(path).getPost(); + co = codegen.fromOperation(path, "POST", operation, null); + mapWithAddPropsUnset = co.responses.get(0); + assertEquals(mapWithAddPropsUnset.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsTrue = co.responses.get(1); + assertEquals(mapWithAddPropsTrue.getAdditionalProperties(), anyTypeSchema); + mapWithAddPropsFalse = co.responses.get(2); + assertEquals(mapWithAddPropsFalse.getAdditionalProperties(), null); + mapWithAddPropsSchema = co.responses.get(3); + assertEquals(mapWithAddPropsSchema.getAdditionalProperties(), stringCp); + } + @Test public void testIsXPresence() { final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_7651.yaml"); diff --git a/modules/openapi-generator/src/test/resources/3_0/issue_7613.yaml b/modules/openapi-generator/src/test/resources/3_0/issue_7613.yaml index 29f45be7444..48645fc0400 100644 --- a/modules/openapi-generator/src/test/resources/3_0/issue_7613.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/issue_7613.yaml @@ -72,6 +72,116 @@ paths: type: integer format: int64 maximum: 7 + /ref_additional_properties/: + post: + tags: + - additional_properties + operationId: arrayWithValidationsInItems + parameters: + - name: additionalPropertiesUnset + in: query + required: true + schema: + $ref: '#/components/schemas/AdditionalPropertiesUnset' + - name: additionalPropertiesTrue + in: query + required: true + schema: + $ref: '#/components/schemas/AdditionalPropertiesTrue' + - name: additionalPropertiesFalse + in: query + required: true + schema: + $ref: '#/components/schemas/AdditionalPropertiesFalse' + - name: additionalPropertiesSchema + in: query + required: true + schema: + $ref: '#/components/schemas/AdditionalPropertiesSchema' + responses: + "200": + description: "200" + content: + application/json: + schema: + $ref: '#/components/schemas/AdditionalPropertiesUnset' + "201": + description: "201" + content: + application/xml: + schema: + $ref: '#/components/schemas/AdditionalPropertiesTrue' + "202": + description: "202" + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/AdditionalPropertiesFalse' + "203": + description: "203" + content: + application/*: + schema: + $ref: '#/components/schemas/AdditionalPropertiesSchema' + /additional_properties/: + post: + tags: + - additional_properties + operationId: arrayWithValidationsInItems + parameters: + - name: additionalPropertiesUnset + in: query + required: true + schema: + type: object + - name: additionalPropertiesTrue + in: query + required: true + schema: + type: object + additionalProperties: true + - name: additionalPropertiesFalse + in: query + required: true + schema: + type: object + additionalProperties: false + - name: additionalPropertiesSchema + in: query + required: true + schema: + type: object + additionalProperties: + type: string + responses: + "200": + description: "200" + content: + application/json: + schema: + type: object + "201": + description: "201" + content: + application/json: + schema: + type: object + additionalProperties: true + "202": + description: "202" + content: + application/json: + schema: + type: object + additionalProperties: false + "203": + description: "203" + content: + application/json: + schema: + type: object + additionalProperties: + type: string components: schemas: ArrayWithValidationsInItems: @@ -110,4 +220,42 @@ components: - type: integer format: int64 maximum: 7 + AdditionalPropertiesUnset: + type: object + AdditionalPropertiesTrue: + type: object + additionalProperties: true + AdditionalPropertiesFalse: + type: object + additionalProperties: false + AdditionalPropertiesSchema: + type: object + additionalProperties: + type: string + ObjectModelWithRefAddPropsInProps: + type: object + properties: + map_with_additional_properties_unset: + $ref: '#/components/schemas/AdditionalPropertiesUnset' + map_with_additional_properties_true: + $ref: '#/components/schemas/AdditionalPropertiesTrue' + map_with_additional_properties_false: + $ref: '#/components/schemas/AdditionalPropertiesFalse' + map_with_additional_properties_schema: + $ref: '#/components/schemas/AdditionalPropertiesSchema' + ObjectModelWithAddPropsInProps: + type: object + properties: + map_with_additional_properties_unset: + type: object + map_with_additional_properties_true: + type: object + additionalProperties: true + map_with_additional_properties_false: + type: object + additionalProperties: false + map_with_additional_properties_schema: + type: object + additionalProperties: + type: string securitySchemes: {} \ No newline at end of file