Skip to content

Commit aa9fe06

Browse files
authored
Add support useOneOfInterfaces property (#1608)
1 parent 6550c5c commit aa9fe06

File tree

15 files changed

+208
-14
lines changed

15 files changed

+208
-14
lines changed

build-logic/src/main/groovy/io.micronaut.build.internal.openapi-java-generator-test-suite.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def openapiGenerate = tasks.register("generateOpenApi", OpenApiGeneratorTask) {
2525
clientId = "myClient"
2626
clientPath = true
2727
ksp = false
28+
useOneOfInterfaces = false
2829
classpath.from(configurations.openapiGenerator)
2930
openApiDefinition.convention(layout.projectDirectory.file("petstore.json"))
3031
outputDirectory.convention(layout.buildDirectory.dir("generated/openapi"))

build-logic/src/main/groovy/io.micronaut.build.internal.openapi-kotlin-kapt-generator-test-suite.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def openapiGenerate = tasks.register("generateOpenApi", OpenApiGeneratorTask) {
2525
clientId = "myClient"
2626
clientPath = true
2727
ksp = false
28+
useOneOfInterfaces = false
2829
classpath.from(configurations.openapiGenerator)
2930
openApiDefinition.convention(layout.projectDirectory.file("petstore.json"))
3031
outputDirectory.convention(layout.buildDirectory.dir("generated/openapi"))

build-logic/src/main/groovy/io.micronaut.build.internal.openapi-kotlin-ksp-generator-test-suite.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def openapiGenerate = tasks.register("generateOpenApi", OpenApiGeneratorTask) {
2525
clientId = "myClient"
2626
clientPath = true
2727
ksp = true
28+
useOneOfInterfaces = false
2829
classpath.from(configurations.openapiGenerator)
2930
openApiDefinition.convention(layout.projectDirectory.file("petstore.json"))
3031
outputDirectory.convention(layout.buildDirectory.dir("generated/openapi"))

build-logic/src/main/groovy/io/micronaut/build/internal/openapi/OpenApiGeneratorTask.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ public abstract class OpenApiGeneratorTask extends DefaultTask {
6767
@Input
6868
public abstract Property<Boolean> getKsp();
6969

70+
@Input
71+
public abstract Property<Boolean> getUseOneOfInterfaces();
72+
7073
@Input
7174
public abstract Property<Boolean> getClientPath();
7275

@@ -144,6 +147,7 @@ public void execute() throws IOException {
144147
args.add(Boolean.toString(generatedAnnotation));
145148
args.add(Boolean.toString(getKsp().get()));
146149
args.add(Boolean.toString(getClientPath().get()));
150+
args.add(Boolean.toString(getUseOneOfInterfaces().get()));
147151
args.add(getNameMapping().get().toString());
148152
args.add(getClientId().getOrElse(""));
149153
args.add(getApiNamePrefix().getOrElse(""));

openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautJavaCodegen.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ protected AbstractMicronautJavaCodegen() {
158158
generateSwaggerAnnotations = this instanceof JavaMicronautClientCodegen ? OPT_GENERATE_SWAGGER_ANNOTATIONS_FALSE : OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2;
159159
generateOperationOnlyForFirstTag = this instanceof JavaMicronautServerCodegen;
160160
openApiNullable = false;
161+
useOneOfInterfaces = true;
161162
inlineSchemaOption.put("RESOLVE_INLINE_ENUMS", "true");
162163
// CHECKSTYLE:ON
163164

@@ -235,7 +236,7 @@ protected AbstractMicronautJavaCodegen() {
235236

236237
final CliOption serializationLibraryOpt = CliOption.newString(CodegenConstants.SERIALIZATION_LIBRARY, "Serialization library for model");
237238
serializationLibraryOpt.defaultValue(SerializationLibraryKind.JACKSON.name());
238-
Map<String, String> serializationLibraryOptions = new HashMap<>();
239+
var serializationLibraryOptions = new HashMap<String, String>();
239240
serializationLibraryOptions.put(SerializationLibraryKind.JACKSON.name(), "Jackson as serialization library");
240241
serializationLibraryOptions.put(SerializationLibraryKind.MICRONAUT_SERDE_JACKSON.name(), "Use micronaut-serialization with Jackson annotations");
241242
serializationLibraryOpt.setEnum(serializationLibraryOptions);

openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautKotlinCodegen.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import java.io.File;
5656
import java.security.SecureRandom;
5757
import java.util.ArrayList;
58+
import java.util.Collection;
5859
import java.util.EnumSet;
5960
import java.util.HashMap;
6061
import java.util.Iterator;
@@ -212,6 +213,7 @@ protected AbstractMicronautKotlinCodegen() {
212213
generateOperationOnlyForFirstTag = this instanceof KotlinMicronautServerCodegen;
213214
enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.UPPERCASE;
214215
inlineSchemaOption.put("RESOLVE_INLINE_ENUMS", "true");
216+
useOneOfInterfaces = true;
215217
// CHECKSTYLE:ON
216218

217219
// Set implemented features for user information
@@ -1274,6 +1276,9 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
12741276
var allVars = new ArrayList<CodegenProperty>();
12751277

12761278
processParentModel(model, requiredVarsWithoutDiscriminator, requiredParentVarsWithoutDiscriminator, allVars, false);
1279+
model.allVars = allVars;
1280+
1281+
processOneOfModels(model, objs.values());
12771282

12781283
var withInheritance = model.hasChildren || model.parent != null;
12791284
model.vendorExtensions.put("withInheritance", withInheritance);
@@ -1301,7 +1306,6 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
13011306
if (!requiredVarsWithoutDiscriminator.isEmpty()) {
13021307
model.vendorExtensions.put("requiredVarsWithoutDiscriminator", requiredVarsWithoutDiscriminator);
13031308
}
1304-
model.allVars = allVars;
13051309
model.vendorExtensions.put("requiredVars", requiredVars);
13061310
model.vendorExtensions.put("withRequiredOrOptionalVars", !requiredVarsWithoutDiscriminator.isEmpty() || !optionalVars.isEmpty());
13071311
model.vendorExtensions.put("optionalVars", optionalVars);
@@ -1324,6 +1328,44 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
13241328
return objs;
13251329
}
13261330

1331+
private void processOneOfModels(CodegenModel model, Collection<ModelsMap> models) {
1332+
1333+
if (!model.vendorExtensions.containsKey("x-is-one-of-interface")
1334+
|| !Boolean.parseBoolean(model.vendorExtensions.get("x-is-one-of-interface").toString())) {
1335+
return;
1336+
}
1337+
1338+
var discriminator = model.discriminator;
1339+
if (discriminator == null) {
1340+
return;
1341+
}
1342+
var oneOfInterfaceName = model.name;
1343+
for (var modelMap : models) {
1344+
var m = modelMap.getModels().get(0).getModel();
1345+
1346+
if (!m.vendorExtensions.containsKey("x-implements")) {
1347+
continue;
1348+
}
1349+
var xImplements = m.vendorExtensions.get("x-implements");
1350+
if (!(xImplements instanceof List<?> xImplementsList)) {
1351+
continue;
1352+
}
1353+
for (var implInterface : xImplementsList) {
1354+
if (!oneOfInterfaceName.equalsIgnoreCase(implInterface.toString())) {
1355+
continue;
1356+
}
1357+
for (var prop : m.allVars) {
1358+
if (prop.name.equals(discriminator.getPropertyName())) {
1359+
prop.isDiscriminator = true;
1360+
prop.isOverridden = true;
1361+
prop.vendorExtensions.put("overridden", true);
1362+
break;
1363+
}
1364+
}
1365+
}
1366+
}
1367+
}
1368+
13271369
private void processProperty(CodegenProperty property, boolean isServer, CodegenModel model, Map<String, ModelsMap> models) {
13281370

13291371
property.vendorExtensions.put("withRequiredAndOptionalVars", model.vendorExtensions.get("withRequiredAndOptionalVars"));

openapi-generator/src/main/java/io/micronaut/openapi/generator/MicronautCodeGeneratorEntryPoint.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ private void configureOptions() {
182182
javaCodeGen.setModelNameSuffix(options.modelNameSuffix);
183183
}
184184

185+
javaCodeGen.setUseOneOfInterfaces(options.useOneOfInterfaces());
185186
javaCodeGen.setReactive(options.reactive);
186187
javaCodeGen.setGenerateHttpResponseAlways(options.generateHttpResponseAlways);
187188
javaCodeGen.setGenerateHttpResponseWhereRequired(options.generateHttpResponseWhereRequired);
@@ -245,7 +246,7 @@ private void configureOptions() {
245246
if (options.modelNameSuffix != null && !options.modelNameSuffix.isBlank()) {
246247
kotlinCodeGen.setModelNameSuffix(options.modelNameSuffix);
247248
}
248-
249+
kotlinCodeGen.setUseOneOfInterfaces(options.useOneOfInterfaces);
249250
kotlinCodeGen.setReactive(options.reactive);
250251
kotlinCodeGen.setGenerateHttpResponseAlways(options.generateHttpResponseAlways);
251252
kotlinCodeGen.setGenerateHttpResponseWhereRequired(options.generateHttpResponseWhereRequired);
@@ -513,6 +514,7 @@ private static class DefaultOptionsBuilder implements MicronautCodeGeneratorOpti
513514

514515
private boolean optional;
515516
private boolean reactive = true;
517+
private boolean useOneOfInterfaces = true;
516518
private boolean generateHttpResponseAlways;
517519
private boolean generateHttpResponseWhereRequired = true;
518520
private TestFramework testFramework = TestFramework.JUNIT5;
@@ -688,6 +690,12 @@ public MicronautCodeGeneratorOptionsBuilder withDateTimeFormat(DateTimeFormat fo
688690
return this;
689691
}
690692

693+
@Override
694+
public MicronautCodeGeneratorOptionsBuilder withUseOneOfInterfaces(boolean useOneOfInterfaces) {
695+
this.useOneOfInterfaces = useOneOfInterfaces;
696+
return this;
697+
}
698+
691699
private Options build() {
692700
return new Options(
693701
lang,
@@ -715,6 +723,7 @@ private Options build() {
715723
beanValidation,
716724
optional,
717725
reactive,
726+
useOneOfInterfaces,
718727
generateHttpResponseAlways,
719728
generateHttpResponseWhereRequired,
720729
testFramework,
@@ -766,6 +775,7 @@ private record Options(
766775
boolean beanValidation,
767776
boolean optional,
768777
boolean reactive,
778+
boolean useOneOfInterfaces,
769779
boolean generateHttpResponseAlways,
770780
boolean generateHttpResponseWhereRequired,
771781
TestFramework testFramework,

openapi-generator/src/main/java/io/micronaut/openapi/generator/MicronautCodeGeneratorOptionsBuilder.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,15 @@ public interface MicronautCodeGeneratorOptionsBuilder {
248248
*/
249249
MicronautCodeGeneratorOptionsBuilder withDateTimeFormat(DateTimeFormat format);
250250

251+
/**
252+
* Flag to indicate whether to use the utils.OneOfImplementorAdditionalData related logic.
253+
*
254+
* @param useOneOfInterfaces if true, then use the utils.OneOfImplementorAdditionalData related logic.
255+
*
256+
* @return this builder
257+
*/
258+
MicronautCodeGeneratorOptionsBuilder withUseOneOfInterfaces(boolean useOneOfInterfaces);
259+
251260
/**
252261
* The possible date-time formatting configurations.
253262
*/

openapi-generator/src/main/resources/templates/java-micronaut/common/model/oneof_interface.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
{{/generatedAnnotation}}
88
{{>common/model/typeInfoAnnotation}}
99
{{>common/model/xmlAnnotation}}
10-
public interface {{classname}} {{#vendorExtensions.x-implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
10+
public interface {{classname}}{{#vendorExtensions.x-implements}}{{#-first}} extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
1111
{{/formatNoEmptyLines}}
12+
1213
{{#discriminator}}
1314
public {{propertyType}} {{propertyGetter}}();
1415
{{/discriminator}}

openapi-generator/src/main/resources/templates/kotlin-micronaut/common/model/oneof_interface.mustache

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
{{>common/generatedAnnotation}}
77
{{/generatedAnnotation}}
88
{{>common/model/typeInfoAnnotation}}
9-
{{>common/model/xmlAnnotation}}
10-
public interface {{classname}} {{#vendorExtensions.x-implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
9+
interface {{classname}}{{#vendorExtensions.x-implements}}{{#-first}} : {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
1110
{{/formatNoEmptyLines}}
11+
1212
{{#discriminator}}
13-
public {{propertyType}} {{propertyGetter}}()
13+
val {{propertyName}}: {{propertyType}}
1414
{{/discriminator}}
1515
}

0 commit comments

Comments
 (0)