Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix generating non string enums. #1451

Merged
Merged
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 @@ -256,6 +256,7 @@ protected AbstractMicronautJavaCodegen() {
importMapping.put("ZonedDateTime", "java.time.ZonedDateTime");
importMapping.put("LocalDate", "java.time.LocalDate");
importMapping.put("LocalTime", "java.time.LocalTime");
importMapping.put("Function", "java.util.function.Function");
}

public void setGenerateHttpResponseAlways(boolean generateHttpResponseAlways) {
Expand Down Expand Up @@ -813,6 +814,26 @@ public CodegenModel fromModel(String name, Schema model) {
return codegenModel;
}

@Override
public String toEnumValue(String value, String datatype) {
if ("Integer".equals(datatype) || "Double".equals(datatype)) {
return value;
} else if ("Long".equals(datatype)) {
// add l to number, e.g. 2048 => 2048L
return value + "L";
} else if ("Float".equals(datatype)) {
// add f to number, e.g. 3.14 => 3.14F
return value + "F";
} else if ("BigDecimal".equals(datatype)) {
// use BigDecimal String constructor
return "new BigDecimal(\"" + value + "\")";
} else if ("URI".equals(datatype)) {
return "URI.create(\"" + escapeText(value) + "\")";
} else {
return "\"" + escapeText(value) + "\"";
}
}

@Override
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers) {
CodegenOperation op = super.fromOperation(path, httpMethod, operation, servers);
Expand Down Expand Up @@ -1084,6 +1105,9 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
for (var property : model.requiredVars) {
processProperty(property, isServer, objs);
}
if (model.isEnum) {
addImport(model, "Function");
}
addStrValueToEnum(model);
}

