From fad22fe1ec0f59d4b0c4172087f08e04354bca64 Mon Sep 17 00:00:00 2001 From: altro3 Date: Fri, 26 Sep 2025 15:42:56 +0700 Subject: [PATCH] Refactor enum converters Fixed #2371 --- .../AbstractMicronautJavaCodegen.java | 6 +- .../AbstractMicronautKotlinCodegen.java | 14 +- .../io/micronaut/openapi/generator/Utils.java | 106 +++++++++- .../common/EnumConverterConfig.mustache | 42 +--- .../common/EnumConverterConfig.mustache | 35 +--- .../JavaMicronautClientCodegenTest.java | 190 +++++++++++++----- .../JavaMicronautServerCodegenTest.java | 187 ++++++++++++++--- .../KotlinMicronautClientCodegenTest.java | 129 +++++++++--- .../KotlinMicronautServerCodegenTest.java | 120 +++++++++-- 9 files changed, 615 insertions(+), 214 deletions(-) diff --git a/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautJavaCodegen.java b/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautJavaCodegen.java index eaafded674..11e9cd8f36 100644 --- a/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautJavaCodegen.java +++ b/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautJavaCodegen.java @@ -1560,7 +1560,7 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List vars) { public static void addEnumParamsForConverters( String modelPackage, + CodegenModel enumModel, CodegenParameter param, Map converterCounters, List enumParams, - List enumImports + List enumImports, + boolean isKotlin ) { var converterName = param.dataType; var alreadyAdded = false; @@ -631,17 +633,101 @@ public static void addEnumParamsForConverters( break; } } - if (!alreadyAdded) { - var counter = converterCounters.get(converterName); - if (counter == null) { - converterCounters.put(converterName, 0); - } else { - converterCounters.put(converterName, counter + 1); + if (alreadyAdded) { + return; + } + + var counter = converterCounters.get(converterName); + converterCounters.put(converterName, counter == null ? 0 : counter + 1); + param.vendorExtensions.put("converterName", converterName + (counter != null ? counter : "")); + + var convertFun = (enumModel.isNullable ? "Optional.ofNullable(" : "Optional.of(") + + param.dataType + ".fromValue(" + (isKotlin ? getKotlinEnumConvertFun(enumModel.dataType) : getJavaEnumConvertFun(enumModel.dataType, enumImports)) + "))"; + + param.vendorExtensions.put("convertFun", convertFun); + param.vendorExtensions.put("convertToStrFun", isKotlin ? getKotlinEnumConvertToStrFun(enumModel.dataType) : getJavaEnumConvertToStrFun((String) enumModel.vendorExtensions.get("baseType"))); + enumParams.add(param); + enumImports.add(modelPackage + "." + param.dataType); + } + + private static String getKotlinEnumConvertToStrFun(String type) { + return "String".equals(type) ? "v.value" : "v.value.toString()"; + } + + private static String getJavaEnumConvertToStrFun(String type) { + if ("String".equals(type)) { + return "v.getValue()"; + } else if ( + "char".equals(type) + || "byte".equals(type) + || "short".equals(type) + || "int".equals(type) + || "long".equals(type) + || "float".equals(type) + || "double".equals(type) + || "boolean".equals(type) + ) { + return "String.valueOf(v.getValue())"; + } else { + return "v.getValue().toString()"; + } + } + + + private static String getKotlinEnumConvertFun(String type) { + if ("Char".equals(type)) { + return "v[0]"; + } else if ("Byte".equals(type)) { + return "v.toByte()"; + } else if ("Short".equals(type)) { + return "v.toShort()"; + } else if ("Int".equals(type)) { + return "v.toInt()"; + } else if ("Long".equals(type)) { + return "v.toLong()"; + } else if ("Float".equals(type)) { + return "v.toFloat()"; + } else if ("Double".equals(type)) { + return "v.toDouble()"; + } else if ("Boolean".equals(type)) { + return "v.toBoolean()"; + } else if ("BigDecimal".equals(type)) { + return "v.toBigDecimal()"; + } else if ("BigInteger".equals(type)) { + return "v.toBigInteger()"; + } + return "v"; + } + + private static String getJavaEnumConvertFun(String type, List imports) { + if ("Character".equals(type) || "char".equals(type)) { + return "v.charAt(0)"; + } else if ("Byte".equals(type) || "byte".equals(type)) { + return "Byte.valueOf(v)"; + } else if ("Short".equals(type) || "short".equals(type)) { + return "Short.valueOf(v)"; + } else if ("Integer".equals(type) || "int".equals(type)) { + return "Integer.valueOf(v)"; + } else if ("Long".equals(type) || "long".equals(type)) { + return "Long.valueOf(v)"; + } else if ("Float".equals(type) || "float".equals(type)) { + return "Float.valueOf(v)"; + } else if ("Double".equals(type) || "double".equals(type)) { + return "Double.valueOf(v)"; + } else if ("Boolean".equals(type) || "boolean".equals(type)) { + return "Boolean.valueOf(v)"; + } else if ("BigDecimal".equals(type)) { + if (!imports.contains("java.math.BigDecimal")) { + imports.add("java.math.BigDecimal"); + } + return "new BigDecimal(v)"; + } else if ("BigInteger".equals(type)) { + if (!imports.contains("java.math.BigInteger")) { + imports.add("java.math.BigInteger"); } - param.vendorExtensions.put("converterName", converterName + (counter != null ? counter : "")); - enumParams.add(param); - enumImports.add(modelPackage + "." + param.dataType); + return "new BigInteger(v)"; } + return "v"; } public static boolean addUserParameter(CodegenOperation op, UserParameterMode userParameterMode, boolean isAnonymous, boolean isDenyAll) { diff --git a/openapi-generator/src/main/resources/templates/java-micronaut/common/EnumConverterConfig.mustache b/openapi-generator/src/main/resources/templates/java-micronaut/common/EnumConverterConfig.mustache index 3803f0c9f0..c21bc2a25a 100644 --- a/openapi-generator/src/main/resources/templates/java-micronaut/common/EnumConverterConfig.mustache +++ b/openapi-generator/src/main/resources/templates/java-micronaut/common/EnumConverterConfig.mustache @@ -4,65 +4,29 @@ package {{invokerPackage}}.config; import io.micronaut.context.annotation.Bean; import io.micronaut.context.annotation.Factory; import io.micronaut.core.convert.TypeConverter; -import io.micronaut.serde.ObjectMapper; {{#generatedAnnotation}} import {{javaxPackage}}.annotation.Generated; {{/generatedAnnotation}} -{{#lombok}} -import lombok.RequiredArgsConstructor; -{{/lombok}} {{#enumImports}} import {{{.}}}; {{/enumImports}} +import java.util.Optional; -import java.io.IOException; - -{{#lombok}} -@RequiredArgsConstructor -{{/lombok}} @Factory {{#generatedAnnotation}} {{>common/generatedAnnotation}} {{/generatedAnnotation}} public class {{{enumConfigClassName}}} { - - private final ObjectMapper objectMapper; -{{^lombok}} - - public {{{enumConfigClassName}}}(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; - } -{{/lombok}} {{#enumParams}} @Bean public TypeConverter toEnum{{{vendorExtensions.converterName}}}() { - return commonToEnumConverter({{{dataType}}}.class, objectMapper); + return (v, c, ctx) -> {{{vendorExtensions.convertFun}}}; } @Bean public TypeConverter<{{{dataType}}}, String> toStr{{{vendorExtensions.converterName}}}() { - return commonToStrConverter({{{dataType}}}.class, objectMapper); + return (v, c, ctx) -> Optional.of({{{vendorExtensions.convertToStrFun}}}); } {{/enumParams}} - - public static TypeConverter commonToStrConverter(Class clazz, ObjectMapper objectMapper) { - return TypeConverter.of(clazz, String.class, (value) -> { - try { - return objectMapper.writeValueAsString(value); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } - - public static TypeConverter commonToEnumConverter(Class clazz, ObjectMapper objectMapper) { - return TypeConverter.of(String.class, clazz, (value) -> { - try { - return objectMapper.readValue(value, clazz); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } } diff --git a/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/EnumConverterConfig.mustache b/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/EnumConverterConfig.mustache index b3fd73d0f5..02a44cbded 100644 --- a/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/EnumConverterConfig.mustache +++ b/openapi-generator/src/main/resources/templates/kotlin-micronaut/common/EnumConverterConfig.mustache @@ -4,52 +4,25 @@ package {{invokerPackage}}.config import io.micronaut.context.annotation.Bean import io.micronaut.context.annotation.Factory import io.micronaut.core.convert.TypeConverter -import io.micronaut.serde.ObjectMapper {{#generatedAnnotation}} import {{javaxPackage}}.annotation.Generated {{/generatedAnnotation}} {{#enumImports}} import {{{.}}} {{/enumImports}} - -import java.io.IOException +import java.util.Optional @Factory {{#generatedAnnotation}} {{>common/generatedAnnotation}} {{/generatedAnnotation}} -class {{{enumConfigClassName}}}( - private val objectMapper: ObjectMapper, -) { +class {{{enumConfigClassName}}} { {{#enumParams}} @Bean - fun toEnum{{{vendorExtensions.converterName}}}(): TypeConverter = - commonToEnumConverter({{{dataType}}}::class.java, objectMapper) + fun toEnum{{{vendorExtensions.converterName}}}() = TypeConverter { v, _, _ -> {{{vendorExtensions.convertFun}}} } @Bean - fun toStr{{{vendorExtensions.converterName}}}(): TypeConverter<{{{dataType}}}, String> = - commonToStrConverter({{{dataType}}}::class.java, objectMapper) + fun toStr{{{vendorExtensions.converterName}}}() = TypeConverter<{{{dataType}}}, String> { v, _, _ -> Optional.of({{{vendorExtensions.convertToStrFun}}}) } {{/enumParams}} - - companion object { - - fun commonToStrConverter(clazz: Class, objectMapper: ObjectMapper): TypeConverter = - TypeConverter.of(clazz, String::class.java) { - try { - objectMapper.writeValueAsString(it) - } catch (e: IOException) { - throw RuntimeException(e) - } - } - - fun commonToEnumConverter(clazz: Class, objectMapper: ObjectMapper): TypeConverter = - TypeConverter.of(String::class.java, clazz) { - try { - objectMapper.readValue(it, clazz) - } catch (e: IOException) { - throw RuntimeException(e) - } - } - } } diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java index 2c05922e7c..fbea938f78 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java @@ -1894,27 +1894,160 @@ void testEnumConvertersConfig() { "import org.openapitools.model.ShortPrimitiveEnum;", "import org.openapitools.model.StringEnum;", "public class EnumConverterClientConfig {", - "public EnumConverterClientConfig(ObjectMapper objectMapper) {", """ @Bean public TypeConverter toEnumStringEnum() { - return commonToEnumConverter(StringEnum.class, objectMapper); + return (v, c, ctx) -> Optional.of(StringEnum.fromValue(v)); } - + """, + """ @Bean public TypeConverter toStrStringEnum() { - return commonToStrConverter(StringEnum.class, objectMapper); + return (v, c, ctx) -> Optional.of(v.getValue()); + } + """, + """ + @Bean + public TypeConverter toEnumIntEnum() { + return (v, c, ctx) -> Optional.of(IntEnum.fromValue(Integer.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrIntEnum() { + return (v, c, ctx) -> Optional.of(v.getValue().toString()); + } + """, + """ + @Bean + public TypeConverter toEnumLongEnum() { + return (v, c, ctx) -> Optional.of(LongEnum.fromValue(Long.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrLongEnum() { + return (v, c, ctx) -> Optional.of(v.getValue().toString()); + } + """, + """ + @Bean + public TypeConverter toEnumDecimalEnum() { + return (v, c, ctx) -> Optional.of(DecimalEnum.fromValue(new BigDecimal(v))); + } + """, + """ + @Bean + public TypeConverter toStrDecimalEnum() { + return (v, c, ctx) -> Optional.of(v.getValue().toString()); + } + """, + """ + @Bean + public TypeConverter toEnumFloatEnum() { + return (v, c, ctx) -> Optional.of(FloatEnum.fromValue(Float.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrFloatEnum() { + return (v, c, ctx) -> Optional.of(v.getValue().toString()); + } + """, + """ + @Bean + public TypeConverter toEnumDoubleEnum() { + return (v, c, ctx) -> Optional.of(DoubleEnum.fromValue(Double.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrDoubleEnum() { + return (v, c, ctx) -> Optional.of(v.getValue().toString()); + } + """, + """ + @Bean + public TypeConverter toEnumBytePrimitiveEnum() { + return (v, c, ctx) -> Optional.of(BytePrimitiveEnum.fromValue(Byte.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrBytePrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); } """, """ @Bean public TypeConverter toEnumShortPrimitiveEnum() { - return commonToEnumConverter(ShortPrimitiveEnum.class, objectMapper); + return (v, c, ctx) -> Optional.of(ShortPrimitiveEnum.fromValue(Short.valueOf(v))); } - + """, + """ @Bean public TypeConverter toStrShortPrimitiveEnum() { - return commonToStrConverter(ShortPrimitiveEnum.class, objectMapper); + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); + } + """, + """ + @Bean + public TypeConverter toEnumIntPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(IntPrimitiveEnum.fromValue(Integer.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrIntPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); + } + """, + """ + @Bean + public TypeConverter toEnumLongPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(LongPrimitiveEnum.fromValue(Long.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrLongPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); + } + """, + """ + @Bean + public TypeConverter toEnumFloatPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(FloatPrimitiveEnum.fromValue(Float.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrFloatPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); + } + """, + """ + @Bean + public TypeConverter toEnumDoublePrimitiveEnum() { + return (v, c, ctx) -> Optional.of(DoublePrimitiveEnum.fromValue(Double.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrDoublePrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); + } + """, + """ + @Bean + public TypeConverter toEnumCharPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(CharPrimitiveEnum.fromValue(v.charAt(0))); + } + """, + """ + @Bean + public TypeConverter toStrCharPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); } """ ); @@ -1943,29 +2076,7 @@ void testEnumConvertersConfigWithCustomClientId() { "import org.openapitools.model.LongPrimitiveEnum;", "import org.openapitools.model.ShortPrimitiveEnum;", "import org.openapitools.model.StringEnum;", - "public class EnumConverterMyApiClientConfig {", - """ - @Bean - public TypeConverter toEnumStringEnum() { - return commonToEnumConverter(StringEnum.class, objectMapper); - } - - @Bean - public TypeConverter toStrStringEnum() { - return commonToStrConverter(StringEnum.class, objectMapper); - } - """, - """ - @Bean - public TypeConverter toEnumShortPrimitiveEnum() { - return commonToEnumConverter(ShortPrimitiveEnum.class, objectMapper); - } - - @Bean - public TypeConverter toStrShortPrimitiveEnum() { - return commonToStrConverter(ShortPrimitiveEnum.class, objectMapper); - } - """ + "public class EnumConverterMyApiClientConfig {" ); } @@ -1988,25 +2099,6 @@ void testEnumConvertersConfigDisabled() { assertFileDoesntExist(path + "EnumConverterClientConfig.java"); } - @Test - void testEnumConvertersWithLombok() { - var codegen = new JavaMicronautClientCodegen(); - codegen.setLombok(true); - codegen.setGeneratedAnnotation(false); - String outputPath = generateFiles(codegen, "src/test/resources/3_0/enum2.yml", false); - String path = outputPath + "src/main/java/org/openapitools/config/"; - - assertFileExists(path + "EnumConverterClientConfig.java"); - assertFileContains(path + "EnumConverterClientConfig.java", - "import lombok.RequiredArgsConstructor;", - """ - @RequiredArgsConstructor - @Factory - public class EnumConverterClientConfig { - """ - ); - } - @Test void testLocalDateTimeDefaultValue() { var codegen = new JavaMicronautClientCodegen(); diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java index 4c69fa3ce4..8089f4b57d 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java @@ -879,27 +879,160 @@ void testEnumConvertersConfig() { "import org.openapitools.model.ShortPrimitiveEnum;", "import org.openapitools.model.StringEnum;", "public class EnumConverterServerConfig {", - "public EnumConverterServerConfig(ObjectMapper objectMapper) {", """ @Bean public TypeConverter toEnumStringEnum() { - return commonToEnumConverter(StringEnum.class, objectMapper); + return (v, c, ctx) -> Optional.of(StringEnum.fromValue(v)); } - + """, + """ @Bean public TypeConverter toStrStringEnum() { - return commonToStrConverter(StringEnum.class, objectMapper); + return (v, c, ctx) -> Optional.of(v.getValue()); + } + """, + """ + @Bean + public TypeConverter toEnumIntEnum() { + return (v, c, ctx) -> Optional.of(IntEnum.fromValue(Integer.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrIntEnum() { + return (v, c, ctx) -> Optional.of(v.getValue().toString()); + } + """, + """ + @Bean + public TypeConverter toEnumLongEnum() { + return (v, c, ctx) -> Optional.of(LongEnum.fromValue(Long.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrLongEnum() { + return (v, c, ctx) -> Optional.of(v.getValue().toString()); + } + """, + """ + @Bean + public TypeConverter toEnumDecimalEnum() { + return (v, c, ctx) -> Optional.of(DecimalEnum.fromValue(new BigDecimal(v))); + } + """, + """ + @Bean + public TypeConverter toStrDecimalEnum() { + return (v, c, ctx) -> Optional.of(v.getValue().toString()); + } + """, + """ + @Bean + public TypeConverter toEnumFloatEnum() { + return (v, c, ctx) -> Optional.of(FloatEnum.fromValue(Float.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrFloatEnum() { + return (v, c, ctx) -> Optional.of(v.getValue().toString()); + } + """, + """ + @Bean + public TypeConverter toEnumDoubleEnum() { + return (v, c, ctx) -> Optional.of(DoubleEnum.fromValue(Double.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrDoubleEnum() { + return (v, c, ctx) -> Optional.of(v.getValue().toString()); + } + """, + """ + @Bean + public TypeConverter toEnumBytePrimitiveEnum() { + return (v, c, ctx) -> Optional.of(BytePrimitiveEnum.fromValue(Byte.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrBytePrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); } """, """ @Bean public TypeConverter toEnumShortPrimitiveEnum() { - return commonToEnumConverter(ShortPrimitiveEnum.class, objectMapper); + return (v, c, ctx) -> Optional.of(ShortPrimitiveEnum.fromValue(Short.valueOf(v))); } - + """, + """ @Bean public TypeConverter toStrShortPrimitiveEnum() { - return commonToStrConverter(ShortPrimitiveEnum.class, objectMapper); + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); + } + """, + """ + @Bean + public TypeConverter toEnumIntPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(IntPrimitiveEnum.fromValue(Integer.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrIntPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); + } + """, + """ + @Bean + public TypeConverter toEnumLongPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(LongPrimitiveEnum.fromValue(Long.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrLongPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); + } + """, + """ + @Bean + public TypeConverter toEnumFloatPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(FloatPrimitiveEnum.fromValue(Float.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrFloatPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); + } + """, + """ + @Bean + public TypeConverter toEnumDoublePrimitiveEnum() { + return (v, c, ctx) -> Optional.of(DoublePrimitiveEnum.fromValue(Double.valueOf(v))); + } + """, + """ + @Bean + public TypeConverter toStrDoublePrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); + } + """, + """ + @Bean + public TypeConverter toEnumCharPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(CharPrimitiveEnum.fromValue(v.charAt(0))); + } + """, + """ + @Bean + public TypeConverter toStrCharPrimitiveEnum() { + return (v, c, ctx) -> Optional.of(String.valueOf(v.getValue())); } """ ); @@ -1000,26 +1133,26 @@ void testEnumInMultipart() { assertFileExists(path + "config/EnumConverterServerConfig.java"); assertFileContains(path + "config/EnumConverterServerConfig.java", """ - @Bean - public TypeConverter toEnumDataDirection() { - return commonToEnumConverter(DataDirection.class, objectMapper); - } - - @Bean - public TypeConverter toStrDataDirection() { - return commonToStrConverter(DataDirection.class, objectMapper); - } - - @Bean - public TypeConverter toEnumDataChannel() { - return commonToEnumConverter(DataChannel.class, objectMapper); - } - - @Bean - public TypeConverter toStrDataChannel() { - return commonToStrConverter(DataChannel.class, objectMapper); - } - """ + @Bean + public TypeConverter toEnumDataDirection() { + return (v, c, ctx) -> Optional.of(DataDirection.fromValue(v)); + } + + @Bean + public TypeConverter toStrDataDirection() { + return (v, c, ctx) -> Optional.of(v.getValue()); + } + + @Bean + public TypeConverter toEnumDataChannel() { + return (v, c, ctx) -> Optional.of(DataChannel.fromValue(v)); + } + + @Bean + public TypeConverter toStrDataChannel() { + return (v, c, ctx) -> Optional.of(v.getValue()); + } + """ ); assertFileExists(path + "api/BasApi.java"); diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java index 5785931b7f..6cde867b97 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java @@ -10,7 +10,6 @@ import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CodegenConstants; -import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -2196,24 +2195,110 @@ void testEnumConvertersConfig() { "import org.openapitools.model.LongPrimitiveEnum", "import org.openapitools.model.ShortPrimitiveEnum", "import org.openapitools.model.StringEnum", - "class EnumConverterClientConfig(", + "class EnumConverterClientConfig {", """ @Bean - fun toEnumStringEnum(): TypeConverter = - commonToEnumConverter(StringEnum::class.java, objectMapper) - + fun toEnumStringEnum() = TypeConverter { v, _, _ -> Optional.of(StringEnum.fromValue(v)) } + """, + """ @Bean - fun toStrStringEnum(): TypeConverter = - commonToStrConverter(StringEnum::class.java, objectMapper) + fun toStrStringEnum() = TypeConverter { v, _, _ -> Optional.of(v.value) } """, """ @Bean - fun toEnumShortPrimitiveEnum(): TypeConverter = - commonToEnumConverter(ShortPrimitiveEnum::class.java, objectMapper) - + fun toEnumIntEnum() = TypeConverter { v, _, _ -> Optional.of(IntEnum.fromValue(v.toInt())) } + """, + """ + @Bean + fun toStrIntEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumLongEnum() = TypeConverter { v, _, _ -> Optional.of(LongEnum.fromValue(v.toLong())) } + """, + """ + @Bean + fun toStrLongEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumDecimalEnum() = TypeConverter { v, _, _ -> Optional.of(DecimalEnum.fromValue(v.toBigDecimal())) } + """, + """ + @Bean + fun toStrDecimalEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumFloatEnum() = TypeConverter { v, _, _ -> Optional.of(FloatEnum.fromValue(v.toFloat())) } + """, + """ + @Bean + fun toStrFloatEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumDoubleEnum() = TypeConverter { v, _, _ -> Optional.of(DoubleEnum.fromValue(v.toDouble())) } + """, + """ + @Bean + fun toStrDoubleEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumBytePrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(BytePrimitiveEnum.fromValue(v.toByte())) } + """, + """ + @Bean + fun toStrBytePrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumShortPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(ShortPrimitiveEnum.fromValue(v.toShort())) } + """, + """ + @Bean + fun toStrShortPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ @Bean - fun toStrShortPrimitiveEnum(): TypeConverter = - commonToStrConverter(ShortPrimitiveEnum::class.java, objectMapper) + fun toEnumIntPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(IntPrimitiveEnum.fromValue(v.toInt())) } + """, + """ + @Bean + fun toStrIntPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumLongPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(LongPrimitiveEnum.fromValue(v.toLong())) } + """, + """ + @Bean + fun toStrLongPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumFloatPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(FloatPrimitiveEnum.fromValue(v.toFloat())) } + """, + """ + @Bean + fun toStrFloatPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumDoublePrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(DoublePrimitiveEnum.fromValue(v.toDouble())) } + """, + """ + @Bean + fun toStrDoublePrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumCharPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(CharPrimitiveEnum.fromValue(v[0])) } + """, + """ + @Bean + fun toStrCharPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } """ ); } @@ -2241,25 +2326,7 @@ void testEnumConvertersConfigWithCustomClientId() { "import org.openapitools.model.LongPrimitiveEnum", "import org.openapitools.model.ShortPrimitiveEnum", "import org.openapitools.model.StringEnum", - "class EnumConverterMyApiClientConfig(", - """ - @Bean - fun toEnumStringEnum(): TypeConverter = - commonToEnumConverter(StringEnum::class.java, objectMapper) - - @Bean - fun toStrStringEnum(): TypeConverter = - commonToStrConverter(StringEnum::class.java, objectMapper) - """, - """ - @Bean - fun toEnumShortPrimitiveEnum(): TypeConverter = - commonToEnumConverter(ShortPrimitiveEnum::class.java, objectMapper) - - @Bean - fun toStrShortPrimitiveEnum(): TypeConverter = - commonToStrConverter(ShortPrimitiveEnum::class.java, objectMapper) - """ + "class EnumConverterMyApiClientConfig {" ); } diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java index 5a5120dd97..9fd2d026b7 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java @@ -1109,24 +1109,110 @@ void testEnumConvertersConfig() { "import org.openapitools.model.LongPrimitiveEnum", "import org.openapitools.model.ShortPrimitiveEnum", "import org.openapitools.model.StringEnum", - "class EnumConverterServerConfig(", + "class EnumConverterServerConfig {", """ @Bean - fun toEnumStringEnum(): TypeConverter = - commonToEnumConverter(StringEnum::class.java, objectMapper) - + fun toEnumStringEnum() = TypeConverter { v, _, _ -> Optional.of(StringEnum.fromValue(v)) } + """, + """ @Bean - fun toStrStringEnum(): TypeConverter = - commonToStrConverter(StringEnum::class.java, objectMapper) + fun toStrStringEnum() = TypeConverter { v, _, _ -> Optional.of(v.value) } """, """ @Bean - fun toEnumShortPrimitiveEnum(): TypeConverter = - commonToEnumConverter(ShortPrimitiveEnum::class.java, objectMapper) - + fun toEnumIntEnum() = TypeConverter { v, _, _ -> Optional.of(IntEnum.fromValue(v.toInt())) } + """, + """ + @Bean + fun toStrIntEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumLongEnum() = TypeConverter { v, _, _ -> Optional.of(LongEnum.fromValue(v.toLong())) } + """, + """ + @Bean + fun toStrLongEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumDecimalEnum() = TypeConverter { v, _, _ -> Optional.of(DecimalEnum.fromValue(v.toBigDecimal())) } + """, + """ + @Bean + fun toStrDecimalEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumFloatEnum() = TypeConverter { v, _, _ -> Optional.of(FloatEnum.fromValue(v.toFloat())) } + """, + """ + @Bean + fun toStrFloatEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumDoubleEnum() = TypeConverter { v, _, _ -> Optional.of(DoubleEnum.fromValue(v.toDouble())) } + """, + """ + @Bean + fun toStrDoubleEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumBytePrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(BytePrimitiveEnum.fromValue(v.toByte())) } + """, + """ + @Bean + fun toStrBytePrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumShortPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(ShortPrimitiveEnum.fromValue(v.toShort())) } + """, + """ + @Bean + fun toStrShortPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumIntPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(IntPrimitiveEnum.fromValue(v.toInt())) } + """, + """ + @Bean + fun toStrIntPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumLongPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(LongPrimitiveEnum.fromValue(v.toLong())) } + """, + """ + @Bean + fun toStrLongPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumFloatPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(FloatPrimitiveEnum.fromValue(v.toFloat())) } + """, + """ + @Bean + fun toStrFloatPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumDoublePrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(DoublePrimitiveEnum.fromValue(v.toDouble())) } + """, + """ + @Bean + fun toStrDoublePrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } + """, + """ + @Bean + fun toEnumCharPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(CharPrimitiveEnum.fromValue(v[0])) } + """, + """ @Bean - fun toStrShortPrimitiveEnum(): TypeConverter = - commonToStrConverter(ShortPrimitiveEnum::class.java, objectMapper) + fun toStrCharPrimitiveEnum() = TypeConverter { v, _, _ -> Optional.of(v.value.toString()) } """ ); } @@ -1242,20 +1328,16 @@ void testEnumInMultipart() { assertFileContains(path + "config/EnumConverterServerConfig.kt", """ @Bean - fun toEnumDataDirection(): TypeConverter = - commonToEnumConverter(DataDirection::class.java, objectMapper) + fun toEnumDataDirection() = TypeConverter { v, _, _ -> Optional.of(DataDirection.fromValue(v)) } @Bean - fun toStrDataDirection(): TypeConverter = - commonToStrConverter(DataDirection::class.java, objectMapper) + fun toStrDataDirection() = TypeConverter { v, _, _ -> Optional.of(v.value) } @Bean - fun toEnumDataChannel(): TypeConverter = - commonToEnumConverter(DataChannel::class.java, objectMapper) + fun toEnumDataChannel() = TypeConverter { v, _, _ -> Optional.of(DataChannel.fromValue(v)) } @Bean - fun toStrDataChannel(): TypeConverter = - commonToStrConverter(DataChannel::class.java, objectMapper) + fun toStrDataChannel() = TypeConverter { v, _, _ -> Optional.of(v.value) } """ );