Skip to content

Commit 313cf27

Browse files
committed
java interface discriminator
1 parent 989049b commit 313cf27

File tree

4 files changed

+54
-77
lines changed

4 files changed

+54
-77
lines changed

src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java

Lines changed: 34 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,9 @@
33
import com.fasterxml.jackson.databind.JsonNode;
44
import com.github.jknack.handlebars.Handlebars;
55
import com.samskivert.mustache.Mustache;
6-
import io.swagger.codegen.v3.CliOption;
7-
import io.swagger.codegen.v3.CodegenArgument;
8-
import io.swagger.codegen.v3.CodegenConfig;
9-
import io.swagger.codegen.v3.CodegenConstants;
10-
import io.swagger.codegen.v3.CodegenContent;
11-
import io.swagger.codegen.v3.CodegenModel;
12-
import io.swagger.codegen.v3.CodegenModelFactory;
13-
import io.swagger.codegen.v3.CodegenModelType;
14-
import io.swagger.codegen.v3.CodegenOperation;
15-
import io.swagger.codegen.v3.CodegenParameter;
16-
import io.swagger.codegen.v3.CodegenProperty;
17-
import io.swagger.codegen.v3.CodegenResponse;
18-
import io.swagger.codegen.v3.CodegenSecurity;
19-
import io.swagger.codegen.v3.ISchemaHandler;
20-
import io.swagger.codegen.v3.SupportingFile;
6+
import io.swagger.codegen.v3.*;
217
import io.swagger.codegen.v3.generators.examples.ExampleGenerator;
22-
import io.swagger.codegen.v3.generators.handlebars.BaseItemsHelper;
23-
import io.swagger.codegen.v3.generators.handlebars.BracesHelper;
24-
import io.swagger.codegen.v3.generators.handlebars.HasHelper;
25-
import io.swagger.codegen.v3.generators.handlebars.HasNotHelper;
26-
import io.swagger.codegen.v3.generators.handlebars.IsHelper;
27-
import io.swagger.codegen.v3.generators.handlebars.IsNotHelper;
28-
import io.swagger.codegen.v3.generators.handlebars.NotEmptyHelper;
29-
import io.swagger.codegen.v3.generators.handlebars.StringUtilHelper;
8+
import io.swagger.codegen.v3.generators.handlebars.*;
309
import io.swagger.codegen.v3.generators.util.OpenAPIUtil;
3110
import io.swagger.codegen.v3.templates.HandlebarTemplateEngine;
3211
import io.swagger.codegen.v3.templates.MustacheTemplateEngine;
@@ -38,30 +17,8 @@
3817
import io.swagger.v3.oas.models.Operation;
3918
import io.swagger.v3.oas.models.examples.Example;
4019
import io.swagger.v3.oas.models.headers.Header;
41-
import io.swagger.v3.oas.models.media.ArraySchema;
42-
import io.swagger.v3.oas.models.media.BinarySchema;
43-
import io.swagger.v3.oas.models.media.BooleanSchema;
44-
import io.swagger.v3.oas.models.media.ByteArraySchema;
45-
import io.swagger.v3.oas.models.media.ComposedSchema;
46-
import io.swagger.v3.oas.models.media.Content;
47-
import io.swagger.v3.oas.models.media.DateSchema;
48-
import io.swagger.v3.oas.models.media.DateTimeSchema;
49-
import io.swagger.v3.oas.models.media.EmailSchema;
50-
import io.swagger.v3.oas.models.media.FileSchema;
51-
import io.swagger.v3.oas.models.media.IntegerSchema;
52-
import io.swagger.v3.oas.models.media.MapSchema;
53-
import io.swagger.v3.oas.models.media.MediaType;
54-
import io.swagger.v3.oas.models.media.NumberSchema;
55-
import io.swagger.v3.oas.models.media.ObjectSchema;
56-
import io.swagger.v3.oas.models.media.Schema;
57-
import io.swagger.v3.oas.models.media.StringSchema;
58-
import io.swagger.v3.oas.models.media.UUIDSchema;
59-
import io.swagger.v3.oas.models.parameters.CookieParameter;
60-
import io.swagger.v3.oas.models.parameters.HeaderParameter;
61-
import io.swagger.v3.oas.models.parameters.Parameter;
62-
import io.swagger.v3.oas.models.parameters.PathParameter;
63-
import io.swagger.v3.oas.models.parameters.QueryParameter;
64-
import io.swagger.v3.oas.models.parameters.RequestBody;
20+
import io.swagger.v3.oas.models.media.*;
21+
import io.swagger.v3.oas.models.parameters.*;
6522
import io.swagger.v3.oas.models.responses.ApiResponse;
6623
import io.swagger.v3.oas.models.responses.ApiResponses;
6724
import io.swagger.v3.oas.models.security.OAuthFlow;
@@ -99,16 +56,8 @@
9956
import java.util.regex.Pattern;
10057
import java.util.stream.Collectors;
10158