Expand Down Expand Up @@ -1240,7 +1264,7 @@ public String getExampleValue(
} else if ("LocalDateTime".equals(dataType)) {
example = "LocalDateTime.of(2001, 2, 3, 4, 5)";
} else if ("BigDecimal".equals(dataType)) {
example = "new BigDecimal(78)";
example = "new BigDecimal(\"78\")";
} else if (allowableValues != null && !allowableValues.isEmpty()) {
// This is an enum
Object value = example;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ protected AbstractMicronautKotlinCodegen() {
importMapping.put("ZonedDateTime", "java.time.ZonedDateTime");
importMapping.put("LocalDate", "java.time.LocalDate");
importMapping.put("LocalTime", "java.time.LocalTime");
importMapping.put("BigDecimal", "java.math.BigDecimal");
}

public void setGenerateHttpResponseAlways(boolean generateHttpResponseAlways) {
Expand Down Expand Up @@ -823,11 +824,36 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
return objs;
}

@Override
public String toEnumValue(String value, String datatype) {
if ("Integer".equals(datatype)
|| "Double".equals(datatype)
|| "Int".equals(datatype)) {
return value;
} else if ("Long".equals(datatype)) {
// add l to number, e.g. 2048 => 2048l
return value + "L";
} else if ("Float".equals(datatype)) {
// add f to number, e.g. 3.14 => 3.14f
return value + "F";
} else if ("BigDecimal".equals(datatype)) {
// use BigDecimal String constructor
return "BigDecimal(\"" + value + "\")";
} else if ("URI".equals(datatype)) {
return "URI.create(\"" + escapeText(value) + "\")";
} else {
return "\"" + escapeText(value) + "\"";
}
}

@Override
public CodegenModel fromModel(String name, Schema model) {
CodegenModel codegenModel = super.fromModel(name, model);
codegenModel.imports.remove("ApiModel");
codegenModel.imports.remove("ApiModelProperty");
if ("BigDecimal".equals(codegenModel.dataType)) {
codegenModel.imports.add("BigDecimal");
}
allModels.put(name, codegenModel);
return codegenModel;
}
Expand Down Expand Up @@ -1406,7 +1432,7 @@ public String getExampleValue(
} else if ("ByteArray".equals(dataType)) {
example = "ByteArray(10)";
} else if ("BigDecimal".equals(dataType)) {
example = "BigDecimal(78)";
example = "BigDecimal(\"78\")";
} else if (allowableValues != null && !allowableValues.isEmpty()) {
// This is an enum
Object value = example;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,12 @@ public static void addStrValueToEnum(CodegenModel model) {
if (argPos >= 0) {
value = value.substring(argPos + 1, value.indexOf(')'));
}
var upperValue = value.toUpperCase();
if (upperValue.endsWith("F")
|| upperValue.endsWith("L")
|| upperValue.endsWith("D")) {
value = value.substring(0, value.length() - 1);
}
if (!value.contains("\"")) {
value = "\"" + value + "\"";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
{{/enumVars}}
{{/allowableValues}}

{{#formatSingleLine}}public final static Map<{{{dataType}}}, {{>common/model/enumName}}> VALUE_MAPPING = Map.copyOf(Arrays.stream(values()){{/formatSingleLine}}
.collect(Collectors.toMap(v -> v.value{{#isString}}{{#useEnumCaseInsensitive}}.toLowerCase(){{/useEnumCaseInsensitive}}{{/isString}}, Function.identity())));

private final {{{dataType}}} value;
{{^lombok}}

Expand All @@ -58,18 +61,17 @@
return String.valueOf(value);
}

{{#formatSingleLine}}public final static Map<{{{dataType}}}, {{>common/model/enumName}}> VALUE_MAPPING = Map.copyOf(Arrays.stream(values()){{/formatSingleLine}}
.collect(Collectors.toMap(v -> v.value{{#isString}}{{#useEnumCaseInsensitive}}.toLowerCase(){{/useEnumCaseInsensitive}}{{/isString}}, v -> v)));

/**
* Create this enum from a value.
*
* @param value the value
*
* @return The enum
*/
{{#jackson}}
@JsonCreator
{{/jackson}}
{{#formatSingleLine}}public static {{>common/model/enumName}} fromValue(String value){{/formatSingleLine}} {
{{#formatSingleLine}}public static {{>common/model/enumName}} fromValue({{{dataType}}} value){{/formatSingleLine}} {
{{^isNullable}}
if (!VALUE_MAPPING.containsKey(value{{#isString}}{{#useEnumCaseInsensitive}}.toLowerCase(){{/useEnumCaseInsensitive}}{{/isString}})) {
throw new IllegalArgumentException("Unexpected value '" + value + "'");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
{{#models}}
{{#model}}
{{#isEnum}}
import java.util.function.Function;

{{>common/model/enum}}
{{/isEnum}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
{{{.}}}
{{/additionalEnumTypeAnnotations}}
{{#nonPublicApi}}internal {{/nonPublicApi}}{{#formatSingleLine}}enum class {{>common/model/enumName}}{{/formatSingleLine}} (
@get:JsonValue val value: String
@get:JsonValue val value: {{{dataType}}}
) {

{{#allowableValues}}
Expand All @@ -36,7 +36,7 @@
{{/allowableValues}}

override fun toString(): String {
return value
return {{#isString}}value{{/isString}}{{^isString}}"$value"{{/isString}}
}

companion object {
Expand All @@ -53,7 +53,7 @@
*/
@JsonCreator
@JvmStatic
fun fromValue(value: String): {{>common/model/enumName}}{{#isNullable}}?{{/isNullable}} {
fun fromValue(value: {{{dataType}}}): {{>common/model/enumName}}{{#isNullable}}?{{/isNullable}} {
{{^isNullable}}
require(VALUE_MAPPING.containsKey(value)) { "Unexpected value '$value'" }
{{/isNullable}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,9 @@ void testEnumsWithNonStringTypeValue() {
String outputPath = generateFiles(codegen, "src/test/resources/3_0/enum.yml", CodegenConstants.APIS, CodegenConstants.MODELS);
String modelPath = outputPath + "src/main/java/org/openapitools/model/";

assertFileContains(modelPath + "StringEnum.java", "@JsonProperty(\"starting\")");
assertFileContains(modelPath + "IntEnum.java", "@JsonProperty(\"1\")");
assertFileContains(modelPath + "DecimalEnum.java", "@JsonProperty(\"1.23\")");
assertFileContains(modelPath + "StringEnum.java", "@JsonProperty(\"starting\")", "STARTING(\"starting\"),");
assertFileContains(modelPath + "IntEnum.java", "@JsonProperty(\"1\")", "NUMBER_1(1),");
assertFileContains(modelPath + "LongEnum.java", "@JsonProperty(\"1\")", "NUMBER_3(3L),");
assertFileContains(modelPath + "DecimalEnum.java", "@JsonProperty(\"1.23\")", "NUMBER_34_DOT_1(new BigDecimal(\"34.1\"))");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,9 @@ void testEnumsWithNonStringTypeValue() {
String outputPath = generateFiles(codegen, "src/test/resources/3_0/enum.yml", CodegenConstants.APIS, CodegenConstants.MODELS);
String modelPath = outputPath + "src/main/kotlin/org/openapitools/model/";

assertFileContains(modelPath + "StringEnum.kt", "@JsonProperty(\"starting\")");
assertFileContains(modelPath + "IntEnum.kt", "@JsonProperty(\"1\")");
assertFileContains(modelPath + "DecimalEnum.kt", "@JsonProperty(\"1.23\")");
assertFileContains(modelPath + "StringEnum.kt", "@JsonProperty(\"starting\")", "STARTING(\"starting\"),");
assertFileContains(modelPath + "IntEnum.kt", "@JsonProperty(\"1\")", "_1(1),");
assertFileContains(modelPath + "LongEnum.kt", "@JsonProperty(\"1\")", "_3(3L),");
assertFileContains(modelPath + "DecimalEnum.kt", "@JsonProperty(\"1.23\")", "_34_1(BigDecimal(\"34.1\"))");
}
}
9 changes: 9 additions & 0 deletions openapi-generator/src/test/resources/3_0/enum.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ paths:
required: true
schema:
$ref: "#/components/schemas/IntEnum"
- name: longEnum
in: query
required: true
schema:
$ref: "#/components/schemas/LongEnum"
- name: boolEnum
in: query
required: true
Expand All @@ -44,6 +49,10 @@ components:
IntEnum:
type: integer
enum: [1, 2, 3, 4, 5]
LongEnum:
type: integer
format: int64
enum: [1, 2, 3, 4, 5]
BooleanEnum:
type: boolean
enum: ['true', 'false']
Expand Down
Loading