Skip to content

Commit 52b6265

Browse files
Adding custom properties to OpenApiSpecInputProvider (#54)
* Adding custom properties to OpenApiSpecInputProvider Signed-off-by: Ricardo Zanini <[email protected]> * Minor changes for comments Signed-off-by: Ricardo Zanini <[email protected]>
1 parent c30f9da commit 52b6265

File tree

10 files changed

+113
-32
lines changed

10 files changed

+113
-32
lines changed

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

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,29 @@
11
package io.quarkiverse.openapi.generator.deployment;
22

33
import java.nio.file.Path;
4-
import java.util.Collections;
54
import java.util.Map;
65

7-
import io.quarkus.runtime.annotations.ConfigGroup;
86
import io.quarkus.runtime.annotations.ConfigItem;
7+
import io.quarkus.runtime.annotations.ConfigPhase;
98
import io.quarkus.runtime.annotations.ConfigRoot;
109

1110
// This configuration is read in codegen phase (before build time), the annotation is for document purposes and avoiding quarkus warns
12-
@ConfigGroup
13-
@ConfigRoot(prefix = SpecConfig.BUILD_TIME_CONFIG_PREFIX)
11+
@ConfigRoot(name = SpecConfig.BUILD_TIME_CONFIG_PREFIX, phase = ConfigPhase.BUILD_TIME)
1412
public class SpecConfig {
1513

16-
public static final String BUILD_TIME_CONFIG_PREFIX = "quarkus.openapi-generator.codegen";
14+
static final String BUILD_TIME_CONFIG_PREFIX = "openapi-generator.codegen";
1715
public static final String API_PKG_SUFFIX = ".api";
1816
public static final String MODEL_PKG_SUFFIX = ".model";
1917
// package visibility for unit tests
20-
static final String BUILD_TIME_SPEC_PREFIX_FORMAT = BUILD_TIME_CONFIG_PREFIX + ".spec.\"%s\"";
18+
static final String BUILD_TIME_SPEC_PREFIX_FORMAT = "quarkus." + BUILD_TIME_CONFIG_PREFIX + ".spec.\"%s\"";
2119
private static final String BASE_PACKAGE_PROP_FORMAT = "%s.base-package";
2220
private static final String SKIP_FORM_MODEL_PROP_FORMAT = "%s.skip-form-model";
2321

2422
/**
2523
* OpenAPI Spec details for codegen configuration.
2624
*/
2725
@ConfigItem(name = "spec")
28-
Map<String, SpecItemConfig> specItem;
29-
30-
public Map<String, SpecItemConfig> getSpecItem() {
31-
return Collections.unmodifiableMap(specItem);
32-
}
26+
public Map<String, SpecItemConfig> specItem;
3327

3428
public static String resolveApiPackage(final String basePackage) {
3529
return String.format("%s%s", basePackage, API_PKG_SUFFIX);
@@ -39,7 +33,7 @@ public static String resolveModelPackage(final String basePackage) {
3933
return String.format("%s%s", basePackage, MODEL_PKG_SUFFIX);
4034
}
4135

42-
public static String getResolvedBasePackageProperty(final Path openApiFilePath) {
36+
public static String getResolvedBasePackagePropertyName(final Path openApiFilePath) {
4337
return String.format(BASE_PACKAGE_PROP_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
4438
}
4539

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
11
package io.quarkiverse.openapi.generator.deployment;
22

3-
// Configuration class for documentation purposes
3+
import java.util.Optional;
4+
5+
import io.quarkus.runtime.annotations.ConfigGroup;
46
import io.quarkus.runtime.annotations.ConfigItem;
57

8+
/*
9+
* Model for the configuration of this extension.
10+
* It's used for documentation purposes only.
11+
* The configuration is consumed in the codegen phase, before build time.
12+
* Not meant to be used outside this scope.
13+
*/
14+
@ConfigGroup
615
public class SpecItemConfig {
716

817
/**
918
* Base package for where the generated code for the given OpenAPI specification will be added.
1019
*/
11-
@ConfigItem
12-
String basePackage;
20+
@ConfigItem(name = "base-package")
21+
public String basePackage;
22+
23+
/**
24+
* Whether to skip the generation of models for form parameters
25+
*/
26+
@ConfigItem(name = "skip-form-model")
27+
public Optional<Boolean> skipFormModel;
1328

1429
}

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package io.quarkiverse.openapi.generator.deployment.codegen;
22

3-
import static io.quarkiverse.openapi.generator.deployment.SpecConfig.getResolvedBasePackageProperty;
3+
import static io.quarkiverse.openapi.generator.deployment.SpecConfig.getResolvedBasePackagePropertyName;
44
import static io.quarkiverse.openapi.generator.deployment.SpecConfig.getSkipFormModelPropertyName;
55

66
import java.io.IOException;
77
import java.nio.file.Files;
88
import java.nio.file.Path;
99
import java.util.stream.Stream;
1010

11+
import org.eclipse.microprofile.config.Config;
12+
1113
import io.quarkiverse.openapi.generator.deployment.circuitbreaker.CircuitBreakerConfigurationParser;
1214
import io.quarkiverse.openapi.generator.deployment.wrapper.OpenApiClientGeneratorWrapper;
1315
import io.quarkus.bootstrap.prebuild.CodeGenException;
@@ -43,7 +45,7 @@ public boolean trigger(CodeGenContext context) throws CodeGenException {
4345
.map(Path::toString)
4446
.filter(s -> s.endsWith(this.inputExtension()))
4547
.map(Path::of).forEach(openApiFilePath -> {
46-
this.generate(context, openApiFilePath, outDir);
48+
this.generate(context.config(), openApiFilePath, outDir);
4749
});
4850
} catch (IOException e) {
4951
throw new CodeGenException("Failed to generate java files from OpenApi files in " + openApiDir.toAbsolutePath(),
@@ -54,20 +56,18 @@ public boolean trigger(CodeGenContext context) throws CodeGenException {
5456
return false;
5557
}
5658

57-
protected void generate(CodeGenContext context, final Path openApiFilePath, final Path outDir) {
59+
protected void generate(Config config, final Path openApiFilePath, final Path outDir) {
5860
// TODO: do not generate if the output dir has generated files and the openapi file has the same checksum of the previous run
59-
final String basePackage = getResolvedBasePackageProperty(openApiFilePath);
61+
final String basePackage = getResolvedBasePackagePropertyName(openApiFilePath);
6062

6163
final OpenApiClientGeneratorWrapper generator = new OpenApiClientGeneratorWrapper(
6264
openApiFilePath.normalize(), outDir)
63-
.withModelCodeGenConfiguration(ModelCodegenConfigParser.parse(context.config(), basePackage))
65+
.withModelCodeGenConfiguration(ModelCodegenConfigParser.parse(config, basePackage))
6466
.withCircuitBreakerConfiguration(CircuitBreakerConfigurationParser.parse(
65-
context.config()));
66-
context.config()
67-
.getOptionalValue(basePackage, String.class)
67+
config));
68+
config.getOptionalValue(basePackage, String.class)
6869
.ifPresent(generator::withBasePackage);
69-
context.config()
70-
.getOptionalValue(getSkipFormModelPropertyName(openApiFilePath), String.class)
70+
config.getOptionalValue(getSkipFormModelPropertyName(openApiFilePath), String.class)
7171
.ifPresent(generator::withSkipFormModelConfig);
7272

7373
generator.generate();

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@
77
import java.nio.channels.ReadableByteChannel;
88
import java.nio.file.Path;
99
import java.nio.file.Paths;
10+
import java.util.ArrayList;
1011
import java.util.List;
1112
import java.util.ServiceLoader;
1213
import java.util.stream.Collectors;
1314

1415
import org.eclipse.microprofile.config.Config;
16+
import org.eclipse.microprofile.config.spi.ConfigSource;
1517
import org.slf4j.Logger;
1618
import org.slf4j.LoggerFactory;
1719

1820
import io.quarkus.bootstrap.prebuild.CodeGenException;
1921
import io.quarkus.deployment.CodeGenContext;
22+
import io.smallrye.config.SmallRyeConfigBuilder;
2023

2124
public class OpenApiGeneratorStreamCodeGen extends OpenApiGeneratorCodeGenBase {
2225

@@ -55,6 +58,7 @@ public String inputDirectory() {
5558
@Override
5659
public boolean trigger(CodeGenContext context) throws CodeGenException {
5760
final Path outDir = context.outDir();
61+
5862
boolean generated = false;
5963

6064
for (final OpenApiSpecInputProvider provider : this.providers) {
@@ -68,7 +72,7 @@ public boolean trigger(CodeGenContext context) throws CodeGenException {
6872
FileOutputStream output = new FileOutputStream(openApiFilePath.toString())) {
6973
output.getChannel().transferFrom(channel, 0, Integer.MAX_VALUE);
7074
LOGGER.debug("Saved OpenAPI spec input model in {}", openApiFilePath);
71-
this.generate(context, openApiFilePath, outDir);
75+
this.generate(this.mergeConfig(context, inputModel), openApiFilePath, outDir);
7276
generated = true;
7377
} catch (IOException e) {
7478
throw new UncheckedIOException("Failed to save InputStream from provider " + provider + " into location ",
@@ -79,6 +83,14 @@ public boolean trigger(CodeGenContext context) throws CodeGenException {
7983
return generated;
8084
}
8185

86+
private Config mergeConfig(CodeGenContext context, SpecInputModel inputModel) {
87+
final List<ConfigSource> sources = new ArrayList<>();
88+
context.config().getConfigSources().forEach(sources::add);
89+
return new SmallRyeConfigBuilder()
90+
.withSources(inputModel.getConfigSource())
91+
.withSources(sources).build();
92+
}
93+
8294
@Override
8395
public boolean shouldRun(Path sourceDir, Config config) {
8496
this.loadServices();

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,21 @@
33
import static java.util.Objects.requireNonNull;
44

55
import java.io.InputStream;
6+
import java.nio.file.Path;
7+
import java.util.HashMap;
8+
import java.util.Map;
69
import java.util.Objects;
710

11+
import org.eclipse.microprofile.config.spi.ConfigSource;
12+
13+
import io.quarkiverse.openapi.generator.deployment.SpecConfig;
14+
import io.smallrye.config.PropertiesConfigSource;
15+
816
public class SpecInputModel {
917

1018
private final InputStream inputStream;
1119
private final String filename;
20+
private final Map<String, String> codegenProperties = new HashMap<>();
1221

1322
public SpecInputModel(final String filename, final InputStream inputStream) {
1423
requireNonNull(inputStream, "InputStream can't be null");
@@ -17,6 +26,16 @@ public SpecInputModel(final String filename, final InputStream inputStream) {
1726
this.filename = filename;
1827
}
1928

29+
/**
30+
* @param filename the name of the file for reference
31+
* @param inputStream the content of the spec file
32+
* @param basePackageName the name of the package where the files will be generated
33+
*/
34+
public SpecInputModel(final String filename, final InputStream inputStream, final String basePackageName) {
35+
this(filename, inputStream);
36+
this.codegenProperties.put(SpecConfig.getResolvedBasePackagePropertyName(Path.of(filename)), basePackageName);
37+
}
38+
2039
public String getFileName() {
2140
return filename;
2241
}
@@ -25,6 +44,10 @@ public InputStream getInputStream() {
2544
return inputStream;
2645
}
2746

47+
public ConfigSource getConfigSource() {
48+
return new PropertiesConfigSource(this.codegenProperties, "properties", 0);
49+
}
50+
2851
@Override
2952
public String toString() {
3053
return "SpecInputModel{" +

integration-tests/generation-input/src/main/java/io/quarkiverse/openapi/generator/codegen/ClassPathPetstoreOpenApiSpecInputProvider.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.quarkiverse.openapi.generator.codegen;
22

3-
import java.util.Collections;
3+
import java.util.ArrayList;
44
import java.util.List;
55

66
import io.quarkiverse.openapi.generator.deployment.codegen.OpenApiSpecInputProvider;
@@ -16,8 +16,11 @@ public class ClassPathPetstoreOpenApiSpecInputProvider implements OpenApiSpecInp
1616

1717
@Override
1818
public List<SpecInputModel> read(CodeGenContext context) {
19-
return Collections.singletonList(
20-
new SpecInputModel("petstore.json", this.getClass().getResourceAsStream("/specs/petstore.json")));
19+
final List<SpecInputModel> inputModels = new ArrayList<>();
20+
inputModels.add(new SpecInputModel("petstore.json", this.getClass().getResourceAsStream("/specs/petstore.json")));
21+
inputModels.add(new SpecInputModel("subtraction.yaml", this.getClass().getResourceAsStream("/specs/subtraction.yaml"),
22+
"org.math"));
23+
return inputModels;
2124
}
2225

2326
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
openapi: 3.0.3
3+
info:
4+
title: Generated API
5+
version: "1.0"
6+
paths:
7+
/:
8+
post:
9+
operationId: doOperation
10+
requestBody:
11+
content:
12+
application/json:
13+
schema:
14+
$ref: '#/components/schemas/SubtractionOperation'
15+
responses:
16+
"200":
17+
description: OK
18+
components:
19+
schemas:
20+
SubtractionOperation:
21+
type: object
22+
properties:
23+
difference:
24+
format: float
25+
type: number
26+
leftElement:
27+
format: float
28+
type: number
29+
rightElement:
30+
format: float
31+
type: number

integration-tests/generation-tests/src/main/resources/application.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
quarkus.openapi-generator.codegen.spec."petstore.json".base-package=org.acme.petstore
2+
# This one is passed through the Classpath source provider. Uncomment to overwrite it
3+
#quarkus.openapi-generator.codegen.spec."subtraction.yaml".base-package=org.acme.subtraction
14
quarkus.oidc-client.client-enabled=false
25
# ${keycloak.url} is provided by test-utils
36
# petstore_auth is the name of the security scheme from the openapi spec file (petstore.json)

integration-tests/generation-tests/src/test/java/io/quarkiverse/openapi/generator/it/PetStoreTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
import javax.inject.Inject;
88

9+
import org.acme.petstore.api.PetApi;
10+
import org.acme.petstore.model.Pet;
911
import org.eclipse.microprofile.rest.client.inject.RestClient;
1012
import org.junit.jupiter.api.Test;
11-
import org.openapi.quarkus.api.PetApi;
12-
import org.openapi.quarkus.model.Pet;
1313

1414
import com.github.tomakehurst.wiremock.WireMockServer;
1515

integration-tests/generation-tests/src/test/java/io/quarkiverse/openapi/generator/it/WiremockPetStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public Map<String, String> start() {
2929
"\"name\": \"Bidu\"," +
3030
"\"status\": \"AVAILABLE\"" +
3131
"}")));
32-
return Collections.singletonMap("org.openapi.quarkus.api.PetApi/mp-rest/url", wireMockServer.baseUrl());
32+
return Collections.singletonMap("org.acme.petstore.api.PetApi/mp-rest/url", wireMockServer.baseUrl());
3333
}
3434

3535
@Override

0 commit comments

Comments
 (0)