From d85614227b70a150dc0b6d6db753118710f6284e Mon Sep 17 00:00:00 2001
From: Sergey Vladimirov <vlsergey@yandex-team.ru>
Date: Mon, 28 Feb 2022 12:42:22 +0300
Subject: [PATCH] Add beanQualifiers option to kotlin-server

---
 docs/generators/kotlin-spring.md              |  1 +
 .../languages/KotlinSpringServerCodegen.java  | 18 ++++++++++++++++
 .../main/resources/kotlin-spring/api.mustache |  2 +-
 .../kotlin-spring/apiController.mustache      |  2 +-
 .../spring/KotlinSpringServerCodegenTest.java | 21 +++++++++++++++++++
 .../resources/3_0/kotlin/bean-qualifiers.yaml | 13 ++++++++++++
 6 files changed, 55 insertions(+), 2 deletions(-)
 create mode 100644 modules/openapi-generator/src/test/resources/3_0/kotlin/bean-qualifiers.yaml

diff --git a/docs/generators/kotlin-spring.md b/docs/generators/kotlin-spring.md
index 98d5d0f1bef..bff2a15e673 100644
--- a/docs/generators/kotlin-spring.md
+++ b/docs/generators/kotlin-spring.md
@@ -23,6 +23,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
 |artifactId|Generated artifact id (name of jar).| |openapi-spring|
 |artifactVersion|Generated artifact's package version.| |1.0.0|
 |basePackage|base package (invokerPackage) for generated code| |org.openapitools|
+|beanQualifiers|Whether to add fully-qualifier class names as bean qualifiers in @Component and @RestController annotations. May be used to prevent bean names clash if multiple generated libraries (contexts) added to single project.| |false|
 |delegatePattern|Whether to generate the server files using the delegate pattern| |false|
 |enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
 |exceptionHandler|generate default global exception handlers (not compatible with reactive. enabling reactive will disable exceptionHandler )| |true|
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java
index f9ef3026e60..6adf38be358 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java
@@ -66,6 +66,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
     public static final String INTERFACE_ONLY = "interfaceOnly";
     public static final String DELEGATE_PATTERN = "delegatePattern";
     public static final String USE_TAGS = "useTags";
+    public static final String BEAN_QUALIFIERS = "beanQualifiers";
 
     private String basePackage;
     private String invokerPackage;
@@ -82,6 +83,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
     private boolean interfaceOnly = false;
     private boolean delegatePattern = false;
     protected boolean useTags = false;
+    private boolean beanQualifiers = false;
 
     public KotlinSpringServerCodegen() {
         super();
@@ -146,6 +148,9 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
         addSwitch(INTERFACE_ONLY, "Whether to generate only API interface stubs without the server files.", interfaceOnly);
         addSwitch(DELEGATE_PATTERN, "Whether to generate the server files using the delegate pattern", delegatePattern);
         addSwitch(USE_TAGS, "Whether to use tags for creating interface and controller class names", useTags);
+        addSwitch(BEAN_QUALIFIERS, "Whether to add fully-qualifier class names as bean qualifiers in @Component and " +
+                "@RestController annotations. May be used to prevent bean names clash if multiple generated libraries" +
+                " (contexts) added to single project.", beanQualifiers);
         supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
         setLibrary(SPRING_BOOT);
 
@@ -256,6 +261,14 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
         this.reactive = reactive;
     }
 
+    public boolean isBeanQualifiers() {
+        return beanQualifiers;
+    }
+
+    public void setBeanQualifiers(boolean beanQualifiers) {
+        this.beanQualifiers = beanQualifiers;
+    }
+
     @Override
     public CodegenType getTag() {
         return CodegenType.SERVER;
@@ -363,6 +376,11 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
         writePropertyBack(REACTIVE, reactive);
         writePropertyBack(EXCEPTION_HANDLER, exceptionHandler);
 
+        if (additionalProperties.containsKey(BEAN_QUALIFIERS) && library.equals(SPRING_BOOT)) {
+            this.setBeanQualifiers(convertPropertyToBoolean(BEAN_QUALIFIERS));
+        }
+        writePropertyBack(BEAN_QUALIFIERS, beanQualifiers);
+
         if (additionalProperties.containsKey(INTERFACE_ONLY)) {
             this.setInterfaceOnly(Boolean.parseBoolean(additionalProperties.get(INTERFACE_ONLY).toString()));
         }
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache
index 9ea6611216f..eb4e64ac357 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache
@@ -40,7 +40,7 @@ import kotlinx.coroutines.flow.Flow;
 import kotlin.collections.List
 import kotlin.collections.Map
 
-@RestController
+@RestController{{#beanQualifiers}}("{{package}}.{{classname}}Controller"){{/beanQualifiers}}
 {{#useBeanValidation}}
 @Validated
 {{/useBeanValidation}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/apiController.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/apiController.mustache
index 9d3f568d7c8..6e5fdb78a78 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/apiController.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/apiController.mustache
@@ -5,7 +5,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import java.util.Optional;
 {{>generatedAnnotation}}
 
-@Controller
+@Controller{{#beanQualifiers}}("{{package}}.{{classname}}Controller"){{/beanQualifiers}}
 {{=<% %>=}}
 @RequestMapping("\${openapi.<%title%>.base-path:<%>defaultBasePath%>}")
 <%={{ }}=%>
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java
index 90b5a86dc6e..20be80f2f55 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java
@@ -374,4 +374,25 @@ public class KotlinSpringServerCodegenTest {
                 "@org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME)"
         );
     }
+
+    @Test(description = "test bean qualifiers")
+    public void beanQualifiers() throws Exception {
+        File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
+        output.deleteOnExit();
+        String outputPath = output.getAbsolutePath().replace('\\', '/');
+
+        KotlinSpringServerCodegen codegen = new KotlinSpringServerCodegen();
+        codegen.setOutputDir(output.getAbsolutePath());
+        codegen.additionalProperties().put(KotlinSpringServerCodegen.BEAN_QUALIFIERS, true);
+
+        new DefaultGenerator().opts(new ClientOptInput()
+                        .openAPI(TestUtils.parseSpec("src/test/resources/3_0/kotlin/bean-qualifiers.yaml"))
+                        .config(codegen))
+                .generate();
+
+        assertFileContains(
+                Paths.get(outputPath + "/src/main/kotlin/org/openapitools/api/PingApiController.kt"),
+                "@RestController(\"org.openapitools.api.PingApiController\")"
+        );
+    }
 }
diff --git a/modules/openapi-generator/src/test/resources/3_0/kotlin/bean-qualifiers.yaml b/modules/openapi-generator/src/test/resources/3_0/kotlin/bean-qualifiers.yaml
new file mode 100644
index 00000000000..7b9d60bac6e
--- /dev/null
+++ b/modules/openapi-generator/src/test/resources/3_0/kotlin/bean-qualifiers.yaml
@@ -0,0 +1,13 @@
+openapi: "3.0.1"
+info:
+  title: test
+  version: "1.0"
+
+paths:
+
+  /ping:
+    get:
+      operationId: ping
+      responses:
+        200:
+          description: OK
-- 
GitLab