Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] [Spring] OneOf base class not generated (#9981) #10009

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,7 @@ public void postProcessParameter(CodegenParameter parameter) {
@Override
@SuppressWarnings("unused")
public void preprocessOpenAPI(OpenAPI openAPI) {
if (useOneOfInterfaces) {
if (useOneOfInterfaces && openAPI.getComponents() != null) {
// we process the openapi schema here to find oneOf schemas and create interface models for them
Map<String, Schema> schemas = new HashMap<String, Schema>(openAPI.getComponents().getSchemas());
if (schemas == null) {
Expand Down Expand Up @@ -866,28 +866,21 @@ public void preprocessOpenAPI(OpenAPI openAPI) {
}
schemas.putAll(propertySchemas);


// go through all gathered schemas and add them as interfaces to be created
for (Map.Entry<String, Schema> e : schemas.entrySet()) {
String n = toModelName(e.getKey());
Schema s = e.getValue();
String nOneOf = toModelName(n + "OneOf");
if (ModelUtils.isComposedSchema(s)) {
if (e.getKey().contains("/")) {
// if this is property schema, we also need to generate the oneOf interface model
addOneOfNameExtension((ComposedSchema) s, nOneOf);
addOneOfInterfaceModel((ComposedSchema) s, nOneOf, openAPI);
} else {
// else this is a component schema, so we will just use that as the oneOf interface model
addOneOfNameExtension((ComposedSchema) s, n);
}
} else if (ModelUtils.isArraySchema(s)) {
Schema items = ((ArraySchema) s).getItems();
String modelName = toModelName(e.getKey());
Schema schema = e.getValue();
String nOneOf = toModelName(modelName + "OneOf");
if (ModelUtils.isComposedSchema(schema)) {
addOneOfForComposedSchema(e, modelName, (ComposedSchema) schema, nOneOf, openAPI);
} else if (ModelUtils.isArraySchema(schema)) {
Schema items = ((ArraySchema) schema).getItems();
if (ModelUtils.isComposedSchema(items)) {
addOneOfNameExtension((ComposedSchema) items, nOneOf);
addOneOfInterfaceModel((ComposedSchema) items, nOneOf, openAPI);
addOneOfForComposedSchemaArray(nOneOf, modelName, (ComposedSchema) items, openAPI);
}
} else if (ModelUtils.isMapSchema(s)) {
Schema addProps = getAdditionalProperties(s);
} else if (ModelUtils.isMapSchema(schema)) {
Schema addProps = getAdditionalProperties(schema);
if (addProps != null && ModelUtils.isComposedSchema(addProps)) {
addOneOfNameExtension((ComposedSchema) addProps, nOneOf);
addOneOfInterfaceModel((ComposedSchema) addProps, nOneOf, openAPI);
Expand All @@ -897,6 +890,24 @@ public void preprocessOpenAPI(OpenAPI openAPI) {
}
}

protected void addOneOfForComposedSchemaArray(String nOneOf, String modelName,
ComposedSchema items, OpenAPI openAPI) {
addOneOfNameExtension(items, nOneOf);
addOneOfInterfaceModel(items, nOneOf, openAPI);
}

protected void addOneOfForComposedSchema(Entry<String, Schema> stringSchemaEntry, String modelName, ComposedSchema composedSchema,
String nOneOf, OpenAPI openAPI) {
if (stringSchemaEntry.getKey().contains("/")) {
// if this is property schema, we also need to generate the oneOf interface model
addOneOfNameExtension(composedSchema, nOneOf);
addOneOfInterfaceModel(composedSchema, nOneOf, openAPI);
} else {
// else this is a component schema, so we will just use that as the oneOf interface model
addOneOfNameExtension(composedSchema, modelName);
}
}

// override with any special handling of the entire OpenAPI spec document
@Override
@SuppressWarnings("unused")
Expand Down Expand Up @@ -6192,8 +6203,8 @@ protected void addBodyModelSchema(CodegenParameter codegenParameter, String name
"'application/x-www-form-urlencoded' or 'multipart/?'");
LOGGER.warn("schema: {}", schema);
LOGGER.warn("codegenModel is null. Default to UNKNOWN_BASE_TYPE");
codegenModelName = "UNKNOWN_BASE_TYPE";
codegenModelDescription = "UNKNOWN_DESCRIPTION";
codegenModelName = getCodegenModelName(codegenProperty);
}

if (StringUtils.isEmpty(bodyParameterName)) {
Expand Down Expand Up @@ -6399,6 +6410,14 @@ public CodegenParameter fromRequestBody(RequestBody body, Set<String> imports, S
return codegenParameter;
}

protected void addAdditionalImports(Set<String> imports, String complexType) {
imports.add(complexType);
}

protected String getCodegenModelName(CodegenProperty codegenProperty) {
return "UNKNOWN_BASE_TYPE";
}

private void addVarsRequiredVarsAdditionalProps(Schema schema, IJsonSchemaValidationProperties property){
setAddProps(schema, property);
if (!"object".equals(schema.getType())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.media.ComposedSchema;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.tuple.Pair;
import org.openapitools.codegen.*;
import org.openapitools.codegen.languages.features.BeanValidationFeatures;
Expand All @@ -38,6 +40,7 @@
import java.util.*;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import java.util.Map.Entry;

import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import static org.openapitools.codegen.utils.StringUtils.camelize;
Expand Down Expand Up @@ -234,6 +237,7 @@ public void processOpts() {

super.processOpts();

useOneOfInterfaces = true;
// clear model and api doc template as this codegen
// does not support auto-generated markdown doc at the moment
//TODO: add doc templates
Expand Down Expand Up @@ -577,6 +581,27 @@ public void preprocessOpenAPI(OpenAPI openAPI) {
}
}

@Override
protected void addOneOfForComposedSchema(Entry<String, Schema> stringSchemaEntry, String modelName, ComposedSchema composedSchema,
String nOneOf, OpenAPI openAPI) {
addOneOfNameExtension(composedSchema, modelName);
addOneOfInterfaceModel(composedSchema, modelName, openAPI);
}
@Override
protected void addOneOfForComposedSchemaArray(String nOneOf, String modelName,
ComposedSchema composedSchema, OpenAPI openAPI) {
addOneOfNameExtension(composedSchema, modelName);
addOneOfInterfaceModel(composedSchema, modelName, openAPI);
}

@Override
protected String getCodegenModelName(CodegenProperty codegenProperty) {
return codegenProperty.getComplexType();
}

@Override
protected void addAdditionalImports(Set<String> imports, String complexType) { }

@Override
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
Expand Down Expand Up @@ -874,4 +899,18 @@ public void setPerformBeanValidation(boolean performBeanValidation) {
public void setUseOptional(boolean useOptional) {
this.useOptional = useOptional;
}

@Override
public void addImportsToOneOfInterface(List<Map<String, String>> imports) {
for (String i : Arrays.asList("JsonSubTypes", "JsonTypeInfo")) {
Map<String, String> oneImport = new HashMap<String, String>() {{
put("import", importMapping.get(i));
}};
if (!imports.contains(oneImport)) {
imports.add(oneImport);
}
}
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import org.springframework.hateoas.RepresentationModel;
{{>enumOuterClass}}
{{/isEnum}}
{{^isEnum}}
{{>pojo}}
{{#vendorExtensions.x-is-one-of-interface}}{{>oneof_interface}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{>pojo}}{{/vendorExtensions.x-is-one-of-interface}}
{{/isEnum}}
{{/model}}
{{/models}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>typeInfoAnnotation}}{{>xmlAnnotation}}
public interface {{classname}} {{#vendorExtensions.x-implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
{{#discriminator}}
public {{propertyType}} {{propertyGetter}}();
{{/discriminator}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/{{#description}}
@ApiModel(description = "{{{.}}}"){{/description}}
{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}{{>additionalModelTypeAnnotations}}
public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}}{{^parent}}{{#hateoas}}extends RepresentationModel<{{classname}}> {{/hateoas}}{{/parent}} {{#serializableModel}}implements Serializable{{/serializableModel}} {
public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}}{{^parent}}{{#hateoas}}extends RepresentationModel<{{classname}}> {{/hateoas}}{{/parent}} {{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}} {
{{#serializableModel}}
private static final long serialVersionUID = 1L;

Expand Down