diff --git a/modules/openapi-generator/pom.xml b/modules/openapi-generator/pom.xml index 2627d347ff2..7645217c8b3 100644 --- a/modules/openapi-generator/pom.xml +++ b/modules/openapi-generator/pom.xml @@ -272,6 +272,12 @@ commons-io ${commons-io.version} + + ch.qos.logback + logback-classic + 1.2.11 + test + org.slf4j slf4j-ext 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 d03499b9916..758ea86e33e 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 @@ -25,11 +25,27 @@ import com.google.common.collect.ImmutableMap; import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Mustache.Compiler; import com.samskivert.mustache.Mustache.Lambda; - +import io.swagger.v3.core.util.Json; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.callbacks.Callback; +import io.swagger.v3.oas.models.examples.Example; +import io.swagger.v3.oas.models.headers.Header; +import io.swagger.v3.oas.models.media.*; +import io.swagger.v3.oas.models.parameters.*; +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.responses.ApiResponses; +import io.swagger.v3.oas.models.security.OAuthFlow; +import io.swagger.v3.oas.models.security.OAuthFlows; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; +import io.swagger.v3.oas.models.servers.ServerVariable; +import io.swagger.v3.parser.util.SchemaTypeUtil; import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.text.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.text.StringEscapeUtils; import org.openapitools.codegen.CodegenDiscriminator.MappedModel; import org.openapitools.codegen.api.TemplatingEngineAdapter; import org.openapitools.codegen.config.GlobalSettings; @@ -634,7 +650,7 @@ public class DefaultCodegen implements CodegenConfig { parent.hasChildren = true; Schema parentSchema = this.openAPI.getComponents().getSchemas().get(parent.name); if (parentSchema == null) { - throw new NullPointerException(parent.name+" in "+this.openAPI.getComponents().getSchemas()); + throw new NullPointerException(parent.name + " in " + this.openAPI.getComponents().getSchemas()); } if (parentSchema.getDiscriminator() == null) { parent = allModels.get(parent.getParent()); @@ -2064,7 +2080,7 @@ public class DefaultCodegen implements CodegenConfig { if (encoding != null) { boolean styleGiven = true; Encoding.StyleEnum style = encoding.getStyle(); - if(style == null || style == Encoding.StyleEnum.FORM) { + if (style == null || style == Encoding.StyleEnum.FORM) { // (Unfortunately, swagger-parser-v3 will always provide 'form' // when style is not specified, so we can't detect that) style = Encoding.StyleEnum.FORM; @@ -2072,12 +2088,12 @@ public class DefaultCodegen implements CodegenConfig { } boolean explodeGiven = true; Boolean explode = encoding.getExplode(); - if(explode == null) { + if (explode == null) { explode = style == Encoding.StyleEnum.FORM; // Default to True when form, False otherwise explodeGiven = false; } - if(!styleGiven && !explodeGiven) { + if (!styleGiven && !explodeGiven) { // Ignore contentType if style or explode are specified. codegenParameter.contentType = encoding.getContentType(); } @@ -2085,7 +2101,7 @@ public class DefaultCodegen implements CodegenConfig { codegenParameter.style = style.toString(); codegenParameter.isDeepObject = Encoding.StyleEnum.DEEP_OBJECT == style; - if(codegenParameter.isContainer) { + if (codegenParameter.isContainer) { codegenParameter.isExplode = explode; String collectionFormat = getCollectionFormat(codegenParameter); codegenParameter.collectionFormat = StringUtils.isEmpty(collectionFormat) ? "csv" : collectionFormat; @@ -3032,7 +3048,6 @@ public class DefaultCodegen implements CodegenConfig { // referenced models here, component that refs another component which is a model // if a component references a schema which is not a generated model, the refed schema will be loaded into // schema by unaliasSchema and one of the above code paths will be taken - ; } if (schema.get$ref() != null) { m.setRef(schema.get$ref()); @@ -3942,7 +3957,7 @@ public class DefaultCodegen implements CodegenConfig { } property.baseType = getSchemaType(p); if (p.getXml() != null) { - property.isXmlWrapped = p.getXml().getWrapped() == null ? false : p.getXml().getWrapped(); + property.isXmlWrapped = p.getXml().getWrapped() != null && p.getXml().getWrapped(); property.xmlPrefix = p.getXml().getPrefix(); property.xmlNamespace = p.getXml().getNamespace(); property.xmlName = p.getXml().getName(); @@ -5052,7 +5067,7 @@ public class DefaultCodegen implements CodegenConfig { // the default value is false // https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#user-content-parameterexplode - codegenParameter.isExplode = parameter.getExplode() == null ? false : parameter.getExplode(); + codegenParameter.isExplode = parameter.getExplode() != null && parameter.getExplode(); // TODO revise collectionFormat, default collection format in OAS 3 appears to multi at least for query parameters // https://swagger.io/docs/specification/serialization/ @@ -5081,7 +5096,6 @@ public class DefaultCodegen implements CodegenConfig { if (ModelUtils.isShortSchema(parameterSchema)) { // int32/short format codegenParameter.isShort = true; } else { // unbounded integer - ; } } } else if (ModelUtils.isTypeObjectSchema(parameterSchema)) { @@ -5093,7 +5107,6 @@ public class DefaultCodegen implements CodegenConfig { } addVarsRequiredVarsAdditionalProps(parameterSchema, codegenParameter); } else if (ModelUtils.isNullType(parameterSchema)) { - ; } else if (ModelUtils.isAnyType(parameterSchema)) { // any schema with no type set, composed schemas often do this if (ModelUtils.isMapSchema(parameterSchema)) { // for map parameter @@ -5121,7 +5134,6 @@ public class DefaultCodegen implements CodegenConfig { } } else { // referenced schemas - ; } CodegenProperty codegenProperty = fromProperty(parameter.getName(), parameterSchema, false); @@ -6853,7 +6865,6 @@ public class DefaultCodegen implements CodegenConfig { if (ModelUtils.isShortSchema(ps)) { // int32/short format codegenParameter.isShort = true; } else { // unbounded integer - ; } } } else if (ModelUtils.isTypeObjectSchema(ps)) { @@ -6861,10 +6872,8 @@ public class DefaultCodegen implements CodegenConfig { codegenParameter.isFreeFormObject = true; } } else if (ModelUtils.isNullType(ps)) { - ; } else if (ModelUtils.isAnyType(ps)) { // any schema with no type set, composed schemas often do this - ; } else if (ModelUtils.isArraySchema(ps)) { Schema inner = getSchemaItems((ArraySchema) ps); CodegenProperty arrayInnerProperty = fromProperty("inner", inner, false); @@ -6905,7 +6914,6 @@ public class DefaultCodegen implements CodegenConfig { } } else { // referenced schemas - ; } if (Boolean.TRUE.equals(codegenProperty.isModel)) { @@ -7809,9 +7817,9 @@ public class DefaultCodegen implements CodegenConfig { return exceptions; } - private String name; - private String removeCharRegEx; - private List exceptions; + private final String name; + private final String removeCharRegEx; + private final List exceptions; @Override public boolean equals(Object o) { @@ -7983,7 +7991,7 @@ public class DefaultCodegen implements CodegenConfig { } private CodegenComposedSchemas getComposedSchemas(Schema schema) { - if (!(schema instanceof ComposedSchema) && schema.getNot()==null) { + if (!(schema instanceof ComposedSchema) && schema.getNot() == null) { return null; } Schema notSchema = schema.getNot(); 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 150bdc6a04e..c28a0a6a214 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 @@ -28,11 +28,12 @@ import io.swagger.v3.oas.models.media.*; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.parser.ObjectMapperFactory; import io.swagger.v3.parser.core.models.AuthorizationValue; import io.swagger.v3.parser.util.ClasspathHelper; -import io.swagger.v3.parser.ObjectMapperFactory; import io.swagger.v3.parser.util.RemoteUrl; import io.swagger.v3.parser.util.SchemaTypeUtil; +import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.IJsonSchemaValidationProperties; @@ -41,18 +42,17 @@ import org.openapitools.codegen.model.ModelMap; import org.openapitools.codegen.model.ModelsMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.commons.io.FileUtils; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.net.URI; import java.net.URLDecoder; -import java.util.*; -import java.util.Map.Entry; -import java.util.stream.Collectors; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.*; +import java.util.Map.Entry; +import java.util.stream.Collectors; import static org.openapitools.codegen.utils.OnceLogger.once; @@ -71,29 +71,30 @@ public class ModelUtils { private static final String freeFormExplicit = "x-is-free-form"; - private static ObjectMapper JSON_MAPPER, YAML_MAPPER; + private static final ObjectMapper JSON_MAPPER; + private static final ObjectMapper YAML_MAPPER; static { JSON_MAPPER = ObjectMapperFactory.createJson(); YAML_MAPPER = ObjectMapperFactory.createYaml(); } - public static void setDisallowAdditionalPropertiesIfNotPresent(boolean value) { - GlobalSettings.setProperty(disallowAdditionalPropertiesIfNotPresent, Boolean.toString(value)); - } - public static boolean isDisallowAdditionalPropertiesIfNotPresent() { return Boolean.parseBoolean(GlobalSettings.getProperty(disallowAdditionalPropertiesIfNotPresent, "true")); } - public static void setGenerateAliasAsModel(boolean value) { - GlobalSettings.setProperty(generateAliasAsModelKey, Boolean.toString(value)); + public static void setDisallowAdditionalPropertiesIfNotPresent(boolean value) { + GlobalSettings.setProperty(disallowAdditionalPropertiesIfNotPresent, Boolean.toString(value)); } public static boolean isGenerateAliasAsModel() { return Boolean.parseBoolean(GlobalSettings.getProperty(generateAliasAsModelKey, "false")); } + public static void setGenerateAliasAsModel(boolean value) { + GlobalSettings.setProperty(generateAliasAsModelKey, Boolean.toString(value)); + } + public static boolean isGenerateAliasAsModel(Schema schema) { return isGenerateAliasAsModel() || (schema.getExtensions() != null && schema.getExtensions().getOrDefault("x-generate-alias-as-model", false).equals(true)); } @@ -371,12 +372,6 @@ public class ModelUtils { } } - @FunctionalInterface - private static interface OpenAPISchemaVisitor { - - public void visit(Schema schema, String mimeType); - } - public static String getSimpleRef(String ref) { if (ref == null) { once(LOGGER).warn("Failed to get the schema name: null"); @@ -456,10 +451,7 @@ public class ModelUtils { } // must have at least one property - if (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty()) { - return true; - } - return false; + return schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty(); } /** @@ -560,11 +552,7 @@ public class ModelUtils { return true; } - if (schema.getAdditionalProperties() instanceof Boolean && (Boolean) schema.getAdditionalProperties()) { - return true; - } - - return false; + return schema.getAdditionalProperties() instanceof Boolean && (Boolean) schema.getAdditionalProperties(); } /** @@ -582,28 +570,20 @@ public class ModelUtils { } public static boolean isStringSchema(Schema schema) { - if (schema instanceof StringSchema || SchemaTypeUtil.STRING_TYPE.equals(schema.getType())) { - return true; - } - return false; + return schema instanceof StringSchema || SchemaTypeUtil.STRING_TYPE.equals(schema.getType()); } public static boolean isIntegerSchema(Schema schema) { if (schema instanceof IntegerSchema) { return true; } - if (SchemaTypeUtil.INTEGER_TYPE.equals(schema.getType())) { - return true; - } - return false; + return SchemaTypeUtil.INTEGER_TYPE.equals(schema.getType()); } public static boolean isShortSchema(Schema schema) { - if (SchemaTypeUtil.INTEGER_TYPE.equals(schema.getType()) // type: integer - && SchemaTypeUtil.INTEGER32_FORMAT.equals(schema.getFormat())) { // format: short (int32) - return true; - } - return false; + // format: short (int32) + return SchemaTypeUtil.INTEGER_TYPE.equals(schema.getType()) // type: integer + && SchemaTypeUtil.INTEGER32_FORMAT.equals(schema.getFormat()); } public static boolean isUnsignedIntegerSchema(Schema schema) { @@ -616,11 +596,9 @@ public class ModelUtils { } public static boolean isLongSchema(Schema schema) { - if (SchemaTypeUtil.INTEGER_TYPE.equals(schema.getType()) // type: integer - && SchemaTypeUtil.INTEGER64_FORMAT.equals(schema.getFormat())) { // format: long (int64) - return true; - } - return false; + // format: long (int64) + return SchemaTypeUtil.INTEGER_TYPE.equals(schema.getType()) // type: integer + && SchemaTypeUtil.INTEGER64_FORMAT.equals(schema.getFormat()); } public static boolean isUnsignedLongSchema(Schema schema) { @@ -636,36 +614,26 @@ public class ModelUtils { if (schema instanceof BooleanSchema) { return true; } - if (SchemaTypeUtil.BOOLEAN_TYPE.equals(schema.getType())) { - return true; - } - return false; + return SchemaTypeUtil.BOOLEAN_TYPE.equals(schema.getType()); } public static boolean isNumberSchema(Schema schema) { if (schema instanceof NumberSchema) { return true; } - if (SchemaTypeUtil.NUMBER_TYPE.equals(schema.getType())) { - return true; - } - return false; + return SchemaTypeUtil.NUMBER_TYPE.equals(schema.getType()); } public static boolean isFloatSchema(Schema schema) { - if (SchemaTypeUtil.NUMBER_TYPE.equals(schema.getType()) - && SchemaTypeUtil.FLOAT_FORMAT.equals(schema.getFormat())) { // format: float - return true; - } - return false; + // format: float + return SchemaTypeUtil.NUMBER_TYPE.equals(schema.getType()) + && SchemaTypeUtil.FLOAT_FORMAT.equals(schema.getFormat()); } public static boolean isDoubleSchema(Schema schema) { - if (SchemaTypeUtil.NUMBER_TYPE.equals(schema.getType()) - && SchemaTypeUtil.DOUBLE_FORMAT.equals(schema.getFormat())) { // format: double - return true; - } - return false; + // format: double + return SchemaTypeUtil.NUMBER_TYPE.equals(schema.getType()) + && SchemaTypeUtil.DOUBLE_FORMAT.equals(schema.getFormat()); } public static boolean isDateSchema(Schema schema) { @@ -673,55 +641,45 @@ public class ModelUtils { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) - && SchemaTypeUtil.DATE_FORMAT.equals(schema.getFormat())) { // format: date - return true; - } - return false; + // format: date + return SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + && SchemaTypeUtil.DATE_FORMAT.equals(schema.getFormat()); } public static boolean isDateTimeSchema(Schema schema) { if (schema instanceof DateTimeSchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) - && SchemaTypeUtil.DATE_TIME_FORMAT.equals(schema.getFormat())) { // format: date-time - return true; - } - return false; + // format: date-time + return SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + && SchemaTypeUtil.DATE_TIME_FORMAT.equals(schema.getFormat()); } public static boolean isPasswordSchema(Schema schema) { if (schema instanceof PasswordSchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) - && SchemaTypeUtil.PASSWORD_FORMAT.equals(schema.getFormat())) { // double - return true; - } - return false; + // double + return SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + && SchemaTypeUtil.PASSWORD_FORMAT.equals(schema.getFormat()); } public static boolean isByteArraySchema(Schema schema) { if (schema instanceof ByteArraySchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) - && SchemaTypeUtil.BYTE_FORMAT.equals(schema.getFormat())) { // format: byte - return true; - } - return false; + // format: byte + return SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + && SchemaTypeUtil.BYTE_FORMAT.equals(schema.getFormat()); } public static boolean isBinarySchema(Schema schema) { if (schema instanceof BinarySchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) - && SchemaTypeUtil.BINARY_FORMAT.equals(schema.getFormat())) { // format: binary - return true; - } - return false; + // format: binary + return SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + && SchemaTypeUtil.BINARY_FORMAT.equals(schema.getFormat()); } public static boolean isFileSchema(Schema schema) { @@ -736,38 +694,30 @@ public class ModelUtils { if (schema instanceof UUIDSchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) - && SchemaTypeUtil.UUID_FORMAT.equals(schema.getFormat())) { // format: uuid - return true; - } - return false; + // format: uuid + return SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + && SchemaTypeUtil.UUID_FORMAT.equals(schema.getFormat()); } public static boolean isURISchema(Schema schema) { - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) - && URI_FORMAT.equals(schema.getFormat())) { // format: uri - return true; - } - return false; + // format: uri + return SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + && URI_FORMAT.equals(schema.getFormat()); } public static boolean isEmailSchema(Schema schema) { if (schema instanceof EmailSchema) { return true; } - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) - && SchemaTypeUtil.EMAIL_FORMAT.equals(schema.getFormat())) { // format: email - return true; - } - return false; + // format: email + return SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) + && SchemaTypeUtil.EMAIL_FORMAT.equals(schema.getFormat()); } public static boolean isDecimalSchema(Schema schema) { - if (SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) // type: string - && "number".equals(schema.getFormat())) { // format: number - return true; - } - return false; + // format: number + return SchemaTypeUtil.STRING_TYPE.equals(schema.getType()) // type: string + && "number".equals(schema.getFormat()); } /** @@ -896,14 +846,10 @@ public class ModelUtils { if (addlProps instanceof ObjectSchema) { ObjectSchema objSchema = (ObjectSchema) addlProps; // additionalProperties defined as {} - if (objSchema.getProperties() == null || objSchema.getProperties().isEmpty()) { - return true; - } + return objSchema.getProperties() == null || objSchema.getProperties().isEmpty(); } else if (addlProps instanceof Schema) { // additionalProperties defined as {} - if (addlProps.getType() == null && addlProps.get$ref() == null && (addlProps.getProperties() == null || addlProps.getProperties().isEmpty())) { - return true; - } + return addlProps.getType() == null && addlProps.get$ref() == null && (addlProps.getProperties() == null || addlProps.getProperties().isEmpty()); } } } @@ -1412,7 +1358,6 @@ public class ModelUtils { .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue().stream().map(e -> e.getKey()).collect(Collectors.toList()))); } - /** * Get the interfaces from the schema (composed) * @@ -1683,18 +1628,15 @@ public class ModelUtils { * either be null or a specified type: *

* OptionalOrder: - * oneOf: - * - type: 'null' - * - $ref: '#/components/schemas/Order' + * oneOf: + * - type: 'null' + * - $ref: '#/components/schemas/Order' * * @param schema the OpenAPI schema * @return true if the schema is the 'null' type */ public static boolean isNullType(Schema schema) { - if ("null".equals(schema.getType())) { - return true; - } - return false; + return "null".equals(schema.getType()); } /** @@ -1715,47 +1657,90 @@ public class ModelUtils { public static void syncValidationProperties(Schema schema, IJsonSchemaValidationProperties target) { // TODO move this method to IJsonSchemaValidationProperties - if (schema != null && target != null) { - if (isNullType(schema) || schema.get$ref() != null || isBooleanSchema(schema)) { - return; - } - Integer minItems = schema.getMinItems(); - Integer maxItems = schema.getMaxItems(); - Boolean uniqueItems = schema.getUniqueItems(); - Integer minProperties = schema.getMinProperties(); - Integer maxProperties = schema.getMaxProperties(); - Integer minLength = schema.getMinLength(); - Integer maxLength = schema.getMaxLength(); - String pattern = schema.getPattern(); - BigDecimal multipleOf = schema.getMultipleOf(); - BigDecimal minimum = schema.getMinimum(); - BigDecimal maximum = schema.getMaximum(); - Boolean exclusiveMinimum = schema.getExclusiveMinimum(); - Boolean exclusiveMaximum = schema.getExclusiveMaximum(); + if (schema == null || + target == null || + schema.get$ref() != null) + return; + SchemaValidations.ValidationSetBuilder vSB = new SchemaValidations.ValidationSetBuilder(); - if (isArraySchema(schema)) { + Integer minItems = schema.getMinItems(); + if (minItems != null) vSB.withMinItems(); + + Integer maxItems = schema.getMaxItems(); + if (maxItems != null) vSB.withMaxItems(); + + Boolean uniqueItems = schema.getUniqueItems(); + if (uniqueItems != null) vSB.withUniqueItems(); + + Integer minProperties = schema.getMinProperties(); + if (minProperties != null) vSB.withMinProperties(); + + Integer maxProperties = schema.getMaxProperties(); + if (maxProperties != null) vSB.withMaxProperties(); + + Integer minLength = schema.getMinLength(); + if (minLength != null) vSB.withMinLength(); + + Integer maxLength = schema.getMaxLength(); + if (maxLength != null) vSB.withMaxLength(); + + String pattern = schema.getPattern(); + if (pattern != null) vSB.withPattern(); + + BigDecimal multipleOf = schema.getMultipleOf(); + if (multipleOf != null) vSB.withMultipleOf(); + + BigDecimal minimum = schema.getMinimum(); + if (minimum != null) vSB.withMinimum(); + + BigDecimal maximum = schema.getMaximum(); + if (maximum != null) vSB.withMaximum(); + + Boolean exclusiveMinimum = schema.getExclusiveMinimum(); + if (exclusiveMinimum != null) vSB.withExclusiveMinimum(); + + Boolean exclusiveMaximum = schema.getExclusiveMaximum(); + if (exclusiveMaximum != null) vSB.withExclusiveMaximum(); + + LinkedHashSet setValidations = vSB.build(); + + if (isBooleanSchema(schema) || isNullType(schema)) { + logWarnMessagesForIneffectiveValidations(setValidations, schema, new HashSet<>()); + } else if (isArraySchema(schema)) { + if (minItems != null || maxItems != null || uniqueItems != null) setArrayValidations(minItems, maxItems, uniqueItems, target); - } else if (isTypeObjectSchema(schema)) { + logWarnMessagesForIneffectiveValidations(new LinkedHashSet(setValidations), schema, SchemaValidations.ARRAY_VALIDATIONS); + } else if (isTypeObjectSchema(schema)) { + if (minProperties != null || maxProperties != null) setObjectValidations(minProperties, maxProperties, target); - } else if (isStringSchema(schema)) { + logWarnMessagesForIneffectiveValidations(new LinkedHashSet(setValidations), schema, SchemaValidations.OBJECT_VALIDATIONS); + } else if (isStringSchema(schema)) { + if (minLength != null || maxLength != null || pattern != null) setStringValidations(minLength, maxLength, pattern, target); - if (isDecimalSchema(schema)) { + if (isDecimalSchema(schema)) { + if (multipleOf != null || minimum != null || maximum != null || exclusiveMinimum != null || exclusiveMaximum != null) setNumericValidations(schema, multipleOf, minimum, maximum, exclusiveMinimum, exclusiveMaximum, target); - } - } else if (isNumberSchema(schema) || isIntegerSchema(schema)) { - setNumericValidations(schema, multipleOf, minimum, maximum, exclusiveMinimum, exclusiveMaximum, target); - } else if (isAnyType(schema)) { - // anyType can have any validations set on it - setArrayValidations(minItems, maxItems, uniqueItems, target); - setObjectValidations(minProperties, maxProperties, target); - setStringValidations(minLength, maxLength, pattern, target); - setNumericValidations(schema, multipleOf, minimum, maximum, exclusiveMinimum, exclusiveMaximum, target); - } - if (maxItems != null || minItems != null || minProperties != null || maxProperties != null || minLength != null || maxLength != null || multipleOf != null || pattern != null || minimum != null || maximum != null || exclusiveMinimum != null || exclusiveMaximum != null || uniqueItems != null) { - target.setHasValidation(true); - } + Set stringAndNumericValidations = new HashSet<>(SchemaValidations.STRING_VALIDATIONS); + stringAndNumericValidations.addAll(SchemaValidations.NUMERIC_VALIDATIONS); + logWarnMessagesForIneffectiveValidations(new LinkedHashSet(setValidations), schema, stringAndNumericValidations); + } else + logWarnMessagesForIneffectiveValidations(new LinkedHashSet(setValidations), schema, SchemaValidations.STRING_VALIDATIONS); + + } else if (isNumberSchema(schema) || isIntegerSchema(schema)) { + if (multipleOf != null || minimum != null || maximum != null || exclusiveMinimum != null || exclusiveMaximum != null) + setNumericValidations(schema, multipleOf, minimum, maximum, exclusiveMinimum, exclusiveMaximum, target); + logWarnMessagesForIneffectiveValidations(new LinkedHashSet(setValidations), schema, SchemaValidations.NUMERIC_VALIDATIONS); + } else if (isAnyType(schema)) { + // anyType can have any validations set on it + setArrayValidations(minItems, maxItems, uniqueItems, target); + setObjectValidations(minProperties, maxProperties, target); + setStringValidations(minLength, maxLength, pattern, target); + setNumericValidations(schema, multipleOf, minimum, maximum, exclusiveMinimum, exclusiveMaximum, target); } + + if (!setValidations.isEmpty()) + target.setHasValidation(true); } private static void setArrayValidations(Integer minItems, Integer maxItems, Boolean uniqueItems, IJsonSchemaValidationProperties target) { @@ -1796,6 +1781,13 @@ public class ModelUtils { } } + private static void logWarnMessagesForIneffectiveValidations(Set setValidations, Schema schema, Set effectiveValidations) { + setValidations.removeAll(effectiveValidations); + setValidations.stream().forEach(validation -> { + LOGGER.warn("Validation '" + validation + "' has no effect on schema '"+ schema.getType() +"'. Ignoring!"); + }); + } + private static ObjectMapper getRightMapper(String data) { ObjectMapper mapper; if (data.trim().startsWith("{")) { @@ -1986,4 +1978,125 @@ public class ModelUtils { return false; } + + @FunctionalInterface + private interface OpenAPISchemaVisitor { + + void visit(Schema schema, String mimeType); + } + + private static final class SchemaValidations { + + public static Set ARRAY_VALIDATIONS = new ValidationSetBuilder() + .withMinItems() + .withMaxItems() + .withUniqueItems() + .build(); + public static Set OBJECT_VALIDATIONS = new ValidationSetBuilder() + .withMinProperties() + .withMaxProperties() + .build(); + public static Set STRING_VALIDATIONS = new ValidationSetBuilder() + .withMinLength() + .withMaxLength() + .withPattern() + .build(); + public static Set NUMERIC_VALIDATIONS = new ValidationSetBuilder() + .withMultipleOf() + .withMinimum() + .withMaximum() + .withExclusiveMinimum() + .withExclusiveMaximum() + .build(); + + public static Set ALL_VALIDATIONS; + + static { + ALL_VALIDATIONS = new HashSet<>(ARRAY_VALIDATIONS); + ALL_VALIDATIONS.addAll(OBJECT_VALIDATIONS); + ALL_VALIDATIONS.addAll(STRING_VALIDATIONS); + ALL_VALIDATIONS.addAll(NUMERIC_VALIDATIONS); + } + + SchemaValidations() { + } + + + public static class ValidationSetBuilder { + LinkedHashSet validationSet; + + ValidationSetBuilder() { + this.validationSet = new LinkedHashSet(); + } + + public ValidationSetBuilder withMinItems() { + this.validationSet.add("minItems"); + return this; + } + + public ValidationSetBuilder withMaxItems() { + this.validationSet.add("maxItems"); + return this; + } + + public ValidationSetBuilder withUniqueItems() { + this.validationSet.add("uniqueItems"); + return this; + } + + public ValidationSetBuilder withMinProperties() { + this.validationSet.add("minProperties"); + return this; + } + + public ValidationSetBuilder withMaxProperties() { + this.validationSet.add("maxProperties"); + return this; + } + + public ValidationSetBuilder withMinLength() { + this.validationSet.add("minLength"); + return this; + } + + public ValidationSetBuilder withMaxLength() { + this.validationSet.add("maxLength"); + return this; + } + + public ValidationSetBuilder withPattern() { + this.validationSet.add("pattern"); + return this; + } + + public ValidationSetBuilder withMultipleOf() { + this.validationSet.add("multipleOf"); + return this; + } + + public ValidationSetBuilder withMinimum() { + this.validationSet.add("minimum"); + return this; + } + + public ValidationSetBuilder withMaximum() { + this.validationSet.add("maximum"); + return this; + } + + public ValidationSetBuilder withExclusiveMinimum() { + this.validationSet.add("exclusiveMinimum"); + return this; + } + + public ValidationSetBuilder withExclusiveMaximum() { + this.validationSet.add("exclusiveMaximum"); + return this; + } + + public LinkedHashSet build() { + return this.validationSet; + } + } + } } 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 369b99f2c38..107fd4e72c4 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 @@ -17,9 +17,13 @@ package org.openapitools.codegen; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; import com.google.common.collect.Sets; import com.samskivert.mustache.Mustache.Lambda; - import io.swagger.parser.OpenAPIParser; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; @@ -33,18 +37,14 @@ import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.parser.core.models.ParseOptions; - import org.openapitools.codegen.config.CodegenConfigurator; import org.openapitools.codegen.config.GlobalSettings; import org.openapitools.codegen.model.ModelMap; import org.openapitools.codegen.model.ModelsMap; -import org.openapitools.codegen.templating.mustache.CamelCaseLambda; -import org.openapitools.codegen.templating.mustache.IndentedLambda; -import org.openapitools.codegen.templating.mustache.LowercaseLambda; -import org.openapitools.codegen.templating.mustache.TitlecaseLambda; -import org.openapitools.codegen.templating.mustache.UppercaseLambda; +import org.openapitools.codegen.templating.mustache.*; import org.openapitools.codegen.utils.ModelUtils; import org.openapitools.codegen.utils.SemVer; +import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.Ignore; import org.testng.annotations.Test; @@ -54,10 +54,13 @@ import java.nio.file.Files; import java.util.*; import java.util.stream.Collectors; +import static junit.framework.Assert.assertEquals; import static org.testng.Assert.*; public class DefaultCodegenTest { + private static final Logger testLogger = (Logger) LoggerFactory.getLogger(ModelUtils.class); + @Test public void testDeeplyNestedAdditionalPropertiesImports() { final DefaultCodegen codegen = new DefaultCodegen(); @@ -667,7 +670,6 @@ public class DefaultCodegenTest { Assert.assertTrue(colorSeen); } - @Test public void testEscapeText() { final DefaultCodegen codegen = new DefaultCodegen(); @@ -1591,7 +1593,6 @@ public class DefaultCodegenTest { assertEquals(cm.discriminator, discriminator); } - @Test public void testAllOfSingleRefNoOwnProps() { final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/2_0/composed-allof.yaml"); @@ -1605,14 +1606,6 @@ public class DefaultCodegenTest { Assert.assertNull(model.allParents); } - class CodegenWithMultipleInheritance extends DefaultCodegen { - public CodegenWithMultipleInheritance() { - super(); - supportsInheritance = true; - supportsMultipleInheritance = true; - } - } - @Test public void testAllOfParent() { final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/allOf-required-parent.yaml"); @@ -2238,83 +2231,6 @@ public class DefaultCodegenTest { assertEquals(codegen.toApiName(""), "DefaultApi"); } - public static class FromParameter { - private CodegenParameter codegenParameter(String path) { - final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/fromParameter.yaml"); - new InlineModelResolver().flatten(openAPI); - final DefaultCodegen codegen = new DefaultCodegen(); - codegen.setOpenAPI(openAPI); - - return codegen - .fromParameter( - openAPI - .getPaths() - .get(path) - .getGet() - .getParameters() - .get(0), - new HashSet<>() - ); - } - - @Test - public void setStyle() { - CodegenParameter parameter = codegenParameter("/set_style"); - assertEquals(parameter.style, "form"); - } - - @Test - public void setShouldExplode() { - CodegenParameter parameter = codegenParameter("/set_should_explode"); - assertTrue(parameter.isExplode); - } - - @Test - public void testConvertPropertyToBooleanAndWriteBack_Boolean_true() { - final DefaultCodegen codegen = new DefaultCodegen(); - Map additionalProperties = codegen.additionalProperties(); - additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, true); - boolean result = codegen.convertPropertyToBooleanAndWriteBack(CodegenConstants.SERIALIZABLE_MODEL); - Assert.assertTrue(result); - } - - @Test - public void testConvertPropertyToBooleanAndWriteBack_Boolean_false() { - final DefaultCodegen codegen = new DefaultCodegen(); - Map additionalProperties = codegen.additionalProperties(); - additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, false); - boolean result = codegen.convertPropertyToBooleanAndWriteBack(CodegenConstants.SERIALIZABLE_MODEL); - Assert.assertFalse(result); - } - - @Test - public void testConvertPropertyToBooleanAndWriteBack_String_true() { - final DefaultCodegen codegen = new DefaultCodegen(); - Map additionalProperties = codegen.additionalProperties(); - additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, "true"); - boolean result = codegen.convertPropertyToBooleanAndWriteBack(CodegenConstants.SERIALIZABLE_MODEL); - Assert.assertTrue(result); - } - - @Test - public void testConvertPropertyToBooleanAndWriteBack_String_false() { - final DefaultCodegen codegen = new DefaultCodegen(); - Map additionalProperties = codegen.additionalProperties(); - additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, "false"); - boolean result = codegen.convertPropertyToBooleanAndWriteBack(CodegenConstants.SERIALIZABLE_MODEL); - Assert.assertFalse(result); - } - - @Test - public void testConvertPropertyToBooleanAndWriteBack_String_blibb() { - final DefaultCodegen codegen = new DefaultCodegen(); - Map additionalProperties = codegen.additionalProperties(); - additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, "blibb"); - boolean result = codegen.convertPropertyToBooleanAndWriteBack(CodegenConstants.SERIALIZABLE_MODEL); - Assert.assertFalse(result); - } - } - @Test public void testCircularReferencesDetection() { // given @@ -2464,7 +2380,7 @@ public class DefaultCodegenTest { "post", path.getPost(), path.getServers()); - assertEquals(operation.formParams.size(), 3, + Assert.assertEquals(operation.formParams.size(), 3, "The list of parameters should include inherited type"); final List names = operation.formParams.stream() @@ -3750,7 +3666,7 @@ public class DefaultCodegenTest { modelName = "ObjectWithComposedProperties"; CodegenModel m = codegen.fromModel(modelName, openAPI.getComponents().getSchemas().get(modelName)); /* TODO inline allOf schema are created as separate models and the following assumptions that - the properties are non-model are no longer valid and need to be revised + the properties are non-model are no longer valid and need to be revised assertTrue(m.vars.get(0).getIsMap()); assertTrue(m.vars.get(1).getIsNumber()); assertTrue(m.vars.get(2).getIsUnboundedInteger()); @@ -4242,6 +4158,356 @@ public class DefaultCodegenTest { Assert.assertEquals(codegenParameter.getSchema(), null); } + @Test + public void testArraySchemaWithIneffectiveConstraints() { + + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + + // add the appender to the logger + testLogger.addAppender(listAppender); + + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue6491.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + String modelName = "ArrayWithIneffectiveValidations"; + Schema sc = openAPI.getComponents().getSchemas().get(modelName); + CodegenModel cm = codegen.fromModel(modelName, sc); + + + List logsList = listAppender.list; + + // JUnit assertions + assertEquals(16, logsList.size()); + assertEquals("Validation 'minProperties' has no effect on schema 'array'. Ignoring!", logsList.get(0) + .getMessage()); + assertEquals("Validation 'maxProperties' has no effect on schema 'array'. Ignoring!", logsList.get(1) + .getMessage()); + assertEquals("Validation 'minLength' has no effect on schema 'array'. Ignoring!", logsList.get(2) + .getMessage()); + assertEquals("Validation 'maxLength' has no effect on schema 'array'. Ignoring!", logsList.get(3) + .getMessage()); + assertEquals("Validation 'pattern' has no effect on schema 'array'. Ignoring!", logsList.get(4) + .getMessage()); + assertEquals("Validation 'multipleOf' has no effect on schema 'array'. Ignoring!", logsList.get(5) + .getMessage()); + assertEquals("Validation 'minimum' has no effect on schema 'array'. Ignoring!", logsList.get(6) + .getMessage()); + assertEquals("Validation 'maximum' has no effect on schema 'array'. Ignoring!", logsList.get(7) + .getMessage()); + + // Assert all logged messages are WARN messages + logsList.stream().limit(8).forEach(log -> assertEquals(Level.WARN, log.getLevel())); + } + + @Test + public void testObjectSchemaWithIneffectiveConstraints() { + + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + + // add the appender to the logger + testLogger.addAppender(listAppender); + + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue6491.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + String modelName = "ObjectWithIneffectiveValidations"; + Schema sc = openAPI.getComponents().getSchemas().get(modelName); + CodegenModel cm = codegen.fromModel(modelName, sc); + + List logsList = listAppender.list; + + // JUnit assertions + assertEquals(9, logsList.size()); + assertEquals("Validation 'minItems' has no effect on schema 'object'. Ignoring!", logsList.get(0) + .getMessage()); + assertEquals("Validation 'maxItems' has no effect on schema 'object'. Ignoring!", logsList.get(1) + .getMessage()); + assertEquals("Validation 'uniqueItems' has no effect on schema 'object'. Ignoring!", logsList.get(2) + .getMessage()); + assertEquals("Validation 'minLength' has no effect on schema 'object'. Ignoring!", logsList.get(3) + .getMessage()); + assertEquals("Validation 'maxLength' has no effect on schema 'object'. Ignoring!", logsList.get(4) + .getMessage()); + assertEquals("Validation 'pattern' has no effect on schema 'object'. Ignoring!", logsList.get(5) + .getMessage()); + assertEquals("Validation 'multipleOf' has no effect on schema 'object'. Ignoring!", logsList.get(6) + .getMessage()); + assertEquals("Validation 'minimum' has no effect on schema 'object'. Ignoring!", logsList.get(7) + .getMessage()); + assertEquals("Validation 'maximum' has no effect on schema 'object'. Ignoring!", logsList.get(8) + .getMessage()); + + // Assert all logged messages are WARN messages + logsList.stream().forEach(log -> assertEquals(Level.WARN, log.getLevel())); + } + + @Test + public void testStringSchemaWithIneffectiveConstraints() { + + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + + // add the appender to the logger + testLogger.addAppender(listAppender); + + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue6491.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + String modelName = "StringWithIneffectiveValidations"; + Schema sc = openAPI.getComponents().getSchemas().get(modelName); + CodegenModel cm = codegen.fromModel(modelName, sc); + + List logsList = listAppender.list; + + // JUnit assertions + assertEquals(8, logsList.size()); + assertEquals("Validation 'minItems' has no effect on schema 'string'. Ignoring!", logsList.get(0) + .getMessage()); + assertEquals("Validation 'maxItems' has no effect on schema 'string'. Ignoring!", logsList.get(1) + .getMessage()); + assertEquals("Validation 'uniqueItems' has no effect on schema 'string'. Ignoring!", logsList.get(2) + .getMessage()); + assertEquals("Validation 'minProperties' has no effect on schema 'string'. Ignoring!", logsList.get(3) + .getMessage()); + assertEquals("Validation 'maxProperties' has no effect on schema 'string'. Ignoring!", logsList.get(4) + .getMessage()); + assertEquals("Validation 'multipleOf' has no effect on schema 'string'. Ignoring!", logsList.get(5) + .getMessage()); + assertEquals("Validation 'minimum' has no effect on schema 'string'. Ignoring!", logsList.get(6) + .getMessage()); + assertEquals("Validation 'maximum' has no effect on schema 'string'. Ignoring!", logsList.get(7) + .getMessage()); + + // Assert all logged messages are WARN messages + logsList.stream().forEach(log -> assertEquals(Level.WARN, log.getLevel())); + } + + @Test + public void testIntegerSchemaWithIneffectiveConstraints() { + + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + + // add the appender to the logger + testLogger.addAppender(listAppender); + + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue6491.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + String modelName = "IntegerWithIneffectiveValidations"; + Schema sc = openAPI.getComponents().getSchemas().get(modelName); + CodegenModel cm = codegen.fromModel(modelName, sc); + + List logsList = listAppender.list; + + // JUnit assertions + assertEquals(8, logsList.size()); + assertEquals("Validation 'minItems' has no effect on schema 'integer'. Ignoring!", logsList.get(0) + .getMessage()); + assertEquals("Validation 'maxItems' has no effect on schema 'integer'. Ignoring!", logsList.get(1) + .getMessage()); + assertEquals("Validation 'uniqueItems' has no effect on schema 'integer'. Ignoring!", logsList.get(2) + .getMessage()); + assertEquals("Validation 'minProperties' has no effect on schema 'integer'. Ignoring!", logsList.get(3) + .getMessage()); + assertEquals("Validation 'maxProperties' has no effect on schema 'integer'. Ignoring!", logsList.get(4) + .getMessage()); + assertEquals("Validation 'minLength' has no effect on schema 'integer'. Ignoring!", logsList.get(5) + .getMessage()); + assertEquals("Validation 'maxLength' has no effect on schema 'integer'. Ignoring!", logsList.get(6) + .getMessage()); + assertEquals("Validation 'pattern' has no effect on schema 'integer'. Ignoring!", logsList.get(7) + .getMessage()); + + // Assert all logged messages are WARN messages + logsList.stream().forEach(log -> assertEquals(Level.WARN, log.getLevel())); + } + + @Test + public void testAnySchemaWithIneffectiveConstraints() { + + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + + // add the appender to the logger + testLogger.addAppender(listAppender); + + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue6491.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + String modelName = "AnyTypeWithIneffectiveValidations"; + Schema sc = openAPI.getComponents().getSchemas().get(modelName); + CodegenModel cm = codegen.fromModel(modelName, sc); + + List logsList = listAppender.list; + + // JUnit assertions + assertEquals(0, logsList.size()); + } + + @Test + public void testBooleanSchemaWithIneffectiveConstraints() { + + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + + // add the appender to the logger + testLogger.addAppender(listAppender); + + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue6491.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + String modelName = "BooleanWithIneffectiveValidations"; + Schema sc = openAPI.getComponents().getSchemas().get(modelName); + CodegenModel cm = codegen.fromModel(modelName, sc); + + List logsList = listAppender.list; + + // JUnit assertions + assertEquals(11, logsList.size()); + assertEquals("Validation 'minItems' has no effect on schema 'boolean'. Ignoring!", logsList.get(0) + .getMessage()); + assertEquals("Validation 'maxItems' has no effect on schema 'boolean'. Ignoring!", logsList.get(1) + .getMessage()); + assertEquals("Validation 'uniqueItems' has no effect on schema 'boolean'. Ignoring!", logsList.get(2) + .getMessage()); + assertEquals("Validation 'minProperties' has no effect on schema 'boolean'. Ignoring!", logsList.get(3) + .getMessage()); + assertEquals("Validation 'maxProperties' has no effect on schema 'boolean'. Ignoring!", logsList.get(4) + .getMessage()); + assertEquals("Validation 'minLength' has no effect on schema 'boolean'. Ignoring!", logsList.get(5) + .getMessage()); + assertEquals("Validation 'maxLength' has no effect on schema 'boolean'. Ignoring!", logsList.get(6) + .getMessage()); + assertEquals("Validation 'pattern' has no effect on schema 'boolean'. Ignoring!", logsList.get(7) + .getMessage()); + assertEquals("Validation 'multipleOf' has no effect on schema 'boolean'. Ignoring!", logsList.get(8) + .getMessage()); + assertEquals("Validation 'minimum' has no effect on schema 'boolean'. Ignoring!", logsList.get(9) + .getMessage()); + assertEquals("Validation 'maximum' has no effect on schema 'boolean'. Ignoring!", logsList.get(10) + .getMessage()); + + // Assert all logged messages are WARN messages + logsList.stream().forEach(log -> assertEquals(Level.WARN, log.getLevel())); + } + + @Test + public void testNullSchemaWithIneffectiveConstraints() { + + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + + // add the appender to the logger + testLogger.addAppender(listAppender); + + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue6491.yaml"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + String modelName = "NullWithIneffectiveValidations"; + Schema sc = openAPI.getComponents().getSchemas().get(modelName); + CodegenModel cm = codegen.fromModel(modelName, sc); + + List logsList = listAppender.list; + + // JUnit assertions + assertEquals(0, logsList.size()); + } + + public static class FromParameter { + private CodegenParameter codegenParameter(String path) { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/fromParameter.yaml"); + new InlineModelResolver().flatten(openAPI); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + return codegen + .fromParameter( + openAPI + .getPaths() + .get(path) + .getGet() + .getParameters() + .get(0), + new HashSet<>() + ); + } + + @Test + public void setStyle() { + CodegenParameter parameter = codegenParameter("/set_style"); + assertEquals(parameter.style, "form"); + } + + @Test + public void setShouldExplode() { + CodegenParameter parameter = codegenParameter("/set_should_explode"); + assertTrue(parameter.isExplode); + } + + @Test + public void testConvertPropertyToBooleanAndWriteBack_Boolean_true() { + final DefaultCodegen codegen = new DefaultCodegen(); + Map additionalProperties = codegen.additionalProperties(); + additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, true); + boolean result = codegen.convertPropertyToBooleanAndWriteBack(CodegenConstants.SERIALIZABLE_MODEL); + Assert.assertTrue(result); + } + + @Test + public void testConvertPropertyToBooleanAndWriteBack_Boolean_false() { + final DefaultCodegen codegen = new DefaultCodegen(); + Map additionalProperties = codegen.additionalProperties(); + additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, false); + boolean result = codegen.convertPropertyToBooleanAndWriteBack(CodegenConstants.SERIALIZABLE_MODEL); + Assert.assertFalse(result); + } + + @Test + public void testConvertPropertyToBooleanAndWriteBack_String_true() { + final DefaultCodegen codegen = new DefaultCodegen(); + Map additionalProperties = codegen.additionalProperties(); + additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, "true"); + boolean result = codegen.convertPropertyToBooleanAndWriteBack(CodegenConstants.SERIALIZABLE_MODEL); + Assert.assertTrue(result); + } + + @Test + public void testConvertPropertyToBooleanAndWriteBack_String_false() { + final DefaultCodegen codegen = new DefaultCodegen(); + Map additionalProperties = codegen.additionalProperties(); + additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, "false"); + boolean result = codegen.convertPropertyToBooleanAndWriteBack(CodegenConstants.SERIALIZABLE_MODEL); + Assert.assertFalse(result); + } + + @Test + public void testConvertPropertyToBooleanAndWriteBack_String_blibb() { + final DefaultCodegen codegen = new DefaultCodegen(); + Map additionalProperties = codegen.additionalProperties(); + additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, "blibb"); + boolean result = codegen.convertPropertyToBooleanAndWriteBack(CodegenConstants.SERIALIZABLE_MODEL); + Assert.assertFalse(result); + } + } + + class CodegenWithMultipleInheritance extends DefaultCodegen { + public CodegenWithMultipleInheritance() { + super(); + supportsInheritance = true; + supportsMultipleInheritance = true; + } + } + @Test public void testFromPropertyRequiredAndOptional() { final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_12857.yaml"); diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6491.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6491.yaml new file mode 100644 index 00000000000..a0076559ff2 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue6491.yaml @@ -0,0 +1,124 @@ +openapi: 3.0.1 +info: + title: My title + description: API under test + version: 1.0.7 +servers: + - url: https://localhost:9999/root +paths: + /location: + get: + operationId: getLocation + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ArrayWithIneffectiveValidations' +components: + schemas: + ArrayWithIneffectiveValidations: + type: array + items: {} + minProperties: 1 + maxProperties: 5 + minLength: 1 + maxLength: 5 + pattern: 'abcde' + multipleOf: 3 + minimum: 1 + maximum: 10 + exclusiveMinimum: 0 + exclusiveMaximum: 100 + + ObjectWithIneffectiveValidations: + type: object + properties: + id: + type: integer + name: + type: string + minItems: 1 + maxItems: 5 + uniqueItems: true + minLength: 1 + maxLength: 10 + pattern: 'abcde' + multipleOf: 3 + minimum: 1 + maximum: 10 + exclusiveMinimum: 1 + exclusiveMaximum: 10 + + + StringWithIneffectiveValidations: + type: string + minItems: 1 + maxItems: 5 + uniqueItems: true + minProperties: 1 + maxProperties: 5 + multipleOf: 3 + minimum: 1 + maximum: 10 + exclusiveMinimum: 0 + exclusiveMaximum: 100 + + IntegerWithIneffectiveValidations: + type: integer + minItems: 1 + maxItems: 5 + uniqueItems: true + minProperties: 1 + maxProperties: 5 + minLength: 1 + maxLength: 10 + pattern: 'abcde' + + AnyTypeWithIneffectiveValidations: + minItems: 1 + maxItems: 5 + uniqueItems: true + minProperties: 1 + maxProperties: 5 + minLength: 1 + maxLength: 10 + pattern: 'abcde' + multipleOf: 4 + minimum: 1 + maximum: 99 + exclusiveMinimum: 0 + exclusiveMaximum: 100 + + BooleanWithIneffectiveValidations: + type: boolean + minItems: 1 + maxItems: 5 + uniqueItems: true + minProperties: 1 + maxProperties: 5 + minLength: 1 + maxLength: 10 + pattern: 'abcde' + multipleOf: 4 + minimum: 1 + maximum: 99 + exclusiveMinimum: 0 + exclusiveMaximum: 100 + + NullWithIneffectiveValidations: + type: null + minItems: 1 + maxItems: 5 + uniqueItems: true + minProperties: 1 + maxProperties: 5 + minLength: 1 + maxLength: 10 + pattern: 'abcde' + multipleOf: 4 + minimum: 1 + maximum: 99 + exclusiveMinimum: 0 + exclusiveMaximum: 100 diff --git a/modules/openapi-generator/src/test/resources/logback.xml b/modules/openapi-generator/src/test/resources/logback.xml new file mode 100644 index 00000000000..dc582c2c8c6 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/logback.xml @@ -0,0 +1,11 @@ + + + + [%thread] %-5level %logger - %msg%n + + + + + + + diff --git a/pom.xml b/pom.xml index e7449a7c8a8..5bd7b38f536 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,11 @@ - + + org.sonatype.oss oss-parent 5 - + + 4.0.0 org.openapitools