From 22d6a8e85a1f067d372b0b611a17ae15e2db4200 Mon Sep 17 00:00:00 2001 From: Cosimo Pasquale RICCHIUTO <cosimo-pasquale.ricchiuto@amadeus.com> Date: Thu, 31 Mar 2022 08:42:43 +0000 Subject: [PATCH 1/2] Pull request #1: ODI-50 guideline for field number index Merge in ODI/openapi-generator from ~LLEONG/openapi-generator:ODI-50-guideline-for-field-number-index to master * commit 'f83d5a62639ded39e6e846cff002f460c5f3487f': use similar extension index handling for parameters in operations use exception getMessage instead of toString add tests with exceptions check index generated by generateFieldNumberFromStringto prevent from duplicates add unit tests fix ordered index auto generation fix typos add test for automatic ordered index generation put usedIndexes as HashSet add duplicate check and strictly positive integers for indexes for operations models Refacto and comments prevent from using non strictly positive field numbers prevent from using same field number handle field number vendor extensions in api template handle x-protobuf-field-number and x-protobuf-index --- .../languages/ProtobufSchemaCodegen.java | 134 ++++++++++++++++-- .../protobuf/ProtobufSchemaCodegenTest.java | 101 +++++++++++-- .../automatic-ordered-index-generation.proto | 26 ++++ .../automatic-ordered-index-generation.yaml | 29 ++++ ...sion-auto-generated-duplicate-indexes.yaml | 22 +++ .../extension-field-number.proto | 20 +++ .../extension-field-number.yaml | 20 +++ .../extension-index-priority.proto | 24 ++++ .../extension-index-priority.yaml | 27 ++++ .../extension-negative-index.yaml | 20 +++ .../extension-non-integer-index.yaml | 20 +++ ...extension-specified-duplicate-indexes.yaml | 23 +++ 12 files changed, 443 insertions(+), 23 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.proto create mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-auto-generated-duplicate-indexes.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.proto create mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.proto create mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-negative-index.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-non-integer-index.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-specified-duplicate-indexes.yaml 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 b0d1419275a..c75e92f3dcf 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 @@ -293,8 +293,9 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf addEnumIndexes(enumVars); } } - - int index = 1; + + //to keep track of the indexes used, prevent duplicate indexes + Set<Integer> usedIndexes = new HashSet<Integer>(); for (CodegenProperty var : cm.vars) { // add x-protobuf-type: repeated if it's an array if (Boolean.TRUE.equals(var.isArray)) { @@ -324,20 +325,75 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf } } - // Add x-protobuf-index, unless already specified - if(this.numberedFieldNumberList) { - var.vendorExtensions.putIfAbsent("x-protobuf-index", index); - index++; + //add x-protobuf-index + int protobufIndex = 0; + if (var.vendorExtensions.containsKey("x-protobuf-index")) { + protobufIndex = (int) var.vendorExtensions.get("x-protobuf-index"); + if (protobufIndex > 0) { + if (!usedIndexes.contains(protobufIndex)) { + //update usedIndexes list + usedIndexes.add(protobufIndex); + } + else { + LOGGER.error("Field number " + protobufIndex + " already used"); + throw new RuntimeException("A same field number is used multiple times"); + } + } + else { + LOGGER.error("Field number " + protobufIndex + " not strictly positive"); + throw new RuntimeException("Only stricly positive field numbers are allowed"); + } } - else { - try { - var.vendorExtensions.putIfAbsent("x-protobuf-index", generateFieldNumberFromString(var.getName())); - } catch (ProtoBufIndexComputationException e) { - LOGGER.error("Exception when assigning a index to a protobuf field", e); - var.vendorExtensions.putIfAbsent("x-protobuf-index", "Generated field number is in reserved range (19000, 19999)"); + else if (var.vendorExtensions.containsKey("x-protobuf-field-number")) { + protobufIndex = (int) var.vendorExtensions.get("x-protobuf-field-number"); + if (protobufIndex > 0) { + if (!usedIndexes.contains(protobufIndex)) { + //update usedIndexes list and add x-protobuf-index + usedIndexes.add(protobufIndex); + var.vendorExtensions.put("x-protobuf-index", protobufIndex); + } + else { + LOGGER.error("Field number " + protobufIndex + " already used"); + throw new RuntimeException("A same field number is used multiple times"); + } + } + else { + LOGGER.error("Field number " + protobufIndex + " not strictly positive"); + throw new RuntimeException("Only stricly positive field numbers are allowed"); } } } + //automatic index generation when index not specified using extensions + int index = 1; + for (CodegenProperty var : cm.vars) { + if (!var.vendorExtensions.containsKey("x-protobuf-index")) { + if (this.numberedFieldNumberList) { + //prevent from using index already used + while (usedIndexes.contains(index)) { + index++; + } + usedIndexes.add(index); + var.vendorExtensions.put("x-protobuf-index", index); + } + else { + try { + int protobufIndex = generateFieldNumberFromString(var.getName()); + if (!usedIndexes.contains(protobufIndex)) { + //update usedIndexes list and add x-protobuf-index + usedIndexes.add(protobufIndex); + var.vendorExtensions.put("x-protobuf-index", protobufIndex); + } + else { + LOGGER.error("Field number " + protobufIndex + " already used"); + throw new RuntimeException("A same field number is used multiple times"); + } + } catch (ProtoBufIndexComputationException e) { + LOGGER.error("Exception when assigning a index to a protobuf field", e); + var.vendorExtensions.put("x-protobuf-index", "Generated field number is in reserved range (19000, 19999)"); + } + } + } + } } return objs; } @@ -547,7 +603,8 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf OperationMap operations = objs.getOperations(); List<CodegenOperation> operationList = operations.getOperation(); for (CodegenOperation op : operationList) { - int index = 1; + //to keep track of the indexes used, prevent duplicate indexes + Set<Integer> usedIndexes = new HashSet<Integer>(); for (CodegenParameter p : op.allParams) { // add x-protobuf-type: repeated if it's an array @@ -571,8 +628,55 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf } } - p.vendorExtensions.putIfAbsent("x-protobuf-index", index); - index++; + //add x-protobuf-index + int protobufIndex = 0; + if (p.vendorExtensions.containsKey("x-protobuf-index")) { + protobufIndex = (int) p.vendorExtensions.get("x-protobuf-index"); + if (protobufIndex > 0) { + if (!usedIndexes.contains(protobufIndex)) { + //update usedIndexes list + usedIndexes.add(protobufIndex); + } + else { + LOGGER.error("Field number " + protobufIndex + " already used"); + throw new RuntimeException("A same field number is used multiple times"); + } + } + else { + LOGGER.error("Field number " + protobufIndex + " not strictly positive"); + throw new RuntimeException("Only stricly positive field numbers are allowed"); + } + } + else if (p.vendorExtensions.containsKey("x-protobuf-field-number")) { + protobufIndex = (int) p.vendorExtensions.get("x-protobuf-field-number"); + if (protobufIndex > 0) { + if (!usedIndexes.contains(protobufIndex)) { + //update usedIndexes list and add x-protobuf-index + usedIndexes.add(protobufIndex); + p.vendorExtensions.put("x-protobuf-index", protobufIndex); + } + else { + LOGGER.error("Field number " + protobufIndex + " already used"); + throw new RuntimeException("A same field number is used multiple times"); + } + } + else { + LOGGER.error("Field number " + protobufIndex + " not strictly positive"); + throw new RuntimeException("Only stricly positive field numbers are allowed"); + } + } + } + //automatic index generation when index not specified using extensions + int index = 1; + for (CodegenParameter p : op.allParams) { + if (!p.vendorExtensions.containsKey("x-protobuf-index")) { + //prevent from using index already used + while (usedIndexes.contains(index)) { + index++; + } + usedIndexes.add(index); + p.vendorExtensions.put("x-protobuf-index", index); + } } if (StringUtils.isEmpty(op.returnType)) { 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 3b30f96b2e3..11c7ad1f1ee 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 @@ -35,6 +35,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; +import java.util.HashMap; +import java.util.Map; public class ProtobufSchemaCodegenTest { @@ -49,28 +51,98 @@ public class ProtobufSchemaCodegenTest { @Test public void testCodeGenWithAllOf() throws IOException { + Map<String, Object> properties = new HashMap<>(); // set line break to \n across all platforms System.setProperty("line.separator", "\n"); File output = Files.createTempDirectory("test").toFile(); + List<File> files = generate(output, properties, "src/test/resources/3_0/allOf_composition_discriminator.yaml"); + TestUtils.ensureContainsFile(files, output, "models/pet.proto"); + Path path = Paths.get(output + "/models/pet.proto"); + assertFileEquals(path, Paths.get("src/test/resources/3_0/protobuf-schema/pet.proto")); - final CodegenConfigurator configurator = new CodegenConfigurator() - .setGeneratorName("protobuf-schema") - .setInputSpec("src/test/resources/3_0/allOf_composition_discriminator.yaml") - .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + output.delete(); + } - final ClientOptInput clientOptInput = configurator.toClientOptInput(); - DefaultGenerator generator = new DefaultGenerator(); - List<File> files = generator.opts(clientOptInput).generate(); + @Test + public void testAutomaticOrderedIndexGeneration() throws IOException { + Map<String, Object> properties = new HashMap<>(); + properties.put("numberedFieldNumberList", "True"); + File output = Files.createTempDirectory("test").toFile(); + List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.yaml"); TestUtils.ensureContainsFile(files, output, "models/pet.proto"); Path path = Paths.get(output + "/models/pet.proto"); + assertFileEquals(path, Paths.get("src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.proto")); - assertFileEquals(path, Paths.get("src/test/resources/3_0/protobuf-schema/pet.proto")); + output.delete(); + } + + @Test + public void testExtensionFieldNumber() throws IOException { + Map<String, Object> properties = new HashMap<>(); + + File output = Files.createTempDirectory("test").toFile(); + List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/extension-field-number.yaml"); + TestUtils.ensureContainsFile(files, output, "models/pet.proto"); + Path path = Paths.get(output + "/models/pet.proto"); + assertFileEquals(path, Paths.get("src/test/resources/3_0/protobuf-schema/extension-field-number.proto")); output.delete(); } + @Test + public void testExtensionNegativeIndex() throws IOException { + try { + Map<String, Object> properties = new HashMap<>(); + File output = Files.createTempDirectory("test").toFile(); + List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/extension-negative-index.yaml"); + fail("No exception thrown!"); + } + catch (RuntimeException e) { + assertEquals(e.getCause().getMessage(), "Only stricly positive field numbers are allowed"); + } + } + + @Test + public void testExtensionNonIntegerIndex() throws IOException { + try { + Map<String, Object> properties = new HashMap<>(); + File output = Files.createTempDirectory("test").toFile(); + List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/extension-non-integer-index.yaml"); + fail("No exception thrown!"); + } + catch (RuntimeException e) { + assertEquals(e.getCause().getMessage(), "java.lang.String cannot be cast to java.lang.Integer"); + } + } + + @Test + public void testExtensionSpecifiedDuplicateIndexes() throws IOException { + try { + Map<String, Object> properties = new HashMap<>(); + File output = Files.createTempDirectory("test").toFile(); + List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/extension-specified-duplicate-indexes.yaml"); + fail("No exception thrown!"); + } + catch (RuntimeException e) { + assertEquals(e.getCause().getMessage(), "A same field number is used multiple times"); + } + } + + @Test + public void testExtensionAutoGeneratedDuplicateIndexes() throws IOException { + try { + Map<String, Object> properties = new HashMap<>(); + File output = Files.createTempDirectory("test").toFile(); + List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/extension-auto-generated-duplicate-indexes.yaml"); + fail("No exception thrown!"); + } + catch (RuntimeException e) { + assertEquals(e.getCause().getMessage(), "A same field number is used multiple times"); + } + } + private void assertFileEquals(Path generatedFilePath, Path expectedFilePath) throws IOException { String generatedFile = new String(Files.readAllBytes(generatedFilePath), StandardCharsets.UTF_8) .replace("\n", "").replace("\r", ""); @@ -79,4 +151,17 @@ public class ProtobufSchemaCodegenTest { assertEquals(generatedFile, expectedFile); } + + private List<File> generate(File output, Map<String, Object> properties, String inputFile) { + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("protobuf-schema") + .setAdditionalProperties(properties) + .setInputSpec(inputFile) + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + final ClientOptInput clientOptInput = configurator.toClientOptInput(); + DefaultGenerator generator = new DefaultGenerator(); + + return generator.opts(clientOptInput).generate(); + } } diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.proto b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.proto new file mode 100644 index 00000000000..b2121dadc62 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.proto @@ -0,0 +1,26 @@ +/* + Automatic ordered index generation + + This specification is used as source for a test to demonstrate the behavior of the automatic ordered index generation (using the additional property numberedFieldNumberList=true) while taking into account the specified indexes and preventing from conflicts + + The version of the OpenAPI document: 1.0.0 + + Generated by OpenAPI Generator: https://openapi-generator.tech +*/ + +syntax = "proto3"; + +package openapitools; + + +message Pet { + + int32 id = 3; + + string name = 2; + + string status = 1; + + repeated string tags = 4; + +} diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.yaml new file mode 100644 index 00000000000..ac6ad69db93 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.yaml @@ -0,0 +1,29 @@ +openapi: 3.0.0 +info: + description: This specification is used as source for a test to demonstrate the behavior of the automatic ordered index generation (using the additional property numberedFieldNumberList=true) while taking into account the specified indexes and preventing from conflicts + version: 1.0.0 + title: Automatic ordered index generation +paths: + /dummy: + get: + summary: A dummy endpoint to make the spec valid. + responses: + '200': + description: Success +components: + schemas: + Pet: + type: object + properties: + id: + type: integer + x-protobuf-index: 3 + name: + type: string + status: + type: string + x-protobuf-index: 1 + tags: + type: array + items: + type: string \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-auto-generated-duplicate-indexes.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-auto-generated-duplicate-indexes.yaml new file mode 100644 index 00000000000..817bda455b5 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-auto-generated-duplicate-indexes.yaml @@ -0,0 +1,22 @@ +openapi: 3.0.0 +info: + description: This specification is used as source for a test to check that automatically generated indexes from hash are not duplicates of specified indexes + version: 1.0.0 + title: Extension auto generated duplicate indexes +paths: + /dummy: + get: + summary: A dummy endpoint to make the spec valid. + responses: + '200': + description: Success +components: + schemas: + Pet: + type: object + properties: + id: + type: integer + name: + type: integer + x-protobuf-index: 3355 \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.proto b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.proto new file mode 100644 index 00000000000..7b1893ab91b --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.proto @@ -0,0 +1,20 @@ +/* + Extension field number + + This specification is used as source for a test to demonstrate the handling of x-protobuf-field-number + + The version of the OpenAPI document: 1.0.0 + + Generated by OpenAPI Generator: https://openapi-generator.tech +*/ + +syntax = "proto3"; + +package openapitools; + + +message Pet { + + int32 id = 2; + +} diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.yaml new file mode 100644 index 00000000000..1d2edc1c6f3 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.yaml @@ -0,0 +1,20 @@ +openapi: 3.0.0 +info: + description: This specification is used as source for a test to demonstrate the handling of x-protobuf-field-number + version: 1.0.0 + title: Extension field number +paths: + /dummy: + get: + summary: A dummy endpoint to make the spec valid. + responses: + '200': + description: Success +components: + schemas: + Pet: + type: object + properties: + id: + type: integer + x-protobuf-field-number: 2 \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.proto b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.proto new file mode 100644 index 00000000000..6092e452aed --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.proto @@ -0,0 +1,24 @@ +/* + Extension index priority + + This specification is used as source for a test to demonstrate handling of both x-protobuf-index and x-protobuf-field-number extensions, with x-protobuf-index having priority + + The version of the OpenAPI document: 1.0.0 + + Generated by OpenAPI Generator: https://openapi-generator.tech +*/ + +syntax = "proto3"; + +package openapitools; + + +message Pet { + + int32 id = 2; + + string name = 3; + + string status = 4; + +} diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.yaml new file mode 100644 index 00000000000..2eebcde312d --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.yaml @@ -0,0 +1,27 @@ +openapi: 3.0.0 +info: + description: This specification is used as source for a test to demonstrate handling of both x-protobuf-index and x-protobuf-field-number extensions, with x-protobuf-index having priority + version: 1.0.0 + title: Extension index priority +paths: + /dummy: + get: + summary: A dummy endpoint to make the spec valid. + responses: + '200': + description: Success +components: + schemas: + Pet: + type: object + properties: + id: + type: integer + x-protobuf-field-number: 1 + x-protobuf-index: 2 + name: + type: string + x-protobuf-index: 3 + status: + type: string + x-protobuf-field-number: 4 diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-negative-index.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-negative-index.yaml new file mode 100644 index 00000000000..ef03263f069 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-negative-index.yaml @@ -0,0 +1,20 @@ +openapi: 3.0.0 +info: + description: This specification is used as source for a test to check that negative indexes are forbidden + version: 1.0.0 + title: Extension negative index +paths: + /dummy: + get: + summary: A dummy endpoint to make the spec valid. + responses: + '200': + description: Success +components: + schemas: + Pet: + type: object + properties: + id: + type: integer + x-protobuf-index: -2 \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-non-integer-index.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-non-integer-index.yaml new file mode 100644 index 00000000000..424bd17f934 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-non-integer-index.yaml @@ -0,0 +1,20 @@ +openapi: 3.0.0 +info: + description: This specification is used as source for a test to check that non integer indexes are forbidden + version: 1.0.0 + title: Extension non integer index +paths: + /dummy: + get: + summary: A dummy endpoint to make the spec valid. + responses: + '200': + description: Success +components: + schemas: + Pet: + type: object + properties: + id: + type: integer + x-protobuf-index: a \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-specified-duplicate-indexes.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-specified-duplicate-indexes.yaml new file mode 100644 index 00000000000..b65b0527fab --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-specified-duplicate-indexes.yaml @@ -0,0 +1,23 @@ +openapi: 3.0.0 +info: + description: This specification is used as source for a test to check that specified duplicate indexes are forbidden + version: 1.0.0 + title: Extension specified duplicate indexes +paths: + /dummy: + get: + summary: A dummy endpoint to make the spec valid. + responses: + '200': + description: Success +components: + schemas: + Pet: + type: object + properties: + id: + type: integer + x-protobuf-index: 1 + name: + type: integer + x-protobuf-index: 1 \ No newline at end of file -- GitLab From 2bcdfe15c34220e1e324a2fa02691b9e63321bb5 Mon Sep 17 00:00:00 2001 From: Cosimo Pasquale RICCHIUTO <cosimo-pasquale.ricchiuto@amadeus.com> Date: Fri, 8 Jul 2022 16:52:07 +0200 Subject: [PATCH 2/2] Revert "Merge pull request #14 from lleongl/feat/proto-field-number" This reverts commit b33b15fe1de6dc21a47fe2e6f22a3554b4b7b8d4, reversing changes made to cfebd14c2bb1da219aa75d841658108fb5e14edb. --- .../languages/ProtobufSchemaCodegen.java | 134 ++---------------- .../protobuf/ProtobufSchemaCodegenTest.java | 101 ++----------- .../automatic-ordered-index-generation.proto | 26 ---- .../automatic-ordered-index-generation.yaml | 29 ---- ...sion-auto-generated-duplicate-indexes.yaml | 22 --- .../extension-field-number.proto | 20 --- .../extension-field-number.yaml | 20 --- .../extension-index-priority.proto | 24 ---- .../extension-index-priority.yaml | 27 ---- .../extension-negative-index.yaml | 20 --- .../extension-non-integer-index.yaml | 20 --- ...extension-specified-duplicate-indexes.yaml | 23 --- 12 files changed, 23 insertions(+), 443 deletions(-) delete mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.proto delete mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.yaml delete mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-auto-generated-duplicate-indexes.yaml delete mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.proto delete mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.yaml delete mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.proto delete mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.yaml delete mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-negative-index.yaml delete mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-non-integer-index.yaml delete mode 100644 modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-specified-duplicate-indexes.yaml 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 c75e92f3dcf..b0d1419275a 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 @@ -293,9 +293,8 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf addEnumIndexes(enumVars); } } - - //to keep track of the indexes used, prevent duplicate indexes - Set<Integer> usedIndexes = new HashSet<Integer>(); + + int index = 1; for (CodegenProperty var : cm.vars) { // add x-protobuf-type: repeated if it's an array if (Boolean.TRUE.equals(var.isArray)) { @@ -325,75 +324,20 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf } } - //add x-protobuf-index - int protobufIndex = 0; - if (var.vendorExtensions.containsKey("x-protobuf-index")) { - protobufIndex = (int) var.vendorExtensions.get("x-protobuf-index"); - if (protobufIndex > 0) { - if (!usedIndexes.contains(protobufIndex)) { - //update usedIndexes list - usedIndexes.add(protobufIndex); - } - else { - LOGGER.error("Field number " + protobufIndex + " already used"); - throw new RuntimeException("A same field number is used multiple times"); - } - } - else { - LOGGER.error("Field number " + protobufIndex + " not strictly positive"); - throw new RuntimeException("Only stricly positive field numbers are allowed"); - } + // Add x-protobuf-index, unless already specified + if(this.numberedFieldNumberList) { + var.vendorExtensions.putIfAbsent("x-protobuf-index", index); + index++; } - else if (var.vendorExtensions.containsKey("x-protobuf-field-number")) { - protobufIndex = (int) var.vendorExtensions.get("x-protobuf-field-number"); - if (protobufIndex > 0) { - if (!usedIndexes.contains(protobufIndex)) { - //update usedIndexes list and add x-protobuf-index - usedIndexes.add(protobufIndex); - var.vendorExtensions.put("x-protobuf-index", protobufIndex); - } - else { - LOGGER.error("Field number " + protobufIndex + " already used"); - throw new RuntimeException("A same field number is used multiple times"); - } - } - else { - LOGGER.error("Field number " + protobufIndex + " not strictly positive"); - throw new RuntimeException("Only stricly positive field numbers are allowed"); + else { + try { + var.vendorExtensions.putIfAbsent("x-protobuf-index", generateFieldNumberFromString(var.getName())); + } catch (ProtoBufIndexComputationException e) { + LOGGER.error("Exception when assigning a index to a protobuf field", e); + var.vendorExtensions.putIfAbsent("x-protobuf-index", "Generated field number is in reserved range (19000, 19999)"); } } } - //automatic index generation when index not specified using extensions - int index = 1; - for (CodegenProperty var : cm.vars) { - if (!var.vendorExtensions.containsKey("x-protobuf-index")) { - if (this.numberedFieldNumberList) { - //prevent from using index already used - while (usedIndexes.contains(index)) { - index++; - } - usedIndexes.add(index); - var.vendorExtensions.put("x-protobuf-index", index); - } - else { - try { - int protobufIndex = generateFieldNumberFromString(var.getName()); - if (!usedIndexes.contains(protobufIndex)) { - //update usedIndexes list and add x-protobuf-index - usedIndexes.add(protobufIndex); - var.vendorExtensions.put("x-protobuf-index", protobufIndex); - } - else { - LOGGER.error("Field number " + protobufIndex + " already used"); - throw new RuntimeException("A same field number is used multiple times"); - } - } catch (ProtoBufIndexComputationException e) { - LOGGER.error("Exception when assigning a index to a protobuf field", e); - var.vendorExtensions.put("x-protobuf-index", "Generated field number is in reserved range (19000, 19999)"); - } - } - } - } } return objs; } @@ -603,8 +547,7 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf OperationMap operations = objs.getOperations(); List<CodegenOperation> operationList = operations.getOperation(); for (CodegenOperation op : operationList) { - //to keep track of the indexes used, prevent duplicate indexes - Set<Integer> usedIndexes = new HashSet<Integer>(); + int index = 1; for (CodegenParameter p : op.allParams) { // add x-protobuf-type: repeated if it's an array @@ -628,55 +571,8 @@ public class ProtobufSchemaCodegen extends DefaultCodegen implements CodegenConf } } - //add x-protobuf-index - int protobufIndex = 0; - if (p.vendorExtensions.containsKey("x-protobuf-index")) { - protobufIndex = (int) p.vendorExtensions.get("x-protobuf-index"); - if (protobufIndex > 0) { - if (!usedIndexes.contains(protobufIndex)) { - //update usedIndexes list - usedIndexes.add(protobufIndex); - } - else { - LOGGER.error("Field number " + protobufIndex + " already used"); - throw new RuntimeException("A same field number is used multiple times"); - } - } - else { - LOGGER.error("Field number " + protobufIndex + " not strictly positive"); - throw new RuntimeException("Only stricly positive field numbers are allowed"); - } - } - else if (p.vendorExtensions.containsKey("x-protobuf-field-number")) { - protobufIndex = (int) p.vendorExtensions.get("x-protobuf-field-number"); - if (protobufIndex > 0) { - if (!usedIndexes.contains(protobufIndex)) { - //update usedIndexes list and add x-protobuf-index - usedIndexes.add(protobufIndex); - p.vendorExtensions.put("x-protobuf-index", protobufIndex); - } - else { - LOGGER.error("Field number " + protobufIndex + " already used"); - throw new RuntimeException("A same field number is used multiple times"); - } - } - else { - LOGGER.error("Field number " + protobufIndex + " not strictly positive"); - throw new RuntimeException("Only stricly positive field numbers are allowed"); - } - } - } - //automatic index generation when index not specified using extensions - int index = 1; - for (CodegenParameter p : op.allParams) { - if (!p.vendorExtensions.containsKey("x-protobuf-index")) { - //prevent from using index already used - while (usedIndexes.contains(index)) { - index++; - } - usedIndexes.add(index); - p.vendorExtensions.put("x-protobuf-index", index); - } + p.vendorExtensions.putIfAbsent("x-protobuf-index", index); + index++; } if (StringUtils.isEmpty(op.returnType)) { 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 11c7ad1f1ee..3b30f96b2e3 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 @@ -35,8 +35,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; -import java.util.HashMap; -import java.util.Map; public class ProtobufSchemaCodegenTest { @@ -51,98 +49,28 @@ public class ProtobufSchemaCodegenTest { @Test public void testCodeGenWithAllOf() throws IOException { - Map<String, Object> properties = new HashMap<>(); // set line break to \n across all platforms System.setProperty("line.separator", "\n"); File output = Files.createTempDirectory("test").toFile(); - List<File> files = generate(output, properties, "src/test/resources/3_0/allOf_composition_discriminator.yaml"); - TestUtils.ensureContainsFile(files, output, "models/pet.proto"); - Path path = Paths.get(output + "/models/pet.proto"); - assertFileEquals(path, Paths.get("src/test/resources/3_0/protobuf-schema/pet.proto")); - output.delete(); - } + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("protobuf-schema") + .setInputSpec("src/test/resources/3_0/allOf_composition_discriminator.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); - @Test - public void testAutomaticOrderedIndexGeneration() throws IOException { - Map<String, Object> properties = new HashMap<>(); - properties.put("numberedFieldNumberList", "True"); + final ClientOptInput clientOptInput = configurator.toClientOptInput(); + DefaultGenerator generator = new DefaultGenerator(); + List<File> files = generator.opts(clientOptInput).generate(); - File output = Files.createTempDirectory("test").toFile(); - List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.yaml"); TestUtils.ensureContainsFile(files, output, "models/pet.proto"); Path path = Paths.get(output + "/models/pet.proto"); - assertFileEquals(path, Paths.get("src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.proto")); - - output.delete(); - } - - @Test - public void testExtensionFieldNumber() throws IOException { - Map<String, Object> properties = new HashMap<>(); - File output = Files.createTempDirectory("test").toFile(); - List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/extension-field-number.yaml"); - TestUtils.ensureContainsFile(files, output, "models/pet.proto"); - Path path = Paths.get(output + "/models/pet.proto"); - assertFileEquals(path, Paths.get("src/test/resources/3_0/protobuf-schema/extension-field-number.proto")); + assertFileEquals(path, Paths.get("src/test/resources/3_0/protobuf-schema/pet.proto")); output.delete(); } - @Test - public void testExtensionNegativeIndex() throws IOException { - try { - Map<String, Object> properties = new HashMap<>(); - File output = Files.createTempDirectory("test").toFile(); - List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/extension-negative-index.yaml"); - fail("No exception thrown!"); - } - catch (RuntimeException e) { - assertEquals(e.getCause().getMessage(), "Only stricly positive field numbers are allowed"); - } - } - - @Test - public void testExtensionNonIntegerIndex() throws IOException { - try { - Map<String, Object> properties = new HashMap<>(); - File output = Files.createTempDirectory("test").toFile(); - List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/extension-non-integer-index.yaml"); - fail("No exception thrown!"); - } - catch (RuntimeException e) { - assertEquals(e.getCause().getMessage(), "java.lang.String cannot be cast to java.lang.Integer"); - } - } - - @Test - public void testExtensionSpecifiedDuplicateIndexes() throws IOException { - try { - Map<String, Object> properties = new HashMap<>(); - File output = Files.createTempDirectory("test").toFile(); - List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/extension-specified-duplicate-indexes.yaml"); - fail("No exception thrown!"); - } - catch (RuntimeException e) { - assertEquals(e.getCause().getMessage(), "A same field number is used multiple times"); - } - } - - @Test - public void testExtensionAutoGeneratedDuplicateIndexes() throws IOException { - try { - Map<String, Object> properties = new HashMap<>(); - File output = Files.createTempDirectory("test").toFile(); - List<File> files = generate(output, properties, "src/test/resources/3_0/protobuf-schema/extension-auto-generated-duplicate-indexes.yaml"); - fail("No exception thrown!"); - } - catch (RuntimeException e) { - assertEquals(e.getCause().getMessage(), "A same field number is used multiple times"); - } - } - private void assertFileEquals(Path generatedFilePath, Path expectedFilePath) throws IOException { String generatedFile = new String(Files.readAllBytes(generatedFilePath), StandardCharsets.UTF_8) .replace("\n", "").replace("\r", ""); @@ -151,17 +79,4 @@ public class ProtobufSchemaCodegenTest { assertEquals(generatedFile, expectedFile); } - - private List<File> generate(File output, Map<String, Object> properties, String inputFile) { - final CodegenConfigurator configurator = new CodegenConfigurator() - .setGeneratorName("protobuf-schema") - .setAdditionalProperties(properties) - .setInputSpec(inputFile) - .setOutputDir(output.getAbsolutePath().replace("\\", "/")); - - final ClientOptInput clientOptInput = configurator.toClientOptInput(); - DefaultGenerator generator = new DefaultGenerator(); - - return generator.opts(clientOptInput).generate(); - } } diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.proto b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.proto deleted file mode 100644 index b2121dadc62..00000000000 --- a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.proto +++ /dev/null @@ -1,26 +0,0 @@ -/* - Automatic ordered index generation - - This specification is used as source for a test to demonstrate the behavior of the automatic ordered index generation (using the additional property numberedFieldNumberList=true) while taking into account the specified indexes and preventing from conflicts - - The version of the OpenAPI document: 1.0.0 - - Generated by OpenAPI Generator: https://openapi-generator.tech -*/ - -syntax = "proto3"; - -package openapitools; - - -message Pet { - - int32 id = 3; - - string name = 2; - - string status = 1; - - repeated string tags = 4; - -} diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.yaml deleted file mode 100644 index ac6ad69db93..00000000000 --- a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/automatic-ordered-index-generation.yaml +++ /dev/null @@ -1,29 +0,0 @@ -openapi: 3.0.0 -info: - description: This specification is used as source for a test to demonstrate the behavior of the automatic ordered index generation (using the additional property numberedFieldNumberList=true) while taking into account the specified indexes and preventing from conflicts - version: 1.0.0 - title: Automatic ordered index generation -paths: - /dummy: - get: - summary: A dummy endpoint to make the spec valid. - responses: - '200': - description: Success -components: - schemas: - Pet: - type: object - properties: - id: - type: integer - x-protobuf-index: 3 - name: - type: string - status: - type: string - x-protobuf-index: 1 - tags: - type: array - items: - type: string \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-auto-generated-duplicate-indexes.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-auto-generated-duplicate-indexes.yaml deleted file mode 100644 index 817bda455b5..00000000000 --- a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-auto-generated-duplicate-indexes.yaml +++ /dev/null @@ -1,22 +0,0 @@ -openapi: 3.0.0 -info: - description: This specification is used as source for a test to check that automatically generated indexes from hash are not duplicates of specified indexes - version: 1.0.0 - title: Extension auto generated duplicate indexes -paths: - /dummy: - get: - summary: A dummy endpoint to make the spec valid. - responses: - '200': - description: Success -components: - schemas: - Pet: - type: object - properties: - id: - type: integer - name: - type: integer - x-protobuf-index: 3355 \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.proto b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.proto deleted file mode 100644 index 7b1893ab91b..00000000000 --- a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.proto +++ /dev/null @@ -1,20 +0,0 @@ -/* - Extension field number - - This specification is used as source for a test to demonstrate the handling of x-protobuf-field-number - - The version of the OpenAPI document: 1.0.0 - - Generated by OpenAPI Generator: https://openapi-generator.tech -*/ - -syntax = "proto3"; - -package openapitools; - - -message Pet { - - int32 id = 2; - -} diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.yaml deleted file mode 100644 index 1d2edc1c6f3..00000000000 --- a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-field-number.yaml +++ /dev/null @@ -1,20 +0,0 @@ -openapi: 3.0.0 -info: - description: This specification is used as source for a test to demonstrate the handling of x-protobuf-field-number - version: 1.0.0 - title: Extension field number -paths: - /dummy: - get: - summary: A dummy endpoint to make the spec valid. - responses: - '200': - description: Success -components: - schemas: - Pet: - type: object - properties: - id: - type: integer - x-protobuf-field-number: 2 \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.proto b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.proto deleted file mode 100644 index 6092e452aed..00000000000 --- a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.proto +++ /dev/null @@ -1,24 +0,0 @@ -/* - Extension index priority - - This specification is used as source for a test to demonstrate handling of both x-protobuf-index and x-protobuf-field-number extensions, with x-protobuf-index having priority - - The version of the OpenAPI document: 1.0.0 - - Generated by OpenAPI Generator: https://openapi-generator.tech -*/ - -syntax = "proto3"; - -package openapitools; - - -message Pet { - - int32 id = 2; - - string name = 3; - - string status = 4; - -} diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.yaml deleted file mode 100644 index 2eebcde312d..00000000000 --- a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-index-priority.yaml +++ /dev/null @@ -1,27 +0,0 @@ -openapi: 3.0.0 -info: - description: This specification is used as source for a test to demonstrate handling of both x-protobuf-index and x-protobuf-field-number extensions, with x-protobuf-index having priority - version: 1.0.0 - title: Extension index priority -paths: - /dummy: - get: - summary: A dummy endpoint to make the spec valid. - responses: - '200': - description: Success -components: - schemas: - Pet: - type: object - properties: - id: - type: integer - x-protobuf-field-number: 1 - x-protobuf-index: 2 - name: - type: string - x-protobuf-index: 3 - status: - type: string - x-protobuf-field-number: 4 diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-negative-index.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-negative-index.yaml deleted file mode 100644 index ef03263f069..00000000000 --- a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-negative-index.yaml +++ /dev/null @@ -1,20 +0,0 @@ -openapi: 3.0.0 -info: - description: This specification is used as source for a test to check that negative indexes are forbidden - version: 1.0.0 - title: Extension negative index -paths: - /dummy: - get: - summary: A dummy endpoint to make the spec valid. - responses: - '200': - description: Success -components: - schemas: - Pet: - type: object - properties: - id: - type: integer - x-protobuf-index: -2 \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-non-integer-index.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-non-integer-index.yaml deleted file mode 100644 index 424bd17f934..00000000000 --- a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-non-integer-index.yaml +++ /dev/null @@ -1,20 +0,0 @@ -openapi: 3.0.0 -info: - description: This specification is used as source for a test to check that non integer indexes are forbidden - version: 1.0.0 - title: Extension non integer index -paths: - /dummy: - get: - summary: A dummy endpoint to make the spec valid. - responses: - '200': - description: Success -components: - schemas: - Pet: - type: object - properties: - id: - type: integer - x-protobuf-index: a \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-specified-duplicate-indexes.yaml b/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-specified-duplicate-indexes.yaml deleted file mode 100644 index b65b0527fab..00000000000 --- a/modules/openapi-generator/src/test/resources/3_0/protobuf-schema/extension-specified-duplicate-indexes.yaml +++ /dev/null @@ -1,23 +0,0 @@ -openapi: 3.0.0 -info: - description: This specification is used as source for a test to check that specified duplicate indexes are forbidden - version: 1.0.0 - title: Extension specified duplicate indexes -paths: - /dummy: - get: - summary: A dummy endpoint to make the spec valid. - responses: - '200': - description: Success -components: - schemas: - Pet: - type: object - properties: - id: - type: integer - x-protobuf-index: 1 - name: - type: integer - x-protobuf-index: 1 \ No newline at end of file -- GitLab