Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ additionalProperties:
useSwaggerUI: "false"
interfaceOnly: "true"
useSpringBoot3: "true"
enumUnknownDefaultCase: "true"
1 change: 1 addition & 0 deletions docs/generators/kotlin-spring.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|delegatePattern|Whether to generate the server files using the delegate pattern| |false|
|documentationProvider|Select the OpenAPI documentation provider.|<dl><dt>**none**</dt><dd>Do not publish an OpenAPI specification.</dd><dt>**source**</dt><dd>Publish the original input OpenAPI specification.</dd><dt>**springdoc**</dt><dd>Generate an OpenAPI 3 specification using SpringDoc.</dd></dl>|springdoc|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', 'original', and 'bestEffortBacktick' (like 'original' but tries to wrap values in backticks before falling back to sanitizing, e.g. `name,asc` stays `name,asc` rather than becoming nameCommaAsc; useful for sort/order enums)| |original|
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response. With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|<dl><dt>**false**</dt><dd>No changes to the enums are made, this is the default option.</dd><dt>**true**</dt><dd>With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.</dd></dl>|false|
|exceptionHandler|generate default global exception handlers (not compatible with reactive. enabling reactive will disable exceptionHandler )| |true|
|generatePageableConstraintValidation|Generate a @ValidPageable annotation and PageableConstraintValidator class, and apply @ValidPageable to the injected Pageable parameter of operations whose 'page' or 'size' parameter specifies a maximum constraint. The annotation enforces those constraints on the Pageable object that replaces the individual page/size query parameters. Requires useBeanValidation=true and library=spring-boot.| |false|
|generateSortValidation|Generate a @ValidSort annotation and SortValidator class, and apply @ValidSort to the injected Pageable parameter of operations whose 'sort' parameter has enum values. The annotation validates that sort values in the Pageable object match the allowed enum values from the spec. Requires useBeanValidation=true and library=spring-boot.| |false|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ public KotlinSpringServerCodegen() {
addSwitch(COMPANION_OBJECT, "Whether to generate companion objects in data classes, enabling companion extensions.", companionObject);
addSwitch(SUSPEND_FUNCTIONS, "Whether to generate suspend functions for API operations. Useful for Spring MVC with Kotlin coroutines without requiring the full reactive stack.", suspendFunctions);
cliOptions.add(CliOption.newBoolean(CodegenConstants.USE_DEDUCTION_FOR_ONE_OF_INTERFACES, CodegenConstants.USE_DEDUCTION_FOR_ONE_OF_INTERFACES_DESC, useDeductionForOneOfInterfaces));
cliOptions.add(CliOption.newBoolean(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE, CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE_DESC).defaultValue("false"));

addSwitch(CodegenConstants.USE_ENUM_VALUE_INTERFACE, CodegenConstants.USE_ENUM_VALUE_INTERFACE_DESC, useEnumValueInterface);
addSwitch(CodegenConstants.OPENAPI_NULLABLE,
"Enable OpenAPI Jackson Nullable library (jackson-databind-nullable) for optional + nullable "
Expand Down Expand Up @@ -659,6 +661,11 @@ public void processOpts() {
}
writePropertyBack(SKIP_DEFAULT_INTERFACE, skipDefaultInterface);


if (additionalProperties.containsKey(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE)) {
setEnumUnknownDefaultCase(Boolean.parseBoolean(additionalProperties.get(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE).toString()));
}

if (additionalProperties.containsKey(REACTIVE)) {
if (SPRING_CLOUD_LIBRARY.equals(library)) {
throw new IllegalArgumentException("Currently, reactive option doesn't supported by Spring Cloud");
Expand Down Expand Up @@ -1520,6 +1527,18 @@ public ModelsMap postProcessModelsEnum(ModelsMap objs) {
}
}

// If enumUnknownDefaultCase is enabled, remove "unknown_default_open_api" from allowableValues
if (additionalProperties.containsKey(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE) &&
Boolean.parseBoolean(additionalProperties.get(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE).toString())) {

for (ModelMap modelMap : objs.getModels()) {
CodegenModel cm = modelMap.getModel();
if (cm.isEnum && cm.allowableValues != null) {
cm.allowableValues.removeIf(av -> "unknown_default_open_api".equals(av.value));
}
}
}

if (useEnumValueInterface) {
EnumValueInterfaceUtils.injectInPostProcessModelsEnum(
objs, valuedEnumClassName, importMapping.get("ValuedEnum"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,15 @@
*/
enum class {{{nameInPascalCase}}}(@get:JsonValue {{#useEnumValueInterface}}{{^isContainer}}override {{/isContainer}}{{/useEnumValueInterface}}val value: {{#isContainer}}{{#items}}{{{dataType}}}{{/items}}{{/isContainer}}{{^isContainer}}{{{dataType}}}{{/isContainer}}) {{#vendorExtensions.x-kotlin-implements}}{{#-first}}: {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}} {{/vendorExtensions.x-kotlin-implements}}{
{{#allowableValues}}{{#enumVars}}
{{{name}}}({{{value}}}){{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}};
{{{name}}}({{{value}}}){{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}{{#enumUnknownDefaultCase}},
UNKNOWN_DEFAULT_OPEN_API({{#isString}}"unknown_default_open_api"{{/isString}}{{^isString}}{{#isLong}}11184809L{{/isLong}}{{#isInteger}}11184809{{/isInteger}}{{#isNumber}}11184809{{/isNumber}}{{#isDouble}}11184809.0{{/isDouble}}{{#isFloat}}11184809.0f{{/isFloat}}{{/isString}}){{/enumUnknownDefaultCase}};

companion object {
@JvmStatic
@JsonCreator
fun forValue(value: {{#isContainer}}{{#items}}{{{dataType}}}{{/items}}{{/isContainer}}{{^isContainer}}{{{dataType}}}{{/isContainer}}): {{{nameInPascalCase}}} {
return values().firstOrNull{it -> it.value == value}
?: throw IllegalArgumentException("Unexpected value '$value' for enum '{{nameInPascalCase}}'")
{{^enumUnknownDefaultCase}}?: throw IllegalArgumentException("Unexpected value '$value' for enum '{{nameInPascalCase}}'"){{/enumUnknownDefaultCase}}{{#enumUnknownDefaultCase}}?: UNKNOWN_DEFAULT_OPEN_API{{/enumUnknownDefaultCase}}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
/**
* {{{description}}}
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
*/
enum class {{classname}}(@get:JsonValue {{#useEnumValueInterface}}override {{/useEnumValueInterface}}val value: {{dataType}}) {{#vendorExtensions.x-kotlin-implements}}{{#-first}}: {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}} {{/vendorExtensions.x-kotlin-implements}}{
* {{{description}}}
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
*/
enum class {{classname}}(
@get:JsonValue {{#useEnumValueInterface}}override {{/useEnumValueInterface}}val value: {{dataType}}
) {{#vendorExtensions.x-kotlin-implements}}{{#-first}}: {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-kotlin-implements}} {

{{#allowableValues}}{{#enumVars}}
{{&name}}({{{value}}}){{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}};
{{&name}}({{{value}}}){{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
{{#enumUnknownDefaultCase}},
UNKNOWN_DEFAULT_OPEN_API({{#isString}}"unknown_default_open_api"{{/isString}}{{^isString}}{{#dataType}}null{{/dataType}}{{/isString}})
{{/enumUnknownDefaultCase}};

companion object {
@JvmStatic
@JsonCreator
fun forValue(value: {{dataType}}): {{classname}} {
return values().firstOrNull{it -> it.value == value}
?: throw IllegalArgumentException("Unexpected value '$value' for enum '{{classname}}'")
return values().firstOrNull { it.value == value }
{{#enumUnknownDefaultCase}}
?: UNKNOWN_DEFAULT_OPEN_API
{{/enumUnknownDefaultCase}}
{{^enumUnknownDefaultCase}}
?: throw IllegalArgumentException(
"Unexpected value '$value' for enum '{{classname}}'"
)
{{/enumUnknownDefaultCase}}
}
}
}
Loading