Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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 @@ -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";

public static final String SUPPORT_MULTIPLE_RESPONSES = "supportMultipleResponses";
Expand All @@ -84,6 +86,8 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf

private boolean wrapComplexType = true;

private boolean simpleEnumName = false;
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to look at the output flip this flag and run the generator, but this is covered by unit tests

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also test the output by adding the flag in bin/configs/protobuf-schema-config.yaml .

Copy link
Copy Markdown
Author

@andrewwilsonnew andrewwilsonnew Apr 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Good to go @wing328


private boolean supportMultipleResponses = true;

@Override
Expand Down Expand Up @@ -196,6 +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(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);
}
Expand Down Expand Up @@ -224,22 +229,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));
}
Expand Down Expand Up @@ -498,16 +507,15 @@ public void addEnumValuesPrefix(Map<String, Object> allowableValues, String pref
prefix = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, prefix);
for (Map<String, Object> 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<Object> values = (List<Object>) allowableValues.get("values");
for (Object value : values) {
value = prefix + "_" + String.valueOf(value);
value = simpleEnumName ? value : prefix + "_" + value;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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()
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modelled this test on this one

.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<String>) property1.allowableValues.get("values")).size(), 2);
List<Map<String, Object>> enumVars1 = (List<Map<String, Object>>) 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<String>) property2.allowableValues.get("values")).size(), 2);
List<Map<String, Object>> enumVars2 = (List<Map<String, Object>>) 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);
}
}
Loading