Skip to content

Commit ce41127

Browse files
committed
Fix #38 - Add option to skip generation of deprecated attributes
Signed-off-by: Ricardo Zanini <[email protected]>
1 parent b7bd2ca commit ce41127

File tree

16 files changed

+571
-54
lines changed

16 files changed

+571
-54
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ public class SpecConfig {
1111
private static final String BASE_PACKAGE_PROP_FORMAT = "%s.base-package";
1212
private static final String SKIP_FORM_MODEL_PROP_FORMAT = "%s.skip-form-model";
1313

14+
public static String resolveApiPackage(final String basePackage) {
15+
return String.format("%s%s", basePackage, API_PKG_SUFFIX);
16+
}
17+
18+
public static String resolveModelPackage(final String basePackage) {
19+
return String.format("%s%s", basePackage, MODEL_PKG_SUFFIX);
20+
}
21+
1422
public static String getResolvedBasePackageProperty(final Path openApiFilePath) {
1523
return String.format(BASE_PACKAGE_PROP_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
1624
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.quarkiverse.openapi.generator.deployment.codegen;
2+
3+
import static io.quarkiverse.openapi.generator.deployment.SpecConfig.resolveModelPackage;
4+
5+
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
import java.util.stream.Collectors;
9+
import java.util.stream.StreamSupport;
10+
11+
import org.eclipse.microprofile.config.Config;
12+
13+
/**
14+
* Extracts the Model codegen properties from a given {@link Config} reference.
15+
* These properties are then injected in the OpenAPI generator to tweak the code generation properties.
16+
*/
17+
public final class ModelCodegenConfigParser {
18+
19+
public static Map<String, Object> parse(final Config config, final String basePackage) {
20+
final List<String> modelProperties = filterModelPropertyNames(config.getPropertyNames(),
21+
resolveModelPackage(basePackage));
22+
final Map<String, Object> modelConfig = new HashMap<>();
23+
modelProperties.forEach(m -> {
24+
modelConfig.put(m, config.getValue(m, String.class));
25+
});
26+
return modelConfig;
27+
}
28+
29+
private static List<String> filterModelPropertyNames(final Iterable<String> propertyNames, final String modelPackage) {
30+
return StreamSupport.stream(propertyNames.spliterator(), false)
31+
.filter(propertyName -> propertyName.startsWith(modelPackage))
32+
.collect(Collectors.toList());
33+
}
34+
}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,16 @@ public boolean trigger(CodeGenContext context) throws CodeGenException {
5555
}
5656

5757
protected void generate(CodeGenContext context, final Path openApiFilePath, final Path outDir) {
58-
// TODO: do not generate with the output dir has generated files and the openapi file has the same checksum of the previous runz
58+
// 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);
60+
5961
final OpenApiClientGeneratorWrapper generator = new OpenApiClientGeneratorWrapper(
6062
openApiFilePath.normalize(), outDir)
63+
.withModelCodeGenConfiguration(ModelCodegenConfigParser.parse(context.config(), basePackage))
6164
.withCircuitBreakerConfiguration(CircuitBreakerConfigurationParser.parse(
6265
context.config()));
6366
context.config()
64-
.getOptionalValue(getResolvedBasePackageProperty(openApiFilePath), String.class)
67+
.getOptionalValue(basePackage, String.class)
6568
.ifPresent(generator::withBasePackage);
6669
context.config()
6770
.getOptionalValue(getSkipFormModelPropertyName(openApiFilePath), String.class)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.quarkiverse.openapi.generator.deployment.template;
2+
3+
import java.util.Map;
4+
import java.util.concurrent.CompletableFuture;
5+
import java.util.concurrent.CompletionStage;
6+
7+
import io.quarkus.qute.EvalContext;
8+
import io.quarkus.qute.ValueResolver;
9+
10+
class ModelConfigValueResolver implements ValueResolver {
11+
12+
private static final String M_GENERATE_MODEL_DEPRECATED = "generateModelDeprecated";
13+
private static final String GENERATE_DEPRECATED_PROP = "generateDeprecated";
14+
private static final String PACKAGE_PARAM = "package";
15+
private static final String CLASSNAME_PARAM = "m.classname";
16+
private static final String CODEGEN_CONFIG_PARAM = "codegen";
17+
18+
@Override
19+
public CompletionStage<Object> resolve(EvalContext context) {
20+
final CompletionStage<Object> pkg = context.evaluate(PACKAGE_PARAM);
21+
final CompletionStage<Object> classname = context.evaluate(CLASSNAME_PARAM);
22+
final CompletionStage<Object> config = context.evaluate(CODEGEN_CONFIG_PARAM);
23+
24+
// in the future, depending on the name of the method, we delegate the last composition to it
25+
return pkg.thenCompose(p -> classname
26+
.thenCompose(clazz -> config.thenCompose(cfg -> CompletableFuture.supplyAsync(() -> {
27+
final String key = String.format("%s.%s.%s", p, clazz, GENERATE_DEPRECATED_PROP);
28+
return Boolean.parseBoolean(((Map<String, Object>) cfg).getOrDefault(key, "true").toString());
29+
}))));
30+
}
31+
32+
@Override
33+
public boolean appliesTo(EvalContext context) {
34+
// we can add more methods here in the future
35+
return M_GENERATE_MODEL_DEPRECATED.equals(context.getName());
36+
}
37+
}

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

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

3+
import static io.quarkiverse.openapi.generator.deployment.SpecConfig.resolveApiPackage;
4+
import static io.quarkiverse.openapi.generator.deployment.SpecConfig.resolveModelPackage;
35
import static java.lang.Boolean.FALSE;
46
import static java.lang.Boolean.TRUE;
57

@@ -12,8 +14,6 @@
1214
import org.openapitools.codegen.DefaultGenerator;
1315
import org.openapitools.codegen.config.GlobalSettings;
1416

15-
import io.quarkiverse.openapi.generator.deployment.SpecConfig;
16-
1717
/**
1818
* Wrapper for the OpenAPIGen tool.
1919
* This is the same as calling the Maven plugin or the CLI.
@@ -76,7 +76,16 @@ public OpenApiClientGeneratorWrapper withBasePackage(final String pkg) {
7676
* @return this wrapper
7777
*/
7878
public OpenApiClientGeneratorWrapper withCircuitBreakerConfiguration(final Map<String, List<String>> config) {
79-
configurator.addAdditionalProperty("circuit-breaker", config);
79+
if (config != null) {
80+
configurator.addAdditionalProperty("circuit-breaker", config);
81+
}
82+
return this;
83+
}
84+
85+
public OpenApiClientGeneratorWrapper withModelCodeGenConfiguration(final Map<String, Object> config) {
86+
if (config != null) {
87+
configurator.addAdditionalProperty("model-codegen", config);
88+
}
8089
return this;
8190
}
8291

@@ -101,10 +110,10 @@ private void consolidatePackageNames() {
101110
basePackage = DEFAULT_PACKAGE;
102111
}
103112
if (apiPackage.isEmpty()) {
104-
this.apiPackage = basePackage.concat(SpecConfig.API_PKG_SUFFIX);
113+
this.apiPackage = resolveApiPackage(basePackage);
105114
}
106115
if (modelPackage.isEmpty()) {
107-
this.modelPackage = basePackage.concat(SpecConfig.MODEL_PKG_SUFFIX);
116+
this.modelPackage = resolveModelPackage(basePackage);
108117
}
109118
this.configurator.setPackageName(basePackage);
110119
this.configurator.setApiPackage(apiPackage);

deployment/src/main/resources/templates/model.qute

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ import javax.validation.Valid;
1515
{/if}
1616
{#for m in models}
1717
{#if m.model.isEnum}{#include enumOuterClass.qute e=m.model/}
18-
{#else}{#include pojo.qute m=m.model withXml=withXml/}{/if}
18+
{#else}{#include pojo.qute m=m.model withXml=withXml codegen=model-codegen package=modelPackage/}{/if}
1919
{/for}

deployment/src/main/resources/templates/pojo.qute

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
3232
public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if m.serializableModel} implements Serializable{/if} {
3333

3434
{#for v in m.vars}
35+
{#if !v.deprecated || generateModelDeprecated()}
3536
{#if v.isEnum}
3637
{#if v.isContainer && v.mostInnerItems}
3738
{#include enumClass.qute e=v/}
@@ -52,9 +53,11 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if m.serializa
5253
{#else}
5354
private {v.datatypeWithEnum} {v.name}{#if v.defaultValue} = {v.defaultValue}{/if};
5455
{/if}
56+
{/if}
5557
{/for}
5658

5759
{#for v in m.vars}
60+
{#if !v.deprecated || generateModelDeprecated()}
5861
/**
5962
{#if v.description}
6063
* {v.description}
@@ -112,6 +115,7 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if m.serializa
112115
{/if}
113116
{/if}
114117

118+
{/if}
115119
{/for}
116120
/**
117121
* Create a string representation of this pojo.
@@ -123,7 +127,9 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if m.serializa
123127
{#if m.parent}
124128
sb.append(" ").append(toIndentedString(super.toString())).append("\n");{/if}
125129
{#for v in m.vars}
130+
{#if !v.deprecated || generateModelDeprecated()}
126131
sb.append(" {v.name}: ").append(toIndentedString({v.name})).append("\n");
132+
{/if}
127133
{/for}
128134
sb.append("}");
129135
return sb.toString();
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.quarkiverse.openapi.generator.deployment;
2+
3+
import java.io.IOException;
4+
import java.io.UncheckedIOException;
5+
import java.net.URL;
6+
import java.util.Objects;
7+
8+
import org.eclipse.microprofile.config.Config;
9+
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
10+
11+
import io.smallrye.config.PropertiesConfigSource;
12+
13+
public final class MockConfigUtils {
14+
15+
private MockConfigUtils() {
16+
}
17+
18+
public static Config getTestConfig(String propertiesFile) {
19+
PropertiesConfigSource configSource;
20+
try {
21+
configSource = new PropertiesConfigSource(getResource(propertiesFile));
22+
} catch (IOException e) {
23+
throw new UncheckedIOException(e);
24+
}
25+
26+
return ConfigProviderResolver
27+
.instance()
28+
.getBuilder()
29+
.withSources(configSource)
30+
.build();
31+
}
32+
33+
private static URL getResource(String resourcePath) {
34+
return Objects.requireNonNull(MockConfigUtils.class.getResource(resourcePath));
35+
}
36+
37+
}

deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/circuitbreaker/CircuitBreakerConfigurationParserTest.java

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,19 @@
22

33
import static org.assertj.core.api.Assertions.assertThat;
44

5-
import java.io.IOException;
6-
import java.io.UncheckedIOException;
7-
import java.net.URL;
85
import java.util.List;
96
import java.util.Map;
10-
import java.util.Objects;
117

128
import org.eclipse.microprofile.config.Config;
13-
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
149
import org.junit.jupiter.api.Test;
1510

16-
import io.smallrye.config.PropertiesConfigSource;
11+
import io.quarkiverse.openapi.generator.deployment.MockConfigUtils;
1712

1813
class CircuitBreakerConfigurationParserTest {
1914

2015
@Test
2116
void parse() {
22-
Config config = mockConfig("/circuitbreaker/application.properties");
17+
Config config = MockConfigUtils.getTestConfig("/circuitbreaker/application.properties");
2318

2419
Map<String, List<String>> circuitBreakerConfiguration = CircuitBreakerConfigurationParser.parse(config);
2520

@@ -32,7 +27,7 @@ void parse() {
3227

3328
@Test
3429
void circuitBreakerDisabledShouldReturnEmptyConfig() {
35-
Config config = mockConfig("/circuitbreaker/circuit_breaker_disabled_application.properties");
30+
Config config = MockConfigUtils.getTestConfig("/circuitbreaker/circuit_breaker_disabled_application.properties");
3631

3732
Map<String, List<String>> circuitBreakerConfiguration = CircuitBreakerConfigurationParser.parse(config);
3833

@@ -41,29 +36,10 @@ void circuitBreakerDisabledShouldReturnEmptyConfig() {
4136

4237
@Test
4338
void missingCircuitBreakerEnabledConfigShouldReturnEmptyConfig() {
44-
Config config = mockConfig("/circuitbreaker/missing_circuit_breaker_enabled_application.properties");
39+
Config config = MockConfigUtils.getTestConfig("/circuitbreaker/missing_circuit_breaker_enabled_application.properties");
4540

4641
Map<String, List<String>> circuitBreakerConfiguration = CircuitBreakerConfigurationParser.parse(config);
4742

4843
assertThat(circuitBreakerConfiguration).isEmpty();
4944
}
50-
51-
private static Config mockConfig(String propertiesFile) {
52-
PropertiesConfigSource configSource;
53-
try {
54-
configSource = new PropertiesConfigSource(getResource(propertiesFile));
55-
} catch (IOException e) {
56-
throw new UncheckedIOException(e);
57-
}
58-
59-
return ConfigProviderResolver
60-
.instance()
61-
.getBuilder()
62-
.withSources(configSource)
63-
.build();
64-
}
65-
66-
private static URL getResource(String resourcePath) {
67-
return Objects.requireNonNull(CircuitBreakerConfigurationParserTest.class.getResource(resourcePath));
68-
}
6945
}

0 commit comments

Comments
 (0)