mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-12-05 11:26:10 +00:00
Support models with multi-level hierarchy (via roxspring) (#4503)
* Example of broken multi-level hierarchy * Support for multiple levels of hierarchy in model objects * Support for multiple levels of hierarchy in generators * Regenerated samples * Temporarily skip scalaz sample verification, which is having issue with Java version in CI container * Re-enable scalaz in verify samples Co-authored-by: Rob Oxspring <roxspring@imapmail.org>
This commit is contained in:
committed by
William Cheng
parent
daec02b8c5
commit
376e419d0b
@@ -1876,7 +1876,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
|
||||
// parent model
|
||||
final String parentName = ModelUtils.getParentName(composed, allDefinitions);
|
||||
final List<String> allParents = ModelUtils.getAllParentsName(composed, allDefinitions);
|
||||
final List<String> allParents = ModelUtils.getAllParentsName(composed, allDefinitions, false);
|
||||
final Schema parent = StringUtils.isBlank(parentName) || allDefinitions == null ? null : allDefinitions.get(parentName);
|
||||
|
||||
// TODO revise the logic below to set dicriminator, xml attributes
|
||||
@@ -2083,10 +2083,8 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
Map<String, Schema> allDefinitions = ModelUtils.getSchemas(this.openAPI);
|
||||
allDefinitions.forEach((childName, child) -> {
|
||||
if (child instanceof ComposedSchema && ((ComposedSchema) child).getAllOf() != null) {
|
||||
Set<String> parentSchemas = ((ComposedSchema) child).getAllOf().stream()
|
||||
.filter(s -> s.get$ref() != null)
|
||||
.map(s -> ModelUtils.getSimpleRef(s.get$ref()))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
final List<String> parentSchemas = ModelUtils.getAllParentsName((ComposedSchema) child, allDefinitions, true);
|
||||
if (parentSchemas.contains(schemaName)) {
|
||||
discriminator.getMappedModels().add(new MappedModel(childName, toModelName(childName)));
|
||||
}
|
||||
|
||||
@@ -477,7 +477,7 @@ public abstract class AbstractEiffelCodegen extends DefaultCodegen implements Co
|
||||
// Because the child models extend the parents, the enums will be available via the parent.
|
||||
|
||||
// Only bother with reconciliation if the parent model has enums.
|
||||
if (!parentCodegenModel.hasEnums) {
|
||||
if (parentCodegenModel == null || !parentCodegenModel.hasEnums) {
|
||||
return codegenModel;
|
||||
}
|
||||
|
||||
|
||||
@@ -572,7 +572,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
|
||||
}
|
||||
|
||||
for (final CodegenProperty property : codegenModel.readWriteVars) {
|
||||
if (property.defaultValue == null && property.baseName.equals(parentCodegenModel.discriminator.getPropertyName())) {
|
||||
if (property.defaultValue == null && parentCodegenModel.discriminator != null && property.baseName.equals(parentCodegenModel.discriminator.getPropertyName())) {
|
||||
property.defaultValue = "\"" + name + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
|
||||
}
|
||||
|
||||
for (final CodegenProperty property : codegenModel.readWriteVars) {
|
||||
if (property.defaultValue == null && property.baseName.equals(parentCodegenModel.discriminator.getPropertyName())) {
|
||||
if (property.defaultValue == null && parentCodegenModel.discriminator != null && property.baseName.equals(parentCodegenModel.discriminator.getPropertyName())) {
|
||||
property.defaultValue = "\"" + name + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -937,7 +937,7 @@ public class ModelUtils {
|
||||
if (s == null) {
|
||||
LOGGER.error("Failed to obtain schema from {}", parentName);
|
||||
return "UNKNOWN_PARENT_NAME";
|
||||
} else if (s.getDiscriminator() != null && StringUtils.isNotEmpty(s.getDiscriminator().getPropertyName())) {
|
||||
} else if (hasOrInheritsDiscriminator(s, allSchemas)) {
|
||||
// discriminator.propertyName is used
|
||||
return parentName;
|
||||
} else {
|
||||
@@ -961,7 +961,7 @@ public class ModelUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<String> getAllParentsName(ComposedSchema composedSchema, Map<String, Schema> allSchemas) {
|
||||
public static List<String> getAllParentsName(ComposedSchema composedSchema, Map<String, Schema> allSchemas, boolean includeAncestors) {
|
||||
List<Schema> interfaces = getInterfaces(composedSchema);
|
||||
List<String> names = new ArrayList<String>();
|
||||
|
||||
@@ -974,9 +974,12 @@ public class ModelUtils {
|
||||
if (s == null) {
|
||||
LOGGER.error("Failed to obtain schema from {}", parentName);
|
||||
names.add("UNKNOWN_PARENT_NAME");
|
||||
} else if (s.getDiscriminator() != null && StringUtils.isNotEmpty(s.getDiscriminator().getPropertyName())) {
|
||||
} else if (hasOrInheritsDiscriminator(s, allSchemas)) {
|
||||
// discriminator.propertyName is used
|
||||
names.add(parentName);
|
||||
if (includeAncestors && s instanceof ComposedSchema) {
|
||||
names.addAll(getAllParentsName((ComposedSchema) s, allSchemas, true));
|
||||
}
|
||||
} else {
|
||||
LOGGER.debug("Not a parent since discriminator.propertyName is not set {}", s.get$ref());
|
||||
// not a parent since discriminator.propertyName is not set
|
||||
@@ -990,6 +993,32 @@ public class ModelUtils {
|
||||
return names;
|
||||
}
|
||||
|
||||
private static boolean hasOrInheritsDiscriminator(Schema schema, Map<String, Schema> allSchemas) {
|
||||
if (schema.getDiscriminator() != null && StringUtils.isNotEmpty(schema.getDiscriminator().getPropertyName())) {
|
||||
return true;
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(schema.get$ref())) {
|
||||
String parentName = getSimpleRef(schema.get$ref());
|
||||
Schema s = allSchemas.get(parentName);
|
||||
if (s != null) {
|
||||
return hasOrInheritsDiscriminator(s, allSchemas);
|
||||
}
|
||||
else {
|
||||
LOGGER.error("Failed to obtain schema from {}", parentName);
|
||||
}
|
||||
}
|
||||
else if (schema instanceof ComposedSchema) {
|
||||
final ComposedSchema composed = (ComposedSchema) schema;
|
||||
final List<Schema> interfaces = getInterfaces(composed);
|
||||
for (Schema i : interfaces) {
|
||||
if (hasOrInheritsDiscriminator(i, allSchemas)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isNullable(Schema schema) {
|
||||
if (schema == null) {
|
||||
return false;
|
||||
|
||||
@@ -488,6 +488,7 @@ public class DefaultCodegenTest {
|
||||
test.setPropertyBaseName("className");
|
||||
test.getMappedModels().add(new CodegenDiscriminator.MappedModel("Dog", "Dog"));
|
||||
test.getMappedModels().add(new CodegenDiscriminator.MappedModel("Cat", "Cat"));
|
||||
test.getMappedModels().add(new CodegenDiscriminator.MappedModel("BigCat", "BigCat"));
|
||||
Assert.assertEquals(discriminator, test);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ public abstract class JavaJaxrsBaseTest {
|
||||
String jsonSubType = "@JsonSubTypes({\n" +
|
||||
" @JsonSubTypes.Type(value = Dog.class, name = \"Dog\"),\n" +
|
||||
" @JsonSubTypes.Type(value = Cat.class, name = \"Cat\"),\n" +
|
||||
" @JsonSubTypes.Type(value = BigDog.class, name = \"BigDog\"),\n" +
|
||||
"})";
|
||||
assertFileContains(generator, outputPath + "/src/gen/java/org/openapitools/model/Animal.java", jsonTypeInfo, jsonSubType);
|
||||
}
|
||||
|
||||
@@ -1330,6 +1330,14 @@ definitions:
|
||||
properties:
|
||||
declawed:
|
||||
type: boolean
|
||||
BigCat:
|
||||
allOf:
|
||||
- $ref: '#/definitions/Cat'
|
||||
- type: object
|
||||
properties:
|
||||
kind:
|
||||
type: string
|
||||
enum: [lions, tigers, leopards, jaguars]
|
||||
Animal:
|
||||
type: object
|
||||
discriminator: className
|
||||
|
||||
Reference in New Issue
Block a user