diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java index 5b936c507d58..540383889c2a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java @@ -515,6 +515,7 @@ public static enum ENUM_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case, public static final String X_NULLABLE = "x-nullable"; public static final String X_ENUM_VARNAMES = "x-enum-varnames"; public static final String X_ENUM_DESCRIPTIONS = "x-enum-descriptions"; + public static final String X_ENUM_DEPRECATED = "x-enum-deprecated"; public static final String X_PY_TYPING = "x-py-typing"; public static final String X_PY_EXAMPLE = "x-py-example"; public static final String X_PY_EXAMPLE_IMPORT = "x-py-example-import"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index e4775e8cd8b1..6ee7949ec60e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -27,9 +27,9 @@ 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.oas.models.security.SecurityScheme.Type; import io.swagger.v3.oas.models.security.SecurityRequirement; import org.apache.commons.lang3.StringUtils; +import org.openapitools.codegen.utils.EnumUtils; import org.openapitools.codegen.utils.ModelUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -1642,8 +1642,7 @@ protected Schema processSimplifyOneOfEnum(Schema schema) { * @return Simplified schema */ protected Schema simplifyComposedSchemaWithEnums(Schema schema, List subSchemas, String composedType) { - Map enumValues = new LinkedHashMap<>(); - Map deprecatedValues = new LinkedHashMap<>(); + Map enumExtensions = new LinkedHashMap<>(); if(schema.getTypes() != null && schema.getTypes().size() > 1) { // we cannot handle enums with multiple types @@ -1697,32 +1696,27 @@ protected Schema simplifyComposedSchemaWithEnums(Schema schema, List sub } description += subSchema.getDescription(); } - enumValues.put(subSchemaEnumValues.get(0), description); - deprecatedValues.put(subSchemaEnumValues.get(0), subSchemaDeprecated); + enumExtensions.put(subSchemaEnumValues.get(0), new EnumUtils.EnumExtensions(description, subSchemaDeprecated)); } else { for(Object e: subSchemaEnumValues) { - enumValues.put(e, ""); - deprecatedValues.put(e, subSchemaDeprecated); + enumExtensions.put(e, new EnumUtils.EnumExtensions("", subSchemaDeprecated)); } } - } - return createSimplifiedEnumSchema(schema, enumValues, deprecatedValues, schemaType, composedType); + return createSimplifiedEnumSchema(schema, enumExtensions, schemaType, composedType); } - /** * Creates a simplified enum schema from collected enum values. * * @param originalSchema Original schema to modify - * @param enumValues Collected enum values - * @param deprecatedValues Per-value deprecated flags (aligned with enumValues key order) + * @param enumExtensions Collected enum values * @param schemaType Consistent type across sub-schemas * @param composedType Type of composed schema being simplified * @return Simplified enum schema */ - protected Schema createSimplifiedEnumSchema(Schema originalSchema, Map enumValues, Map deprecatedValues, String schemaType, String composedType) { + protected Schema createSimplifiedEnumSchema(Schema originalSchema, Map enumExtensions, String schemaType, String composedType) { // Clear the composed schema type if ("oneOf".equals(composedType)) { originalSchema.setOneOf(null); @@ -1730,20 +1724,7 @@ protected Schema createSimplifiedEnumSchema(Schema originalSchema, Map(enumValues.keySet())); - if(enumValues.values().stream().anyMatch(e -> !e.isEmpty())) { - //set x-enum-descriptions only if there's at least one non-empty description - originalSchema.addExtension(X_ENUM_DESCRIPTIONS, new ArrayList<>(enumValues.values())); - } - if (deprecatedValues != null && deprecatedValues.values().stream().anyMatch(Boolean.TRUE::equals)) { - // preserve per-value deprecated flags from OAS 3.1 oneOf/anyOf + const sub-schemas - originalSchema.addExtension("x-enum-deprecated", new ArrayList<>(deprecatedValues.values())); - } + EnumUtils.createSimplifiedEnumSchema(originalSchema, enumExtensions, schemaType); LOGGER.debug("Simplified {} with enum sub-schemas to single enum: {}", composedType, originalSchema); @@ -1835,7 +1816,7 @@ protected Schema processReplaceOneOfByMapping(Schema schema) { return schema; } Map mappings = new TreeMap<>(); - // is the discriminator qttribute qlready in this schema? + // is the discriminator attribute already in this schema? // if yes, it will be deleted in references oneOf to avoid duplicates boolean hasProperty = findProperty(schema, discriminator.getPropertyName(), false, new HashSet<>()) != null; discriminator.setMapping(mappings); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/EnumUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/EnumUtils.java new file mode 100644 index 000000000000..d0d8ab6eb7d2 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/EnumUtils.java @@ -0,0 +1,56 @@ +package org.openapitools.codegen.utils; + +import io.swagger.v3.oas.models.media.Schema; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.openapitools.codegen.CodegenConstants.X_ENUM_DEPRECATED; +import static org.openapitools.codegen.CodegenConstants.X_ENUM_DESCRIPTIONS; + +public class EnumUtils { + + public static Schema createSimplifiedEnumSchema(Schema originalSchema, + Map enums, + String schemaType) { + if (ModelUtils.getType(originalSchema) == null && schemaType != null) { + //if type was specified in subschemas, keep it in the main schema + ModelUtils.setType(originalSchema, schemaType); + } + + originalSchema.setEnum(new ArrayList<>(enums.keySet())); + List enumDescriptions = enums.values().stream().map(EnumExtensions::getDescription).collect(Collectors.toList()); + List enumDeprecations = enums.values().stream().map(EnumExtensions::isDeprecated).collect(Collectors.toList()); + if(enumDescriptions.stream().anyMatch(e -> !e.isEmpty())) { + //set x-enum-descriptions only if there's at least one non-empty description + originalSchema.addExtension(X_ENUM_DESCRIPTIONS, new ArrayList<>(enumDescriptions)); + } + if (enumDeprecations.stream().anyMatch(Boolean.TRUE::equals)) { + // preserve per-value deprecated flags from OAS 3.1 oneOf/anyOf + const sub-schemas + originalSchema.addExtension(X_ENUM_DEPRECATED, new ArrayList<>(enumDeprecations)); + } + + return originalSchema; + } + + public static class EnumExtensions { + private final String description; + private final boolean deprecated; + + public EnumExtensions(String description, boolean deprecated) { + this.description = description; + this.deprecated = deprecated; + } + + public String getDescription() { + return description; + } + + public boolean isDeprecated() { + return deprecated; + } + } + +}