Skip to content

Commit d35000d

Browse files
[quarkus2] Add new property "config-key" and use configKey instead openApiSpecId on templating (#469)
1 parent f9cca93 commit d35000d

File tree

14 files changed

+858
-5
lines changed

14 files changed

+858
-5
lines changed

README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,52 @@ It's also possible to only use a type mapping with a fully qualified name, for i
774774

775775
See the module [type-mapping](integration-tests/type-mapping) for an example of how to use this feature.
776776

777+
## Config key
778+
779+
By default, the `@RegisterRestClient` `configKey` property is the sanitized name of the file containing the OpenAPI spec. For example, if the file name is `petstore.json`, the `configKey` will be `petstore_json`:
780+
781+
```java
782+
/* omitted */
783+
@RegisterRestClient(configKey="petstore_json")
784+
public interface DefaultApi { /* omitted */ }
785+
}
786+
```
787+
788+
If you want to use a different configKey than the default one, you can set the `quarkus.openapi-generator.codegen.spec.petstore_json.[config-key]` property.
789+
790+
Using the `config-key` the extension allow you to define all allowed properties with `quarkus.openapi-generator.codegen.spec.[my_custom_config_key].*` prefix. For example:
791+
792+
```properties
793+
quarkus.openapi-generator.codegen.spec.petstore_json.config-key=petstore
794+
quarkus.openapi-generator.codegen.spec.petstore.additional-api-type-annotations[email protected]
795+
```
796+
797+
With it, you will have the following result:
798+
799+
```java
800+
/* omitted */
801+
@RegisterRestClient(configKey="petstore")
802+
@org.test.Foo
803+
public interface DefaultApi { /* omitted */ }
804+
```
805+
806+
> **️⚠️ NOTE:** If you configure the property config-key, it will override the sanitized file name (will not consider the order of the configurations). For example, having the following configuration:
807+
808+
```properties
809+
quarkus.openapi-generator.codegen.spec.petstore_json.config-key=custom_config_key
810+
quarkus.openapi-generator.codegen.spec.custom_config_key.additional-api-type-annotations[email protected]
811+
quarkus.openapi-generator.codegen.spec.petstore_json.additional-api-type-annotations[email protected]
812+
```
813+
814+
The generated code will be:
815+
816+
```java
817+
/* omitted */
818+
@RegisterRestClient(configKey="custom_config_key")
819+
@org.test.Foo
820+
public interface DefaultApi { /* omitted */ }
821+
```
822+
777823
## Template Customization
778824

779825
You have the option to swap out the [templates used by this extension](deployment/src/main/resources/templates/libraries/microprofile) with your customized versions. To achieve this, place your custom templates under the `resources/templates` directory. It's crucial that the filename of each custom template matches that of the original template.

deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public enum ConfigName {
4949
NORMALIZER("open-api-normalizer"),
5050
RETURN_RESPONSE("return-response"),
5151
ENABLE_SECURITY_GENERATION("enable-security-generation"),
52+
CONFIG_KEY("config-key"),
5253
GENERATE_PART_FILENAME("generate-part-filename"),
5354
PART_FILENAME_VALUE("part-filename-value"),
5455
USE_FIELD_NAME_IN_PART_FILENAME("use-field-name-in-part-filename");
@@ -89,6 +90,17 @@ public static String getSpecConfigName(ConfigName configName, final Path openApi
8990
return String.format("%s.%s", getBuildTimeSpecPropertyPrefix(openApiFilePath), configName.name);
9091
}
9192

93+
/**
94+
* Return spec config name by config-key (<b>openapi-generator.codegen.spec.%s.config-key</b>) property.
95+
* For example, given a configuration <code>quarkus.openapi.generator.codegen.spec.spec_yaml.config-key=petstore</code>, the
96+
* returned value is
97+
* <code>openapi.generator.codegen.spec.petstore.mutiny</code>.
98+
*/
99+
public static String getSpecConfigNameByConfigKey(final String configKey, final ConfigName configName) {
100+
String buildTimeSpecPropertyPrefix = String.format(BUILD_TIME_SPEC_PREFIX_FORMAT, configKey);
101+
return String.format("%s.%s", buildTimeSpecPropertyPrefix, configName.name);
102+
}
103+
92104
/**
93105
* Gets the config prefix for a given OpenAPI file in the path.
94106
* For example, given a path like /home/luke/projects/petstore.json, the returned value is

deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.List;
1717
import java.util.Map;
1818
import java.util.Optional;
19+
import java.util.function.Predicate;
1920
import java.util.stream.Collectors;
2021
import java.util.stream.Stream;
2122
import java.util.stream.StreamSupport;
@@ -48,6 +49,7 @@ public abstract class OpenApiGeneratorCodeGenBase implements CodeGenProvider {
4849
static final String JSON = ".json";
4950

5051
private static final String DEFAULT_PACKAGE = "org.openapi.quarkus";
52+
private static final String CONFIG_KEY_PROPERTY = "config-key";
5153

5254
/**
5355
* The input base directory from
@@ -180,6 +182,10 @@ protected void generate(final Config config, final Path openApiFilePath, final P
180182
getValues(config, openApiFilePath, CodegenConfig.ConfigName.ADDITIONAL_API_TYPE_ANNOTATIONS, String.class)
181183
.ifPresent(generator::withAdditionalApiTypeAnnotationsConfig);
182184

185+
getConfigKeyValue(config, openApiFilePath)
186+
.ifPresentOrElse(generator::withConfigKey,
187+
() -> generator.withConfigKey(getSanitizedFileName(openApiFilePath)));
188+
183189
generator.withReturnResponse(
184190
getValues(config, openApiFilePath, CodegenConfig.ConfigName.RETURN_RESPONSE, Boolean.class).orElse(false));
185191

@@ -245,16 +251,78 @@ private Optional<String> getInputBaseDirRelativeToModule(final Path sourceDir, f
245251

246252
private <T> Optional<T> getValues(final Config config, final Path openApiFilePath, CodegenConfig.ConfigName configName,
247253
Class<T> propertyType) {
248-
return config
249-
.getOptionalValue(CodegenConfig.getSpecConfigName(configName, openApiFilePath), propertyType)
250-
.or(() -> config.getOptionalValue(CodegenConfig.getGlobalConfigName(configName), propertyType));
254+
255+
return getConfigKeyValues(config, openApiFilePath, configName, propertyType)
256+
.or(() -> getValuesBySpecConfigName(config, openApiFilePath, configName, propertyType));
251257
}
252258

253259
private <K, V> Optional<Map<K, V>> getValues(final SmallRyeConfig config, final Path openApiFilePath,
254260
CodegenConfig.ConfigName configName,
255261
Class<K> kClass, Class<V> vClass) {
262+
263+
return getConfigKeyValues(config, openApiFilePath, configName, kClass, vClass)
264+
.or(() -> getValuesBySpecConfigName(config, openApiFilePath, configName, kClass, vClass));
265+
}
266+
267+
private static <T> Optional<T> getValuesBySpecConfigName(Config config, Path openApiFilePath,
268+
CodegenConfig.ConfigName configName,
269+
Class<T> propertyType) {
270+
return config
271+
.getOptionalValue(CodegenConfig.getSpecConfigName(configName, openApiFilePath), propertyType)
272+
.or(() -> config.getOptionalValue(CodegenConfig.getGlobalConfigName(configName), propertyType));
273+
}
274+
275+
private static <K, V> Optional<Map<K, V>> getValuesBySpecConfigName(SmallRyeConfig config, Path openApiFilePath,
276+
CodegenConfig.ConfigName configName, Class<K> kClass, Class<V> vClass) {
256277
return config
257278
.getOptionalValues(CodegenConfig.getSpecConfigName(configName, openApiFilePath), kClass, vClass)
258279
.or(() -> config.getOptionalValues(CodegenConfig.getGlobalConfigName(configName), kClass, vClass));
259280
}
281+
282+
private static <T> Optional<T> getValuesByConfigKey(Config config, String configName, Class<T> propertyType,
283+
CodegenConfig.ConfigName codegenConfigName) {
284+
return config
285+
.getOptionalValue(configName, propertyType)
286+
.or(() -> config.getOptionalValue(CodegenConfig.getGlobalConfigName(codegenConfigName), propertyType));
287+
}
288+
289+
private static <K, V> Optional<Map<K, V>> getValuesByConfigKey(SmallRyeConfig config, CodegenConfig.ConfigName configName,
290+
Class<K> kClass, Class<V> vClass, String configKey) {
291+
return config
292+
.getOptionalValues(CodegenConfig.getSpecConfigNameByConfigKey(configKey, configName), kClass,
293+
vClass)
294+
.or(() -> config.getOptionalValues(CodegenConfig.getGlobalConfigName(configName), kClass, vClass));
295+
}
296+
297+
private static Optional<String> getConfigKeyValue(Config config, Path openApiFilePath) {
298+
String configKey = String.format("quarkus.openapi-generator.codegen.spec.%s.%s", getSanitizedFileName(openApiFilePath),
299+
CONFIG_KEY_PROPERTY);
300+
return config.getOptionalValue(configKey, String.class)
301+
.filter(Predicate.not(String::isBlank));
302+
}
303+
304+
private <T> Optional<T> getConfigKeyValues(final Config config, final Path openApiFilePath,
305+
CodegenConfig.ConfigName configName,
306+
Class<T> propertyType) {
307+
308+
Optional<String> possibleConfigKey = getConfigKeyValue(config, openApiFilePath);
309+
if (possibleConfigKey.isPresent()) {
310+
return getValuesByConfigKey(config, CodegenConfig.getSpecConfigNameByConfigKey(possibleConfigKey.get(), configName),
311+
propertyType, configName);
312+
}
313+
314+
return Optional.empty();
315+
}
316+
317+
private <K, V> Optional<Map<K, V>> getConfigKeyValues(final SmallRyeConfig config, final Path openApiFilePath,
318+
CodegenConfig.ConfigName configName,
319+
Class<K> kClass, Class<V> vClass) {
320+
321+
Optional<String> possibleConfigKey = getConfigKeyValue(config, openApiFilePath);
322+
if (possibleConfigKey.isPresent()) {
323+
return getValuesByConfigKey(config, configName, kClass, vClass, possibleConfigKey.get());
324+
}
325+
326+
return Optional.empty();
327+
}
260328
}

deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import org.openapitools.codegen.DefaultGenerator;
2020
import org.openapitools.codegen.config.GlobalSettings;
2121

22+
import io.smallrye.config.common.utils.StringUtil;
23+
2224
/**
2325
* Wrapper for the OpenAPIGen tool.
2426
* This is the same as calling the Maven plugin or the CLI.
@@ -216,4 +218,10 @@ private void consolidatePackageNames() {
216218
this.configurator.setModelPackage(modelPackage);
217219
this.configurator.setInvokerPackage(apiPackage);
218220
}
221+
222+
public void withConfigKey(final String config) {
223+
if (config != null && !config.isBlank()) {
224+
this.configurator.addAdditionalProperty("configKey", StringUtil.replaceNonAlphanumericByUnderscores(config));
225+
}
226+
}
219227
}

deployment/src/main/resources/templates/libraries/microprofile/api.qute

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import io.quarkiverse.openapi.generator.annotations.GeneratedParam;
3131
*/
3232
{/if}
3333
@Path("{#if useAnnotatedBasePath}{contextPath}{/if}{commonPath}")
34-
@RegisterRestClient({#if defaultServerUrl}baseUri="{defaultServerUrl}",{/if} configKey="{quarkus-generator.openApiSpecId}")
34+
@RegisterRestClient({#if defaultServerUrl}baseUri="{defaultServerUrl}",{/if} configKey="{configKey}")
3535
@GeneratedClass(value="{openapi:parseUri(inputSpec)}", tag = "{baseName}")
3636
{#if enable-security-generation && hasAuthMethods}
3737
@RegisterProvider(CompositeAuthenticationProvider.class)
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<parent>
4+
<artifactId>quarkus-openapi-generator-integration-tests</artifactId>
5+
<groupId>io.quarkiverse.openapi.generator</groupId>
6+
<version>2.0.0-SNAPSHOT</version>
7+
</parent>
8+
<modelVersion>4.0.0</modelVersion>
9+
10+
<artifactId>quarkus-openapi-generator-it-config-key</artifactId>
11+
<name>Quarkus - Openapi Generator - Integration Tests - Config Key</name>
12+
13+
<dependencies>
14+
<dependency>
15+
<groupId>io.quarkiverse.openapi.generator</groupId>
16+
<artifactId>quarkus-openapi-generator</artifactId>
17+
</dependency>
18+
<dependency>
19+
<groupId>org.assertj</groupId>
20+
<artifactId>assertj-core</artifactId>
21+
<scope>test</scope>
22+
</dependency>
23+
<dependency>
24+
<groupId>io.quarkus</groupId>
25+
<artifactId>quarkus-junit5</artifactId>
26+
<scope>test</scope>
27+
</dependency>
28+
</dependencies>
29+
<build>
30+
<plugins>
31+
<plugin>
32+
<groupId>io.quarkus</groupId>
33+
<artifactId>quarkus-maven-plugin</artifactId>
34+
<extensions>true</extensions>
35+
<executions>
36+
<execution>
37+
<goals>
38+
<goal>build</goal>
39+
<goal>generate-code</goal>
40+
<goal>generate-code-tests</goal>
41+
</goals>
42+
</execution>
43+
</executions>
44+
</plugin>
45+
</plugins>
46+
</build>
47+
<profiles>
48+
<profile>
49+
<id>native-image</id>
50+
<activation>
51+
<property>
52+
<name>native</name>
53+
</property>
54+
</activation>
55+
<build>
56+
<plugins>
57+
<plugin>
58+
<artifactId>maven-surefire-plugin</artifactId>
59+
<configuration>
60+
<skipTests>${native.surefire.skip}</skipTests>
61+
</configuration>
62+
</plugin>
63+
<plugin>
64+
<artifactId>maven-failsafe-plugin</artifactId>
65+
<executions>
66+
<execution>
67+
<goals>
68+
<goal>integration-test</goal>
69+
<goal>verify</goal>
70+
</goals>
71+
<configuration>
72+
<systemPropertyVariables>
73+
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
74+
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
75+
<maven.home>${maven.home}</maven.home>
76+
</systemPropertyVariables>
77+
</configuration>
78+
</execution>
79+
</executions>
80+
</plugin>
81+
</plugins>
82+
</build>
83+
<properties>
84+
<quarkus.package.type>native</quarkus.package.type>
85+
</properties>
86+
</profile>
87+
</profiles>
88+
89+
</project>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.quarkiverse.openapi.generator.configkey;
2+
3+
import java.lang.annotation.Retention;
4+
import java.lang.annotation.RetentionPolicy;
5+
6+
@Retention(RetentionPolicy.RUNTIME)
7+
public @interface AnotherCustomAnnotation {
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.quarkiverse.openapi.generator.configkey;
2+
3+
import java.lang.annotation.Retention;
4+
import java.lang.annotation.RetentionPolicy;
5+
6+
@Retention(RetentionPolicy.RUNTIME)
7+
public @interface CustomAnnotation {
8+
}

0 commit comments

Comments
 (0)