102-
import static io.swagger.codegen.v3.CodegenConstants.HAS_ONLY_READ_ONLY_EXT_NAME;
103-
import static io.swagger.codegen.v3.CodegenConstants.HAS_OPTIONAL_EXT_NAME;
104-
import static io.swagger.codegen.v3.CodegenConstants.HAS_REQUIRED_EXT_NAME;
105-
import static io.swagger.codegen.v3.CodegenConstants.IS_ARRAY_MODEL_EXT_NAME;
106-
import static io.swagger.codegen.v3.CodegenConstants.IS_CONTAINER_EXT_NAME;
107-
import static io.swagger.codegen.v3.CodegenConstants.IS_ENUM_EXT_NAME;
108-
import static io.swagger.codegen.v3.generators.CodegenHelper.getDefaultIncludes;
109-
import static io.swagger.codegen.v3.generators.CodegenHelper.getImportMappings;
110-
import static io.swagger.codegen.v3.generators.CodegenHelper.getTypeMappings;
111-
import static io.swagger.codegen.v3.generators.CodegenHelper.initalizeSpecialCharacterMapping;
59+
import static io.swagger.codegen.v3.CodegenConstants.*;
60+
import static io.swagger.codegen.v3.generators.CodegenHelper.*;
11261
import static io.swagger.codegen.v3.generators.handlebars.ExtensionHelper.getBooleanValue;
11362

