From c2c39c67f3e51d54ab2953fcde65b7cec655660e Mon Sep 17 00:00:00 2001
From: William Cheng <wing328hk@gmail.com>
Date: Thu, 3 Nov 2022 01:13:15 +0800
Subject: [PATCH] add option to skip reusing inline schemas

---
 docs/customization.md                         |  4 +--
 .../openapitools/codegen/cmd/Generate.java    |  2 +-
 .../codegen/InlineModelResolver.java          | 10 ++++++
 .../codegen/InlineModelResolverTest.java      | 36 +++++++++++++++++++
 .../resources/3_0/inline_model_resolver.yaml  | 31 ++++++++++++++++
 5 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/docs/customization.md b/docs/customization.md
index 39d45c3834e..0fac8deb71a 100644
--- a/docs/customization.md
+++ b/docs/customization.md
@@ -438,7 +438,7 @@ java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generat
 
 Another useful option is `inlineSchemaNameDefaults`, which allows you to customize the suffix of the auto-generated inline schema name, e.g. in CLI
 ```
---inline-schema-name-defaults arrayItemSuffix=_array_item
+--inline-schema-name-defaults arrayItemSuffix=_array_item,mapItemSuffix=_map_item
 ```
 
-Note: Only arrayItemSuffix, mapItemSuffix are supported at the moment.
+Note: Only arrayItemSuffix, mapItemSuffix are supported at the moment. `SKIP_SCHEMA_REUSE=true` is a special value to skip reusing inline schemas.
diff --git a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java
index 02f6f99f613..ae78b2f9fd9 100644
--- a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java
+++ b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java
@@ -177,7 +177,7 @@ public class Generate extends OpenApiGeneratorCommand {
             name = {"--inline-schema-name-defaults"},
             title = "inline schema name defaults",
             description = "specifies the default values used when naming inline schema as such array items in the format of arrayItemSuffix=_inner,mapItemSuffix=_value. "
-                    + " ONLY arrayItemSuffix, mapItemSuffix at the moment.")
+                    + " ONLY arrayItemSuffix, mapItemSuffix are supported at the moment. `SKIP_SCHEMA_REUSE=true` is a special value to skip reusing inline schemas.")
     private List<String> inlineSchemaNameDefaults = new ArrayList<>();
 
     @Option(
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java
index 40ebf90595a..f09bc8bd46f 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java
@@ -45,6 +45,7 @@ public class InlineModelResolver {
     private Map<String, String> inlineSchemaNameDefaults = new HashMap<>();
     private Set<String> inlineSchemaNameMappingValues = new HashSet<>();
     public boolean resolveInlineEnums = false;
+    public boolean skipSchemaReuse = false; // skip reusing inline schema if set to true
 
     // structure mapper sorts properties alphabetically on write to ensure models are
     // serialized consistently for lookup of existing models
@@ -73,6 +74,11 @@ public class InlineModelResolver {
 
     public void setInlineSchemaNameDefaults(Map inlineSchemaNameDefaults) {
         this.inlineSchemaNameDefaults.putAll(inlineSchemaNameDefaults);
+
+        if ("true".equalsIgnoreCase(
+                this.inlineSchemaNameDefaults.getOrDefault("SKIP_SCHEMA_REUSE", "false"))) {
+            this.skipSchemaReuse = true;
+        }
     }
 
     void flatten(OpenAPI openAPI) {
@@ -638,6 +644,10 @@ public class InlineModelResolver {
     }
 
     private String matchGenerated(Schema model) {
+        if (skipSchemaReuse) { // skip reusing schema
+            return null;
+        }
+
         try {
             String json = structureMapper.writeValueAsString(model);
             if (generatedSignature.containsKey(json)) {
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/InlineModelResolverTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/InlineModelResolverTest.java
index 6e4fa4f84f3..f21dcb2202e 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/InlineModelResolverTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/InlineModelResolverTest.java
@@ -1050,6 +1050,42 @@ public class InlineModelResolverTest {
         assertTrue(nothingNew.getProperties().get("arbitrary_request_body_array_property") instanceof ObjectSchema);
     }
 
+    @Test
+    public void testInlineSchemaSkipReuseSetToFalse() {
+        OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/inline_model_resolver.yaml");
+        InlineModelResolver resolver = new InlineModelResolver();
+        Map<String, String> inlineSchemaNameDefaults = new HashMap<>();
+        //inlineSchemaNameDefaults.put("SKIP_SCHEMA_REUSE", "false"); // default is false
+        resolver.setInlineSchemaNameDefaults(inlineSchemaNameDefaults);
+        resolver.flatten(openAPI);
+
+        Schema schema = openAPI.getComponents().getSchemas().get("meta_200_response");
+        assertTrue(schema.getProperties().get("name") instanceof StringSchema);
+        assertTrue(schema.getProperties().get("id") instanceof IntegerSchema);
+
+        // mega_200_response is NOT created since meta_200_response is reused
+        Schema schema2 = openAPI.getComponents().getSchemas().get("mega_200_response");
+        assertNull(schema2);
+    }
+
+    @Test
+    public void testInlineSchemaSkipReuseSetToTrue() {
+        OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/inline_model_resolver.yaml");
+        InlineModelResolver resolver = new InlineModelResolver();
+        Map<String, String> inlineSchemaNameDefaults = new HashMap<>();
+        inlineSchemaNameDefaults.put("SKIP_SCHEMA_REUSE", "true");
+        resolver.setInlineSchemaNameDefaults(inlineSchemaNameDefaults);
+        resolver.flatten(openAPI);
+
+        Schema schema = openAPI.getComponents().getSchemas().get("meta_200_response");
+        assertTrue(schema.getProperties().get("name") instanceof StringSchema);
+        assertTrue(schema.getProperties().get("id") instanceof IntegerSchema);
+
+        Schema schema2 = openAPI.getComponents().getSchemas().get("mega_200_response");
+        assertTrue(schema2.getProperties().get("name") instanceof StringSchema);
+        assertTrue(schema2.getProperties().get("id") instanceof IntegerSchema);
+    }
+
     @Test
     public void resolveInlineRequestBodyAllOf() {
         OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/inline_model_resolver.yaml");
diff --git a/modules/openapi-generator/src/test/resources/3_0/inline_model_resolver.yaml b/modules/openapi-generator/src/test/resources/3_0/inline_model_resolver.yaml
index 0741d3b5d77..3ac008a02aa 100644
--- a/modules/openapi-generator/src/test/resources/3_0/inline_model_resolver.yaml
+++ b/modules/openapi-generator/src/test/resources/3_0/inline_model_resolver.yaml
@@ -252,6 +252,37 @@ paths:
             application/json:
               schema:
                 type: object
+  /meta:
+    get:
+      operationId: meta
+      responses:
+        '200':
+          description: OK
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  name:
+                    type: string
+                  id:
+                    type: integer
+  /mega:
+    get:
+      operationId: mega
+      responses:
+        '200':
+          description: OK
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  name:
+                    type: string
+                  id:
+                    type: integer
+
   /arbitrary_object_response_array:
     get:
       operationId: arbitraryObjectResponseArray
-- 
GitLab