From 059fdca43fad5e92d00e1483c8eea63f80104bf0 Mon Sep 17 00:00:00 2001 From: andrewwilsonnew Date: Tue, 8 Apr 2025 13:51:22 +0100 Subject: [PATCH 1/5] improving with simple enum names --- .../languages/ProtobufSchemaCodegen.java | 24 ++++--- .../protobuf/ProtobufSchemaCodegenTest.java | 72 +++++++++++++++++++ 2 files changed, 88 insertions(+), 8 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java index 362249ab3be2..96d030515f65 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java @@ -66,6 +66,8 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf public static final String WRAP_COMPLEX_TYPE = "wrapComplexType"; + public static final String SIMPLE_ENUM_NAME = "enumSimpleName"; + public static final String AGGREGATE_MODELS_NAME = "aggregateModelsName"; private final Logger LOGGER = LoggerFactory.getLogger(ProtobufSchemaCodegen.class); @@ -82,6 +84,8 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf private boolean wrapComplexType = true; + private boolean simpleEnumName = false; + @Override public CodegenType getTag() { return CodegenType.SCHEMA; @@ -192,6 +196,7 @@ public ProtobufSchemaCodegen() { addSwitch(START_ENUMS_WITH_UNSPECIFIED, "Introduces \"UNSPECIFIED\" as the first element of enumerations.", startEnumsWithUnspecified); addSwitch(ADD_JSON_NAME_ANNOTATION, "Append \"json_name\" annotation to message field when the specification name differs from the protobuf field name", addJsonNameAnnotation); addSwitch(WRAP_COMPLEX_TYPE, "Generate Additional message for complex type", wrapComplexType); + addSwitch(SIMPLE_ENUM_NAME, "Use a simple name for enums", simpleEnumName); addOption(AGGREGATE_MODELS_NAME, "Aggregated model filename. If set, all generated models will be combined into this single file.", null); } @@ -219,22 +224,26 @@ public void processOpts() { additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); } - if (additionalProperties.containsKey(this.NUMBERED_FIELD_NUMBER_LIST)) { + if (additionalProperties.containsKey(NUMBERED_FIELD_NUMBER_LIST)) { this.numberedFieldNumberList = convertPropertyToBooleanAndWriteBack(NUMBERED_FIELD_NUMBER_LIST); } - if (additionalProperties.containsKey(this.START_ENUMS_WITH_UNSPECIFIED)) { + if (additionalProperties.containsKey(START_ENUMS_WITH_UNSPECIFIED)) { this.startEnumsWithUnspecified = convertPropertyToBooleanAndWriteBack(START_ENUMS_WITH_UNSPECIFIED); } - if (additionalProperties.containsKey(this.ADD_JSON_NAME_ANNOTATION)) { + if (additionalProperties.containsKey(ADD_JSON_NAME_ANNOTATION)) { this.addJsonNameAnnotation = convertPropertyToBooleanAndWriteBack(ADD_JSON_NAME_ANNOTATION); } - if (additionalProperties.containsKey(this.WRAP_COMPLEX_TYPE)) { + if (additionalProperties.containsKey(WRAP_COMPLEX_TYPE)) { this.wrapComplexType = convertPropertyToBooleanAndWriteBack(WRAP_COMPLEX_TYPE); } + if (additionalProperties.containsKey(SIMPLE_ENUM_NAME)) { + this.simpleEnumName = convertPropertyToBooleanAndWriteBack(SIMPLE_ENUM_NAME); + } + if (additionalProperties.containsKey(AGGREGATE_MODELS_NAME)) { this.setAggregateModelsName((String) additionalProperties.get(AGGREGATE_MODELS_NAME)); } @@ -489,16 +498,15 @@ public void addEnumValuesPrefix(Map allowableValues, String pref prefix = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, prefix); for (Map value : enumVars) { String name = (String) value.get("name"); - value.put("name", prefix + "_" + name); - value.put("value", "\"" + prefix + "_" + name + "\""); - + value.put("name", simpleEnumName ? name : prefix + "_" + name); + value.put("value", simpleEnumName ? name : "\"" + prefix + "_" + name + "\""); } } if (allowableValues.containsKey("values")) { List values = (List) allowableValues.get("values"); for (Object value : values) { - value = prefix + "_" + String.valueOf(value); + value = simpleEnumName ? value : prefix + "_" + value; } } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/protobuf/ProtobufSchemaCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/protobuf/ProtobufSchemaCodegenTest.java index 0ab92922dd74..8a3c5951aa78 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/protobuf/ProtobufSchemaCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/protobuf/ProtobufSchemaCodegenTest.java @@ -17,8 +17,12 @@ package org.openapitools.codegen.protobuf; import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.IntegerSchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.media.StringSchema; import org.openapitools.codegen.ClientOptInput; import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenProperty; import org.openapitools.codegen.DefaultGenerator; import org.openapitools.codegen.TestUtils; import org.openapitools.codegen.config.CodegenConfigurator; @@ -34,8 +38,12 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import java.util.List; +import java.util.Map; +import static org.openapitools.codegen.TestUtils.createCodegenModelWrapper; +import static org.openapitools.codegen.languages.ProtobufSchemaCodegen.SIMPLE_ENUM_NAME; import static org.testng.Assert.assertEquals; public class ProtobufSchemaCodegenTest { @@ -141,4 +149,68 @@ public void modelTest() { Assert.assertEquals(simpleName.classname, "DollarModel"); Assert.assertEquals(simpleName.classVarName, "dollar_model"); } + + @Test(description = "support complex enum values") + public void supportComplexEnumValues() { + testEnumValues(false); + } + + @Test(description = "support simple enum values") + public void supportSimpleEnumValues() { + testEnumValues(true); + } + + private void testEnumValues(boolean simpleEnumValue) { + final Schema model = new Schema() + .description("a sample model") + .addProperties("testStringEnum", new StringSchema()._enum(Arrays.asList("foo", "bar"))) + .addProperties("testIntEnum", new IntegerSchema().addEnumItem(1).addEnumItem(2)); + final ProtobufSchemaCodegen codegen = new ProtobufSchemaCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", model); + codegen.additionalProperties().put(SIMPLE_ENUM_NAME, simpleEnumValue); + codegen.processOpts(); + codegen.postProcessModels(createCodegenModelWrapper(cm)); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "testStringEnum"); + Assert.assertEquals(property1.dataType, "string"); + Assert.assertEquals(property1.baseType, "string"); + Assert.assertEquals(property1.datatypeWithEnum, "Test_string_enum"); + Assert.assertEquals(property1.name, "test_string_enum"); + Assert.assertTrue(property1.isEnum); + Assert.assertEquals(property1.allowableValues.size(), 2); + Assert.assertEquals(((List) property1.allowableValues.get("values")).size(), 2); + List> enumVars1 = (List>) property1.allowableValues.get("enumVars"); + Assert.assertEquals(enumVars1.size(), 2); + + Assert.assertEquals(enumVars1.get(0).get("name"), simpleEnumValue ? "FOO" : "TEST_STRING_ENUM_FOO"); + Assert.assertEquals(enumVars1.get(0).get("value"), simpleEnumValue ? "FOO" : "\"TEST_STRING_ENUM_FOO\""); + Assert.assertEquals(enumVars1.get(0).get("isString"), false); + + Assert.assertEquals(enumVars1.get(1).get("name"), simpleEnumValue ? "BAR" : "TEST_STRING_ENUM_BAR"); + Assert.assertEquals(enumVars1.get(1).get("value"), simpleEnumValue ? "BAR" : "\"TEST_STRING_ENUM_BAR\""); + Assert.assertEquals(enumVars1.get(1).get("isString"), false); + + final CodegenProperty property2 = cm.vars.get(1); + Assert.assertEquals(property2.baseName, "testIntEnum"); + Assert.assertEquals(property2.dataType, "int32"); + Assert.assertEquals(property2.baseType, "int32"); + Assert.assertEquals(property2.datatypeWithEnum, "Test_int_enum"); + Assert.assertEquals(property2.name, "test_int_enum"); + Assert.assertTrue(property2.isEnum); + Assert.assertEquals(property2.allowableValues.size(), 2); + Assert.assertEquals(((List) property2.allowableValues.get("values")).size(), 2); + List> enumVars2 = (List>) property2.allowableValues.get("enumVars"); + Assert.assertEquals(enumVars2.size(), 2); + + Assert.assertEquals(enumVars2.get(0).get("name"), simpleEnumValue ? "_1" : "TEST_INT_ENUM__1"); + Assert.assertEquals(enumVars2.get(0).get("value"), simpleEnumValue ? "_1" : "\"TEST_INT_ENUM__1\""); + Assert.assertEquals(enumVars2.get(0).get("isString"), false); + + Assert.assertEquals(enumVars2.get(1).get("name"), simpleEnumValue ? "_2" : "TEST_INT_ENUM__2"); + Assert.assertEquals(enumVars2.get(1).get("value"), simpleEnumValue ? "_2" : "\"TEST_INT_ENUM__2\""); + Assert.assertEquals(enumVars2.get(1).get("isString"), false); + } } From 785c49f233594bd2b0336f63e1117121b6b4d2ed Mon Sep 17 00:00:00 2001 From: andrewwilsonnew Date: Wed, 9 Apr 2025 09:35:26 +0100 Subject: [PATCH 2/5] adding test case --- bin/configs/protobuf-schema-config.yaml | 1 + .../protobuf-schema-config/models/data.proto | 26 +++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/bin/configs/protobuf-schema-config.yaml b/bin/configs/protobuf-schema-config.yaml index 7a57d7fdaba3..442e517fb00e 100644 --- a/bin/configs/protobuf-schema-config.yaml +++ b/bin/configs/protobuf-schema-config.yaml @@ -10,6 +10,7 @@ additionalProperties: wrapComplexType: false supportMultipleResponses: false aggregateModelsName: data + enumSimpleName: true typeMappings: object: "google.protobuf.Struct" importMappings: diff --git a/samples/config/petstore/protobuf-schema-config/models/data.proto b/samples/config/petstore/protobuf-schema-config/models/data.proto index 946e1d2c1093..45298f62de1a 100644 --- a/samples/config/petstore/protobuf-schema-config/models/data.proto +++ b/samples/config/petstore/protobuf-schema-config/models/data.proto @@ -45,11 +45,11 @@ message Dog { bool bark = 1; enum Breed { - BREED_UNSPECIFIED = 0; - BREED_DINGO = 1; - BREED_HUSKY = 2; - BREED_RETRIEVER = 3; - BREED_SHEPHERD = 4; + UNSPECIFIED = 0; + DINGO = 1; + HUSKY = 2; + RETRIEVER = 3; + SHEPHERD = 4; } Breed breed = 2; @@ -78,10 +78,10 @@ message Order { // Order Status enum Status { - STATUS_UNSPECIFIED = 0; - STATUS_PLACED = 1; - STATUS_APPROVED = 2; - STATUS_DELIVERED = 3; + UNSPECIFIED = 0; + PLACED = 1; + APPROVED = 2; + DELIVERED = 3; } Status status = 5; @@ -112,10 +112,10 @@ message Pet { // pet status in the store enum Status { - STATUS_UNSPECIFIED = 0; - STATUS_AVAILABLE = 1; - STATUS_PENDING = 2; - STATUS_SOLD = 3; + UNSPECIFIED = 0; + AVAILABLE = 1; + PENDING = 2; + SOLD = 3; } Status status = 6; From ea26e968f5c46e8ea7e3d5a9e66cc6a46fdcfe7d Mon Sep 17 00:00:00 2001 From: andrewwilsonnew Date: Thu, 10 Apr 2025 11:59:29 +0100 Subject: [PATCH 3/5] fixing docs --- docs/generators/protobuf-schema.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/generators/protobuf-schema.md b/docs/generators/protobuf-schema.md index d3ddc215aeea..6a954a0f5164 100644 --- a/docs/generators/protobuf-schema.md +++ b/docs/generators/protobuf-schema.md @@ -20,6 +20,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl | ------ | ----------- | ------ | ------- | |addJsonNameAnnotation|Append "json_name" annotation to message field when the specification name differs from the protobuf field name| |false| |aggregateModelsName|Aggregated model filename. If set, all generated models will be combined into this single file.| |null| +|enumSimpleName|Use a simple name for enums| |false| |numberedFieldNumberList|Field numbers in order.| |false| |startEnumsWithUnspecified|Introduces "UNSPECIFIED" as the first element of enumerations.| |false| |supportMultipleResponses|Support multiple responses| |true| From 9a9f68f7cab628f09762e6540c86e4b2ba41f51e Mon Sep 17 00:00:00 2001 From: andrewwilsonnew Date: Thu, 10 Apr 2025 21:04:49 +0100 Subject: [PATCH 4/5] fixing param name --- bin/configs/protobuf-schema-config.yaml | 2 +- docs/generators/protobuf-schema.md | 2 +- .../codegen/languages/ProtobufSchemaCodegen.java | 16 ++++++++-------- .../protobuf/ProtobufSchemaCodegenTest.java | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bin/configs/protobuf-schema-config.yaml b/bin/configs/protobuf-schema-config.yaml index 442e517fb00e..e1fcd9f97e85 100644 --- a/bin/configs/protobuf-schema-config.yaml +++ b/bin/configs/protobuf-schema-config.yaml @@ -10,7 +10,7 @@ additionalProperties: wrapComplexType: false supportMultipleResponses: false aggregateModelsName: data - enumSimpleName: true + useSimplifiedEnumNames: true typeMappings: object: "google.protobuf.Struct" importMappings: diff --git a/docs/generators/protobuf-schema.md b/docs/generators/protobuf-schema.md index 6a954a0f5164..c3a9c3dee9a4 100644 --- a/docs/generators/protobuf-schema.md +++ b/docs/generators/protobuf-schema.md @@ -20,7 +20,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl | ------ | ----------- | ------ | ------- | |addJsonNameAnnotation|Append "json_name" annotation to message field when the specification name differs from the protobuf field name| |false| |aggregateModelsName|Aggregated model filename. If set, all generated models will be combined into this single file.| |null| -|enumSimpleName|Use a simple name for enums| |false| +|useSimplifiedEnumNames|Use a simple name for enums| |false| |numberedFieldNumberList|Field numbers in order.| |false| |startEnumsWithUnspecified|Introduces "UNSPECIFIED" as the first element of enumerations.| |false| |supportMultipleResponses|Support multiple responses| |true| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java index b141dbcef576..1f7260b768ee 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ProtobufSchemaCodegen.java @@ -66,7 +66,7 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf public static final String WRAP_COMPLEX_TYPE = "wrapComplexType"; - public static final String SIMPLE_ENUM_NAME = "enumSimpleName"; + public static final String USE_SIMPLIFIED_ENUM_NAMES = "useSimplifiedEnumNames"; public static final String AGGREGATE_MODELS_NAME = "aggregateModelsName"; @@ -86,7 +86,7 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf private boolean wrapComplexType = true; - private boolean simpleEnumName = false; + private boolean useSimplifiedEnumNames = false; private boolean supportMultipleResponses = true; @@ -200,7 +200,7 @@ public ProtobufSchemaCodegen() { addSwitch(START_ENUMS_WITH_UNSPECIFIED, "Introduces \"UNSPECIFIED\" as the first element of enumerations.", startEnumsWithUnspecified); addSwitch(ADD_JSON_NAME_ANNOTATION, "Append \"json_name\" annotation to message field when the specification name differs from the protobuf field name", addJsonNameAnnotation); addSwitch(WRAP_COMPLEX_TYPE, "Generate Additional message for complex type", wrapComplexType); - addSwitch(SIMPLE_ENUM_NAME, "Use a simple name for enums", simpleEnumName); + addSwitch(USE_SIMPLIFIED_ENUM_NAMES, "Use a simple name for enums", useSimplifiedEnumNames); addSwitch(SUPPORT_MULTIPLE_RESPONSES, "Support multiple responses", supportMultipleResponses); addOption(AGGREGATE_MODELS_NAME, "Aggregated model filename. If set, all generated models will be combined into this single file.", null); } @@ -245,8 +245,8 @@ public void processOpts() { this.wrapComplexType = convertPropertyToBooleanAndWriteBack(WRAP_COMPLEX_TYPE); } - if (additionalProperties.containsKey(SIMPLE_ENUM_NAME)) { - this.simpleEnumName = convertPropertyToBooleanAndWriteBack(SIMPLE_ENUM_NAME); + if (additionalProperties.containsKey(USE_SIMPLIFIED_ENUM_NAMES)) { + this.useSimplifiedEnumNames = convertPropertyToBooleanAndWriteBack(USE_SIMPLIFIED_ENUM_NAMES); } if (additionalProperties.containsKey(AGGREGATE_MODELS_NAME)) { @@ -507,15 +507,15 @@ public void addEnumValuesPrefix(Map allowableValues, String pref prefix = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, prefix); for (Map value : enumVars) { String name = (String) value.get("name"); - value.put("name", simpleEnumName ? name : prefix + "_" + name); - value.put("value", simpleEnumName ? name : "\"" + prefix + "_" + name + "\""); + value.put("name", useSimplifiedEnumNames ? name : prefix + "_" + name); + value.put("value", useSimplifiedEnumNames ? name : "\"" + prefix + "_" + name + "\""); } } if (allowableValues.containsKey("values")) { List values = (List) allowableValues.get("values"); for (Object value : values) { - value = simpleEnumName ? value : prefix + "_" + value; + value = useSimplifiedEnumNames ? value : prefix + "_" + value; } } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/protobuf/ProtobufSchemaCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/protobuf/ProtobufSchemaCodegenTest.java index 8a3c5951aa78..68fe376efca4 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/protobuf/ProtobufSchemaCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/protobuf/ProtobufSchemaCodegenTest.java @@ -43,7 +43,7 @@ import java.util.Map; import static org.openapitools.codegen.TestUtils.createCodegenModelWrapper; -import static org.openapitools.codegen.languages.ProtobufSchemaCodegen.SIMPLE_ENUM_NAME; +import static org.openapitools.codegen.languages.ProtobufSchemaCodegen.USE_SIMPLIFIED_ENUM_NAMES; import static org.testng.Assert.assertEquals; public class ProtobufSchemaCodegenTest { @@ -169,7 +169,7 @@ private void testEnumValues(boolean simpleEnumValue) { OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); codegen.setOpenAPI(openAPI); final CodegenModel cm = codegen.fromModel("sample", model); - codegen.additionalProperties().put(SIMPLE_ENUM_NAME, simpleEnumValue); + codegen.additionalProperties().put(USE_SIMPLIFIED_ENUM_NAMES, simpleEnumValue); codegen.processOpts(); codegen.postProcessModels(createCodegenModelWrapper(cm)); From f8a773369cda21d69ad79ed70107cb46049e1ceb Mon Sep 17 00:00:00 2001 From: andrewwilsonnew Date: Fri, 11 Apr 2025 04:40:27 +0100 Subject: [PATCH 5/5] fix docs --- docs/generators/protobuf-schema.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/generators/protobuf-schema.md b/docs/generators/protobuf-schema.md index c3a9c3dee9a4..6cf2250ab4b0 100644 --- a/docs/generators/protobuf-schema.md +++ b/docs/generators/protobuf-schema.md @@ -20,10 +20,10 @@ These options may be applied as additional-properties (cli) or configOptions (pl | ------ | ----------- | ------ | ------- | |addJsonNameAnnotation|Append "json_name" annotation to message field when the specification name differs from the protobuf field name| |false| |aggregateModelsName|Aggregated model filename. If set, all generated models will be combined into this single file.| |null| -|useSimplifiedEnumNames|Use a simple name for enums| |false| |numberedFieldNumberList|Field numbers in order.| |false| |startEnumsWithUnspecified|Introduces "UNSPECIFIED" as the first element of enumerations.| |false| |supportMultipleResponses|Support multiple responses| |true| +|useSimplifiedEnumNames|Use a simple name for enums| |false| |wrapComplexType|Generate Additional message for complex type| |true| ## IMPORT MAPPING