11463
public abstract class DefaultCodegenConfig implements CodegenConfig {
@@ -1345,9 +1294,7 @@ public CodegenModel fromModel(String name, Schema schema, Map<String, Schema> al
13451294
codegenModel.getVendorExtensions().put(CodegenConstants.IS_ALIAS_EXT_NAME, typeAliases.containsKey(name));
13461295

13471296
codegenModel.discriminator = schema.getDiscriminator();
1348-
if (codegenModel.discriminator != null && codegenModel.discriminator.getPropertyName() != null) {
1349-
codegenModel.discriminator.setPropertyName(toVarName(codegenModel.discriminator.getPropertyName()));
1350-
}
1297+
13511298

13521299
if (schema.getXml() != null) {
13531300
codegenModel.xmlPrefix = schema.getXml().getPrefix();
@@ -1398,6 +1345,33 @@ else if (schema instanceof ComposedSchema) {
13981345
}
13991346
}
14001347
}
1348+
1349+
if (codegenModel.discriminator != null && codegenModel.discriminator.getPropertyName() != null) {
1350+
codegenModel.discriminator.setPropertyName(toVarName(codegenModel.discriminator.getPropertyName()));
1351+
Map<String, String> classnameKeys = new HashMap<>();
1352+
1353+
if (composed.getOneOf()!=null) {
1354+
composed.getOneOf().forEach( s -> {
1355+
1356+
codegenModel.discriminator.getMapping().keySet().stream().filter( key -> codegenModel.discriminator.getMapping().get(key).equals(s.get$ref()))
1357+
.forEach(key -> {
1358+
String mappingValue = codegenModel.discriminator.getMapping().get(key);
1359+
if (classnameKeys.containsKey(codegenModel.classname)) {
1360+
throw new IllegalArgumentException("Duplicate shema name in discriminator mapping");
1361+
}
1362+
classnameKeys.put(toModelName(mappingValue.replace("#/components/schemas/", "")),key);
1363+
});
1364+
1365+
});
1366+
1367+
codegenModel.discriminator.getMapping().putAll(classnameKeys);
1368+
1369+
}
1370+
1371+
1372+
}
1373+
1374+
14011375
} else {
14021376
allProperties = null;
14031377
allRequired = null;

src/main/java/io/swagger/codegen/v3/generators/SchemaHandler.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,7 @@ protected void addInterfaces(List<Schema> schemas, CodegenModel codegenModel, Ma
199199
codegenModel.addSubType(model);
200200
}
201201

202-
if (codegenModel.getVendorExtensions() == null || codegenModel.getVendorExtensions().containsKey("x-discriminator-type")) {
203-
continue;
204-
}
202+
205203
if (codegenModel.getDiscriminator() != null && StringUtils.isNotBlank(codegenModel.getDiscriminator().getPropertyName())) {
206204
Optional<CodegenProperty> optionalProperty = model.vars.stream()
207205
.filter(codegenProperty -> codegenProperty.baseName.equals(codegenModel.getDiscriminator().getPropertyName())).findFirst();

src/main/resources/handlebars/Java/interface.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
99
@JsonTypeInfo(
1010
use = JsonTypeInfo.Id.NAME,
1111
include = JsonTypeInfo.As.PROPERTY,
12-
property = "type")
12+
property = "{{discriminator.propertyName}}")
1313
@JsonSubTypes({
1414
{{#subTypes}}
15-
@JsonSubTypes.Type(value = {{classname}}.class, name = "{{classname}}"){{^@last}},{{/@last}}
15+
@JsonSubTypes.Type(value = {{classname}}.class, name = "{{subtypeName}}"){{^@last}},{{/@last}}
1616
{{/subTypes}}
1717
})
1818
{{/jackson}}

src/test/java/io/swagger/codegen/v3/generators/java/GeneratorResultTestJava.java

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package io.swagger.codegen.v3.generators.java;
22

3+
import com.fasterxml.jackson.annotation.JsonSubTypes;
34
import io.swagger.codegen.v3.generators.GeneratorRunner;
45
import io.swagger.codegen.v3.service.GenerationRequest;
6+
import org.apache.commons.io.FileUtils;
57
import org.testng.Assert;
68
import org.testng.annotations.Test;
79

@@ -52,6 +54,8 @@ public void interfaceWithCustomDiscriminator() throws Exception {
5254
boolean flattenInlineComposedSchema = true;
5355
String outFolder = null; // temporary folder
5456

57+
File tmpFolder = GeneratorRunner.getTmpFolder();
58+
Assert.assertNotNull(tmpFolder);
5559

5660
List<File> files = GeneratorRunner.runGenerator(
5761
name,
@@ -60,11 +64,10 @@ public void interfaceWithCustomDiscriminator() throws Exception {
6064
v2Spec,
6165
yaml,
6266
flattenInlineComposedSchema,
63-
outFolder,
67+
tmpFolder.getAbsolutePath(),
6468
options -> options.setLibrary("resttemplate"));
6569

6670

67-
6871
File interfaceFile = files.stream().filter(f -> f.getName().equals("Item.java")).findAny().orElseThrow(() -> new RuntimeException("No interface generated"));
6972

7073
String interfaceContent = new String(Files.readAllBytes(Paths.get(interfaceFile.toURI())));
@@ -73,19 +76,21 @@ public void interfaceWithCustomDiscriminator() throws Exception {
7376

7477
Matcher matcher = typeInfoPattern.matcher(interfaceContent);
7578

76-
Assert.assertTrue(matcher.matches(), "No JsonTypeInfo generated into the interface file");
79+
Assert.assertTrue(matcher.matches(),
80+
"No JsonTypeInfo generated into the interface file");
7781

78-
String generatedTypeinfoLines = matcher.group(2)+matcher.group(3)+matcher.group(4);
82+
String generatedTypeInfoLines = matcher.group(2)+matcher.group(3)+matcher.group(4);
7983

80-
Assert.assertEquals( generatedTypeinfoLines,"@JsonTypeInfo(\n" +
81-
" use = JsonTypeInfo.Id.NAME,\n" +
82-
" include = JsonTypeInfo.As.PROPERTY,\n" +
83-
" property = \"aCustomProperty\")\n" +
84-
"@JsonSubTypes({\n" +
85-
" @JsonSubTypes.Type(value = ClassA.class, name = \"typeA\"),\n" +
86-
" @JsonSubTypes.Type(value = ClassB.class, name = \"typeB\"),\n" +
87-
" @JsonSubTypes.Type(value = ClassC.class, name = \"typeC\")\n" +
84+
Assert.assertEquals( generatedTypeInfoLines, "@JsonTypeInfo(" + System.lineSeparator() +
85+
" use = JsonTypeInfo.Id.NAME," + System.lineSeparator() +
86+
" include = JsonTypeInfo.As.PROPERTY," + System.lineSeparator() +
87+
" property = \"aCustomProperty\")" + System.lineSeparator() +
88+
"@JsonSubTypes({" + System.lineSeparator() +
89+
" @JsonSubTypes.Type(value = ClassA.class, name = \"typeA\")," + System.lineSeparator() +
90+
" @JsonSubTypes.Type(value = ClassB.class, name = \"typeB\")," + System.lineSeparator() +
91+
" @JsonSubTypes.Type(value = ClassC.class, name = \"typeC\")" + System.lineSeparator() +
8892
"})", "Wrong json subtypes generated");
8993

94+
FileUtils.deleteDirectory(new File(tmpFolder.getAbsolutePath()));
9095
}
9196
}

0 commit comments

Comments
 (0)