Skip to content

Commit 854f16b

Browse files
committed
refactored composed schema objects generation
1 parent 6a331b0 commit 854f16b

File tree

6 files changed

+188
-78
lines changed

6 files changed

+188
-78
lines changed

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

Lines changed: 5 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import io.swagger.codegen.v3.CodegenProperty;
1717
import io.swagger.codegen.v3.CodegenResponse;
1818
import io.swagger.codegen.v3.CodegenSecurity;
19+
import io.swagger.codegen.v3.ISchemaHandler;
1920
import io.swagger.codegen.v3.SupportingFile;
2021
import io.swagger.codegen.v3.generators.examples.ExampleGenerator;
2122
import io.swagger.codegen.v3.generators.handlebars.BaseItemsHelper;
@@ -160,7 +161,6 @@ public abstract class DefaultCodegenConfig implements CodegenConfig {
160161
protected String httpUserAgent;
161162
protected Boolean hideGenerationTimestamp = true;
162163
protected TemplateEngine templateEngine = new HandlebarTemplateEngine(this);
163-
protected SchemaHandler schemaHandler = new SchemaHandler(this);
164164
// How to encode special characters like $
165165
// They are translated to words like "Dollar" and prefixed with '
166166
// Then translated back during JSON encoding and decoding
@@ -267,28 +267,6 @@ public Map<String, Object> postProcessAllModels(Map<String, Object> processedMod
267267
if (supportsInheritance) {
268268
processCodegenModels(allModels);
269269
}
270-
for (String modelName : allModels.keySet()) {
271-
final CodegenModel codegenModel = allModels.get(modelName);
272-
if (!codegenModel.vendorExtensions.containsKey("x-is-composed-model")) {
273-
continue;
274-
}
275-
List<String> modelNames = (List<String>) codegenModel.vendorExtensions.get("x-model-names");
276-
if (modelNames == null || modelNames.isEmpty()) {
277-
continue;
278-
}
279-
for (String name : modelNames) {
280-
final CodegenModel model = allModels.get(name);
281-
if (model == null) {
282-
continue;
283-
}
284-
if (model.interfaceModels == null) {
285-
model.interfaceModels = new ArrayList<>();
286-
}
287-
if (!model.interfaceModels.stream().anyMatch(value -> value.name.equalsIgnoreCase(modelName))) {
288-
model.interfaceModels.add(codegenModel);
289-
}
290-
}
291-
}
292270
return processedModels;
293271
}
294272

@@ -1299,12 +1277,6 @@ public CodegenModel fromModel(String name, Schema schema, Map<String, Schema> al
12991277
if (schema instanceof ArraySchema) {
13001278
codegenModel.getVendorExtensions().put(IS_ARRAY_MODEL_EXT_NAME, Boolean.TRUE);
13011279
codegenModel.getVendorExtensions().put(IS_CONTAINER_EXT_NAME, Boolean.TRUE);
1302-
1303-
final Schema items = ((ArraySchema) schema).getItems();
1304-
if (items != null && items instanceof ComposedSchema) {
1305-
schemaHandler.configureComposedModelFromSchemaItems(codegenModel, ((ComposedSchema) items));
1306-
}
1307-
13081280
codegenModel.arrayModelType = fromProperty(name, schema).complexType;
13091281
addParentContainer(codegenModel, name, schema);
13101282
}
@@ -1357,11 +1329,7 @@ else if (schema instanceof ComposedSchema) {
13571329
// parent model
13581330
final String parentName = getParentName(composed);
13591331
final Schema parent = StringUtils.isBlank(parentName) ? null : allDefinitions.get(parentName);
1360-
13611332
final List<Schema> allOf = composed.getAllOf();
1362-
final List<Schema> oneOf = composed.getOneOf();
1363-
final List<Schema> anyOf = composed.getAnyOf();
1364-
13651333
// interfaces (intermediate models)
13661334
if (allOf != null && !allOf.isEmpty()) {
13671335
for (int i = 0; i < allOf.size(); i++) {
@@ -1389,14 +1357,6 @@ else if (schema instanceof ComposedSchema) {
13891357
}
13901358
}
13911359
}
1392-
if (oneOf != null && !oneOf.isEmpty()) {
1393-
codegenModel.dataType = getSchemaType(composed);
1394-
this.schemaHandler.configureOneOfModel(codegenModel, oneOf);
1395-
}
1396-
if (anyOf != null && !anyOf.isEmpty()) {
1397-
codegenModel.dataType = getSchemaType(composed);
1398-
this.schemaHandler.configureAnyOfModel(codegenModel, anyOf);
1399-
}
14001360
if (parent != null) {
14011361
codegenModel.parentSchema = parentName;
14021362
codegenModel.parent = toModelName(parentName);
@@ -1704,9 +1664,6 @@ public CodegenProperty fromProperty(String name, Schema propertySchema) {
17041664
// handle inner property
17051665
CodegenProperty cp = fromProperty("inner", (Schema) propertySchema.getAdditionalProperties());
17061666
updatePropertyForMap(codegenProperty, cp);
1707-
} else if (propertySchema instanceof ComposedSchema) {
1708-
ComposedSchema composedProperty = (ComposedSchema) propertySchema;
1709-
this.schemaHandler.createCodegenModel(composedProperty, codegenProperty);
17101667
} else if (propertySchema instanceof MapSchema && hasTrueAdditionalProperties(propertySchema)) {
17111668

17121669
codegenProperty.getVendorExtensions().put(CodegenConstants.IS_CONTAINER_EXT_NAME, Boolean.TRUE);
@@ -3084,14 +3041,6 @@ private void addVars(CodegenModel codegenModel, List<CodegenProperty> vars, Map<
30843041
final CodegenProperty codegenProperty = fromProperty(key, propertySchema);
30853042
codegenProperty.required = mandatory.contains(key);
30863043

3087-
if (codegenProperty.vendorExtensions.containsKey("oneOf-model")) {
3088-
this.schemaHandler.configureOneOfModelFromProperty(codegenProperty, codegenModel);
3089-
}
3090-
3091-
if (codegenProperty.vendorExtensions.containsKey("anyOf-model")) {
3092-
this.schemaHandler.configureAnyOfModelFromProperty(codegenProperty, codegenModel);
3093-
}
3094-
30953044
if (propertySchema.get$ref() != null) {
30963045
if (this.openAPI == null) {
30973046
LOGGER.warn("open api utility object was not properly set.");
@@ -4284,4 +4233,8 @@ public void setIgnoreImportMapping(boolean ignoreImportMapping) {
42844233
public boolean defaultIgnoreImportMappingOption() {
42854234
return false;
42864235
}
4236+
4237+
public ISchemaHandler getSchemaHandler() {
4238+
return new SchemaHandler(this);
4239+
}
42874240
}

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

Lines changed: 156 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,162 @@
44
import io.swagger.codegen.v3.CodegenModelFactory;
55
import io.swagger.codegen.v3.CodegenModelType;
66
import io.swagger.codegen.v3.CodegenProperty;
7+
import io.swagger.codegen.v3.ISchemaHandler;
78
import io.swagger.codegen.v3.generators.util.OpenAPIUtil;
9+
import io.swagger.v3.oas.models.media.ArraySchema;
810
import io.swagger.v3.oas.models.media.ComposedSchema;
911
import io.swagger.v3.oas.models.media.Schema;
1012
import org.apache.commons.lang3.StringUtils;
1113

1214
import java.util.ArrayList;
1315
import java.util.List;
16+
import java.util.Map;
17+
import java.util.Optional;
1418

15-
public class SchemaHandler {
19+
public class SchemaHandler implements ISchemaHandler {
20+
21+
public static final String ONE_OF_PREFFIX = "OneOf";
22+
public static final String ANY_OF_PREFFIX = "AnyOf";
23+
public static final String ARRAY_ITEMS_SUFFIX = "Items";
1624

1725
protected DefaultCodegenConfig codegenConfig;
26+
private List<CodegenModel> composedModels = new ArrayList<>();
1827

1928
public SchemaHandler(DefaultCodegenConfig codegenConfig) {
2029
this.codegenConfig = codegenConfig;
2130
}
2231

32+
@Override
33+
public void processComposedSchemas(CodegenModel codegenModel, Schema schema, Map<String, CodegenModel> allModels) {
34+
if (schema instanceof ComposedSchema) {
35+
this.processComposedSchema(codegenModel, (ComposedSchema) schema, allModels);
36+
return;
37+
}
38+
if (schema instanceof ArraySchema) {
39+
this.processArrayItemSchema(codegenModel, (ArraySchema) schema, allModels);
40+
return;
41+
}
42+
final Map<String, Schema> properties = schema.getProperties();
43+
if (properties == null || properties.isEmpty()) {
44+
return;
45+
}
46+
for (String name : properties.keySet()) {
47+
final Schema property = properties.get(name);
48+
final Optional<CodegenProperty> optionalCodegenProperty = codegenModel.getVars()
49+
.stream()
50+
.filter(codegenProperty -> codegenProperty.baseName.equals(name))
51+
.findFirst();
52+
if (!optionalCodegenProperty.isPresent()) {
53+
continue;
54+
}
55+
final CodegenProperty codegenProperty = optionalCodegenProperty.get();
56+
final String codegenName = codegenModel.getName() + codegenConfig.toModelName(codegenProperty.getName());
57+
if (property instanceof ComposedSchema) {
58+
processComposedSchema(codegenName, codegenProperty, (ComposedSchema) property, allModels);
59+
continue;
60+
}
61+
if (schema instanceof ArraySchema) {
62+
this.processArrayItemSchema(codegenName, codegenProperty, (ArraySchema) property, allModels);
63+
continue;
64+
}
65+
}
66+
}
67+
68+
@Override
69+
public List<CodegenModel> getModels() {
70+
return composedModels;
71+
}
72+
73+
protected void processComposedSchema(CodegenModel codegenModel, ComposedSchema composedSchema, Map<String, CodegenModel> allModels) {
74+
List<Schema> schemas = composedSchema.getOneOf();
75+
CodegenModel composedModel = this.createComposedModel(ONE_OF_PREFFIX + codegenModel.getName(), schemas);
76+
if (composedModel == null) {
77+
schemas = composedSchema.getAnyOf();
78+
composedModel = this.createComposedModel(ANY_OF_PREFFIX + codegenModel.getName(), schemas);
79+
if (composedModel == null) {
80+
return;
81+
}
82+
}
83+
this.addInterfaceModel(codegenModel, composedModel);
84+
this.addInterfaces(schemas, composedModel, allModels);
85+
composedModels.add(composedModel);
86+
}
87+
88+
protected void processComposedSchema(String codegenModelName, CodegenProperty codegenProperty, ComposedSchema composedSchema, Map<String, CodegenModel> allModels) {
89+
List<Schema> schemas = composedSchema.getOneOf();
90+
CodegenModel composedModel = this.createComposedModel(ONE_OF_PREFFIX + codegenModelName, schemas);
91+
if (composedModel == null) {
92+
schemas = composedSchema.getAnyOf();
93+
composedModel = this.createComposedModel(ANY_OF_PREFFIX + codegenModelName, schemas);
94+
if (composedModel == null) {
95+
return;
96+
}
97+
}
98+
this.addInterfaces(schemas, composedModel, allModels);
99+
codegenProperty.datatype = composedModel.getName();
100+
codegenProperty.datatypeWithEnum = composedModel.getName();
101+
codegenProperty.baseType = composedModel.getName();
102+
codegenProperty.complexType = composedModel.getName();
103+
104+
composedModels.add(composedModel);
105+
}
106+
107+
protected void processArrayItemSchema(CodegenModel codegenModel, ArraySchema arraySchema, Map<String, CodegenModel> allModels) {
108+
final Schema itemsSchema = arraySchema.getItems();
109+
if (itemsSchema instanceof ComposedSchema) {
110+
final CodegenModel itemsModel = CodegenModelFactory.newInstance(CodegenModelType.MODEL);
111+
itemsModel.setName(codegenModel.name + ARRAY_ITEMS_SUFFIX);
112+
this.processComposedSchema(itemsModel, (ComposedSchema) itemsSchema, allModels);
113+
}
114+
}
115+
116+
protected void processArrayItemSchema(String codegenModelName, CodegenProperty codegenProperty, ArraySchema arraySchema, Map<String, CodegenModel> allModels) {
117+
final Schema itemsSchema = arraySchema.getItems();
118+
if (itemsSchema instanceof ComposedSchema) {
119+
this.processComposedSchema(codegenModelName, codegenProperty, (ComposedSchema) itemsSchema, allModels);
120+
}
121+
}
122+
123+
protected CodegenModel createComposedModel(String name, List<Schema> schemas) {
124+
if (schemas == null || schemas.isEmpty()) {
125+
return null;
126+
}
127+
final CodegenModel composedModel = CodegenModelFactory.newInstance(CodegenModelType.MODEL);
128+
composedModel.setIsComposedModel(true);
129+
composedModel.setInterfaces(new ArrayList<>());
130+
this.configureModel(composedModel, name);
131+
132+
return composedModel;
133+
}
134+
135+
private void addInterfaceModel(CodegenModel codegenModel, CodegenModel interfaceModel) {
136+
if (codegenModel == null) {
137+
return;
138+
}
139+
if (codegenModel.getInterfaceModels() == null) {
140+
codegenModel.setInterfaceModels(new ArrayList<>());
141+
}
142+
codegenModel.getInterfaceModels().add(interfaceModel);
143+
}
144+
145+
private void addInterfaces(List<Schema> schemas, CodegenModel codegenModel, Map<String, CodegenModel> allModels) {
146+
for (Schema interfaceSchema : schemas) {
147+
final String ref = interfaceSchema.get$ref();
148+
if (StringUtils.isBlank(ref)) {
149+
continue;
150+
}
151+
final String schemaName = ref.substring(ref.lastIndexOf("/") + 1);
152+
this.addInterfaceModel(allModels.get(codegenConfig.toModelName(schemaName)), codegenModel);
153+
}
154+
}
23155

24156
/**
25157
* creates a codegen model object based on a composed schema property.
26158
* @param composedProperty
27159
* @param codegenProperty
28160
*/
29-
public void createCodegenModel(ComposedSchema composedProperty, CodegenProperty codegenProperty) {
161+
@Deprecated
162+
protected void createCodegenModel(ComposedSchema composedProperty, CodegenProperty codegenProperty) {
30163
final List<Schema> oneOf = composedProperty.getOneOf();
31164
final List<Schema> anyOf = composedProperty.getAnyOf();
32165

@@ -45,11 +178,13 @@ public void createCodegenModel(ComposedSchema composedProperty, CodegenProperty
45178

46179
}
47180

48-
public void configureComposedModelFromSchemaItems(CodegenModel codegenModel, ComposedSchema items) {
181+
@Deprecated
182+
protected void configureComposedModelFromSchemaItems(CodegenModel codegenModel, ComposedSchema items) {
49183
List<Schema> oneOfList = items.getOneOf();
50184
if (oneOfList != null && !oneOfList.isEmpty()){
51185
String name = "OneOf" + codegenModel.name + "Items";
52-
final CodegenModel oneOfModel = createComposedModel(name);
186+
final CodegenModel oneOfModel = CodegenModelFactory.newInstance(CodegenModelType.MODEL);
187+
this.configureModel(oneOfModel, name);
53188
// setting name to be used as instance type on composed model.
54189
items.addExtension("x-model-name", codegenConfig.toModelName(name));
55190

@@ -68,7 +203,8 @@ public void configureComposedModelFromSchemaItems(CodegenModel codegenModel, Com
68203
List<Schema> anyOfList = items.getAnyOf();
69204
if (anyOfList != null && !anyOfList.isEmpty()){
70205
String name = "AnyOf" + codegenModel.name + "Items";
71-
final CodegenModel anyOfModel = createComposedModel(name);
206+
final CodegenModel anyOfModel = CodegenModelFactory.newInstance(CodegenModelType.MODEL);
207+
this.configureModel(anyOfModel, name);
72208
items.addExtension("x-model-name", codegenConfig.toModelName(name));
73209

74210
final List<String> modelNames = new ArrayList<>();
@@ -85,8 +221,11 @@ public void configureComposedModelFromSchemaItems(CodegenModel codegenModel, Com
85221
}
86222
}
87223

224+
@Deprecated
88225
public void configureOneOfModel(CodegenModel codegenModel, List<Schema> oneOf) {
89-
final CodegenModel oneOfModel = createComposedModel("OneOf" + codegenModel.name);
226+
final CodegenModel oneOfModel = CodegenModelFactory.newInstance(CodegenModelType.MODEL);
227+
this.configureModel(oneOfModel, "OneOf" + codegenModel.name);
228+
90229
final List<String> modelNames = new ArrayList<>();
91230
for (Schema interfaceSchema : oneOf) {
92231
if (StringUtils.isNotBlank(interfaceSchema.get$ref())) {
@@ -104,8 +243,10 @@ public void configureOneOfModel(CodegenModel codegenModel, List<Schema> oneOf) {
104243
}
105244
}
106245

246+
@Deprecated
107247
public void configureAnyOfModel(CodegenModel codegenModel, List<Schema> anyOf) {
108-
final CodegenModel anyOfModel = createComposedModel("AnyOf" + codegenModel.name);
248+
final CodegenModel anyOfModel = CodegenModelFactory.newInstance(CodegenModelType.MODEL);
249+
this.configureModel(anyOfModel, "AnyOf" + codegenModel.name);
109250
final List<String> modelNames = new ArrayList<>();
110251
for (Schema interfaceSchema : anyOf) {
111252
if (StringUtils.isNotBlank(interfaceSchema.get$ref())) {
@@ -123,7 +264,8 @@ public void configureAnyOfModel(CodegenModel codegenModel, List<Schema> anyOf) {
123264
}
124265
}
125266

126-
public void configureOneOfModelFromProperty(CodegenProperty codegenProperty, CodegenModel codegenModel) {
267+
@Deprecated
268+
protected void configureOneOfModelFromProperty(CodegenProperty codegenProperty, CodegenModel codegenModel) {
127269
String name = "OneOf" + codegenConfig.toModelName(codegenModel.name);
128270
name += codegenConfig.toModelName(codegenProperty.name);
129271
CodegenModel oneOfModel = (CodegenModel) codegenProperty.vendorExtensions.get("oneOf-model");
@@ -138,7 +280,8 @@ public void configureOneOfModelFromProperty(CodegenProperty codegenProperty, Cod
138280
codegenModel.vendorExtensions.put("oneOf-model", oneOfModel);
139281
}
140282

141-
public void configureAnyOfModelFromProperty(CodegenProperty codegenProperty, CodegenModel codegenModel) {
283+
@Deprecated
284+
protected void configureAnyOfModelFromProperty(CodegenProperty codegenProperty, CodegenModel codegenModel) {
142285
String name = "AnyOf" + codegenConfig.toModelName(codegenModel.name);
143286
name += codegenConfig.toModelName(codegenProperty.name);
144287
CodegenModel anyOfModel = (CodegenModel) codegenProperty.vendorExtensions.get("anyOf-model");
@@ -153,7 +296,8 @@ public void configureAnyOfModelFromProperty(CodegenProperty codegenProperty, Cod
153296
codegenModel.vendorExtensions.put("anyOf-model", anyOfModel);
154297
}
155298

156-
private CodegenModel createFromOneOfSchemas(List<Schema> schemas) {
299+
@Deprecated
300+
protected CodegenModel createFromOneOfSchemas(List<Schema> schemas) {
157301
final CodegenModel codegenModel = CodegenModelFactory.newInstance(CodegenModelType.MODEL);
158302
final List<String> modelNames = new ArrayList<>();
159303

@@ -167,21 +311,14 @@ private CodegenModel createFromOneOfSchemas(List<Schema> schemas) {
167311
return codegenModel;
168312
}
169313

170-
private CodegenModel createComposedModel(String name) {
171-
final CodegenModel composedModel = CodegenModelFactory.newInstance(CodegenModelType.MODEL);
172-
this.configureModel(composedModel, name);
173-
return composedModel;
174-
}
175-
176-
private void configureModel(CodegenModel codegenModel, String name) {
314+
protected void configureModel(CodegenModel codegenModel, String name) {
177315
codegenModel.name = name;
178316
codegenModel.classname = codegenConfig.toModelName(name);
179317
codegenModel.classVarName = codegenConfig.toVarName(name);
180318
codegenModel.classFilename = codegenConfig.toModelFilename(name);
181-
codegenModel.vendorExtensions.put("x-is-composed-model", Boolean.TRUE);
182319
}
183320

184-
private boolean hasNonObjectSchema(List<Schema> schemas) {
321+
protected boolean hasNonObjectSchema(List<Schema> schemas) {
185322
for (Schema schema : schemas) {
186323
if (!codegenConfig.isObjectSchema(schema)) {
187324
return true;

0 commit comments

Comments
 (0)