From 7f7b87dc4a5041ac6d54f0879fec63b5a85a00c2 Mon Sep 17 00:00:00 2001 From: felixstotz Date: Wed, 19 Jul 2023 13:55:44 +0200 Subject: [PATCH 1/6] [dart-dio] fix issue with multi layered discriminators --- .../languages/DartDioClientCodegen.java | 148 ++++++++++++++---- 1 file changed, 114 insertions(+), 34 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java index f63779cb27a7..74fe9e9176c1 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java @@ -19,9 +19,11 @@ import com.google.common.collect.Sets; import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Template; + import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Discriminator; import io.swagger.v3.oas.models.media.Schema; + import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.*; @@ -84,12 +86,12 @@ public DartDioClientCodegen() { ClientModificationFeature.Authorizations, ClientModificationFeature.UserAgent ).includeSchemaSupportFeatures( - SchemaSupportFeature.Polymorphism, - SchemaSupportFeature.Union, - SchemaSupportFeature.Composite, - SchemaSupportFeature.allOf, - SchemaSupportFeature.oneOf, - SchemaSupportFeature.anyOf + SchemaSupportFeature.Polymorphism, + SchemaSupportFeature.Union, + SchemaSupportFeature.Composite, + SchemaSupportFeature.allOf, + SchemaSupportFeature.oneOf, + SchemaSupportFeature.anyOf ) ); generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata) @@ -175,8 +177,7 @@ public void processOpts() { if (!additionalProperties.containsKey(FINAL_PROPERTIES)) { additionalProperties.put(FINAL_PROPERTIES, Boolean.parseBoolean(FINAL_PROPERTIES_DEFAULT_VALUE)); LOGGER.debug("finalProperties not set, using default {}", FINAL_PROPERTIES_DEFAULT_VALUE); - } - else { + } else { additionalProperties.put(FINAL_PROPERTIES, Boolean.parseBoolean(additionalProperties.get(FINAL_PROPERTIES).toString())); } @@ -448,9 +449,9 @@ private void adaptToDartInheritance(Map objs) { cm.vendorExtensions.put(kIsPure, isPure); if (!isParent && (cm.oneOf == null || cm.oneOf.isEmpty())) { //discriminator has no meaning here - if (cm.discriminator!=null) { + if (cm.discriminator != null) { cm.vendorExtensions.put(kParentDiscriminator, cm.discriminator); - cm.discriminator=null; + cm.discriminator = null; } } @@ -553,8 +554,8 @@ private void adaptToDartInheritance(Map objs) { protected CodegenDiscriminator createDiscriminator(String schemaName, Schema schema) { CodegenDiscriminator sub = super.createDiscriminator(schemaName, schema); Discriminator originalDiscriminator = schema.getDiscriminator(); - if (originalDiscriminator!=null) { - Map originalMapping = originalDiscriminator.getMapping(); + if (originalDiscriminator != null) { + Map originalMapping = originalDiscriminator.getMapping(); if (originalMapping != null && !originalMapping.isEmpty()) { //we already have a discriminator mapping, remove everything else for (MappedModel currentMappings : new HashSet<>(sub.getMappedModels())) { @@ -570,6 +571,75 @@ protected CodegenDiscriminator createDiscriminator(String schemaName, Schema sch return sub; } + private boolean isParentRecursive(CodegenModel codegenModel, String classname) { + if ((codegenModel.parent == classname) || (codegenModel.getAllParents() != null && codegenModel.getAllParents().contains(classname)) || (codegenModel.interfaces != null && codegenModel.interfaces.contains(classname)) || (codegenModel.parentModel != null && isParentRecursive(codegenModel.parentModel, classname))) { + return true; + } + return false; + } + + // filter out all the models, which are not submodels of this model + private void filterMappedModels(CodegenModel cm) { + if (cm.discriminator != null && cm.discriminator.getMappedModels() != null) { + final CodegenDiscriminator discriminator = cm.getDiscriminator(); + final String classname = cm.getClassname(); + final Set filteredModels = new HashSet(); + final Set removedModels = new HashSet(); + for (CodegenDiscriminator.MappedModel mappedModel : discriminator.getMappedModels()) { + final CodegenModel mappedCodegenModel = mappedModel.getModel(); + // filter out all the models, which are not submodels of this model + if (isParentRecursive(mappedCodegenModel, classname)) { + filteredModels.add(mappedModel); + } else { + removedModels.add(mappedModel); + } + } + cm.discriminator.setMappedModels(filteredModels); + + Set filteredImports = new HashSet<>(); + for (String mImport : cm.getImports()) { + boolean found = false; + if (cm.parent != null) { + String parentString = rewriteImport(cm.getParent(), true); + found = parentString.equals(mImport); + } + if (!found) { + for (MappedModel mappedModel : filteredModels) { + String mappedModelImport = rewriteImport(mappedModel.getModelName(), true); + if (mappedModelImport.equals(mImport)) { + found = true; + break; + } + } + } + if (!found) { + for (CodegenProperty codegenProperty : cm.getAllVars()) { + String codeGenImport = rewriteImport(codegenProperty.getDataType(), true); + if (codeGenImport.equals(mImport)) { + found = true; + break; + } + } + } + if (!found) { + boolean removeIt = false; + for (MappedModel removedModel : removedModels) { + String removedImport = rewriteImport(removedModel.getModelName(), true); + if (removedImport.equals(mImport)) { + removeIt = true; + break; + } + } + found = !removeIt; + } + if (found) { + filteredImports.add(mImport); + } + } + cm.setImports(filteredImports); + } + } + @Override public Map postProcessAllModels(Map objs) { objs = super.postProcessAllModels(objs); @@ -584,6 +654,9 @@ public Map postProcessAllModels(Map objs) CodegenModel cm = mo.getModel(); cm.imports = rewriteImports(cm.imports, true); cm.vendorExtensions.put("x-has-vars", !cm.vars.isEmpty()); + + // filter out all the models, which are not submodels of this model + filterMappedModels(cm); } } @@ -717,32 +790,39 @@ private void addBuiltValueSerializer(BuiltValueSerializer serializer) { private Set rewriteImports(Set originalImports, boolean isModel) { Set resultImports = Sets.newHashSet(); for (String modelImport : originalImports) { - if (modelImport.startsWith("BuiltList", 0)) { - modelImport = "BuiltList"; - } else if (modelImport.startsWith("BuiltSet", 0)) { - modelImport = "BuiltSet"; - } else if (modelImport.startsWith("BuiltMap", 0)) { - modelImport = "BuiltMap"; + final String rewriteString = rewriteImport(modelImport, isModel); + if (rewriteString != null) { + resultImports.add(rewriteString); } + } + return resultImports; + } - if (imports.containsKey(modelImport)) { - String i = imports.get(modelImport); - if (Objects.equals(i, DIO_IMPORT) && !isModel) { - // Don't add imports to operations that are already imported - continue; - } - resultImports.add(i); - } else if (importMapping().containsKey(modelImport)) { - resultImports.add(importMapping().get(modelImport)); - } else if (modelImport.startsWith("dart:")) { // import dart:* directly - resultImports.add(modelImport); - } else if (modelImport.startsWith("package:")) { // e.g. package:openapi/src/model/child.dart - resultImports.add(modelImport); - } else { - resultImports.add("package:" + pubName + "/" + sourceFolder + "/" + modelPackage() + "/" + underscore(modelImport) + ".dart"); + private String rewriteImport(String modelImport, boolean isModel) { + if (modelImport.startsWith("BuiltList", 0)) { + modelImport = "BuiltList"; + } else if (modelImport.startsWith("BuiltSet", 0)) { + modelImport = "BuiltSet"; + } else if (modelImport.startsWith("BuiltMap", 0)) { + modelImport = "BuiltMap"; + } + + if (imports.containsKey(modelImport)) { + String i = imports.get(modelImport); + if (Objects.equals(i, DIO_IMPORT) && !isModel) { + // Don't add imports to operations that are already imported + return null; } + return i; + } else if (importMapping().containsKey(modelImport)) { + return importMapping().get(modelImport); + } else if (modelImport.startsWith("dart:")) { // import dart:* directly + return modelImport; + } else if (modelImport.startsWith("package:")) { // e.g. package:openapi/src/model/child.dart + return modelImport; + } else { + return "package:" + pubName + "/" + sourceFolder + "/" + modelPackage() + "/" + underscore(modelImport) + ".dart"; } - return resultImports; } static class BuiltValueSerializer { From 10a8b0380d35877de007df5521cf9a9b807db0d7 Mon Sep 17 00:00:00 2001 From: felixstotz Date: Wed, 30 Aug 2023 10:07:30 +0200 Subject: [PATCH 2/6] [dart-dio] fix ordering parents before children causing discriminatorValue to return the parent instead --- .java-version | 2 +- .../languages/DartDioClientCodegen.java | 54 ++++++++++++++++--- .../lib/src/model/entity.dart | 48 ++++++++--------- .../lib/src/model/entity_ref.dart | 24 ++++----- .../lib/src/model/animal.dart | 24 ++++----- 5 files changed, 96 insertions(+), 56 deletions(-) diff --git a/.java-version b/.java-version index 6259340971be..2dbc24b32d3c 100644 --- a/.java-version +++ b/.java-version @@ -1 +1 @@ -1.8 +11.0 diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java index 74fe9e9176c1..ade4419e30f8 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java @@ -369,6 +369,7 @@ private void syncRootTypesWithInnerVars(Map objs) { syncRootTypesWithInnerVars(allModels, model); } } + private void syncRootTypesWithInnerVars(Map objs, CodegenModel model) { List allVars = new ArrayList<>(); allVars.addAll(((Collection) model.vendorExtensions.get(kSelfAndAncestorOnlyProps))); @@ -388,6 +389,7 @@ private void syncRootTypesWithInnerVars(Map objs, CodegenM } } } + private final String kIsChild = "x-is-child"; private final String kIsParent = "x-is-parent"; private final String kIsPure = "x-is-pure"; @@ -427,7 +429,6 @@ private void adaptToDartInheritance(Map objs) { } - Set allPureClasses = new HashSet<>(); // set isChild,isParent,isPure for (java.util.Map.Entry cmEntry : allModels.entrySet()) { @@ -571,30 +572,68 @@ protected CodegenDiscriminator createDiscriminator(String schemaName, Schema sch return sub; } - private boolean isParentRecursive(CodegenModel codegenModel, String classname) { - if ((codegenModel.parent == classname) || (codegenModel.getAllParents() != null && codegenModel.getAllParents().contains(classname)) || (codegenModel.interfaces != null && codegenModel.interfaces.contains(classname)) || (codegenModel.parentModel != null && isParentRecursive(codegenModel.parentModel, classname))) { + private boolean isParentRecursive(CodegenModel codegenModel, CodegenModel parentModel, boolean acceptAllParentsNull) { + final String classname = parentModel.getClassname(); + final String childClassName = codegenModel.getClassname(); + + if ((codegenModel.parent == classname) + || (codegenModel.getAllParents() != null && codegenModel.getAllParents().contains(classname)) + || (codegenModel.interfaces != null && codegenModel.interfaces.contains(classname)) + || parentModel.anyOf.contains(childClassName) + || parentModel.oneOf.contains(childClassName) + || (codegenModel.parentModel != null && isParentRecursive(codegenModel.parentModel, parentModel, false))) { return true; } + return false; } + /// sort the models by first putting the childModels and then the parent models + private Set sortFilteredModels(Set unSortedModels) { + final Set sortedModels = new HashSet(); + final Set notSortedModels = new HashSet(); + for (MappedModel mappedModel : unSortedModels) { + final CodegenModel mappedCodegenModel = mappedModel.getModel(); + if (unSortedModels.stream().anyMatch(m -> m != mappedModel && isParentRecursive(mappedCodegenModel, m.getModel(), false))) { + notSortedModels.add(mappedModel); + } else { + sortedModels.add(mappedModel); + } + } + + final Set finishedSortedModels = new LinkedHashSet(); + if (!notSortedModels.isEmpty()) { + final Set sortedUnsortedModels = sortFilteredModels(notSortedModels); + finishedSortedModels.addAll(sortedUnsortedModels); + } + finishedSortedModels.addAll(sortedModels); + return finishedSortedModels; + } + // filter out all the models, which are not submodels of this model private void filterMappedModels(CodegenModel cm) { + if (cm.discriminator != null && cm.discriminator.getMappedModels() != null) { final CodegenDiscriminator discriminator = cm.getDiscriminator(); final String classname = cm.getClassname(); + LOGGER.info("anyOf " + classname + " : " + cm.anyOf); + LOGGER.info("oneOf " + classname + " : " + cm.oneOf); final Set filteredModels = new HashSet(); final Set removedModels = new HashSet(); - for (CodegenDiscriminator.MappedModel mappedModel : discriminator.getMappedModels()) { + for (MappedModel mappedModel : discriminator.getMappedModels()) { final CodegenModel mappedCodegenModel = mappedModel.getModel(); // filter out all the models, which are not submodels of this model - if (isParentRecursive(mappedCodegenModel, classname)) { + if (isParentRecursive(mappedCodegenModel, cm, true)) { filteredModels.add(mappedModel); } else { removedModels.add(mappedModel); } } - cm.discriminator.setMappedModels(filteredModels); + + // sort the models by first putting the childModels and then the parent models + final Set sortedModels = sortFilteredModels(filteredModels); + + cm.discriminator.setMappedModels(sortedModels); Set filteredImports = new HashSet<>(); for (String mImport : cm.getImports()) { @@ -723,7 +762,7 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List param.dataType.equals("Uint8List")) && op.responses.stream().filter(response -> response.dataType != null) - .noneMatch(response -> response.dataType.equals("Uint8List"))) { + .noneMatch(response -> response.dataType.equals("Uint8List"))) { // Remove unused imports after processing op.imports.remove("Uint8List"); } @@ -777,6 +816,7 @@ private void addBuiltValueSerializerImport(String type) { /** * Adds the serializer to the global list of custom built_value serializers. + * * @param serializer */ private void addBuiltValueSerializer(BuiltValueSerializer serializer) { diff --git a/samples/openapi3/client/petstore/dart-dio/oneof_polymorphism_and_inheritance/lib/src/model/entity.dart b/samples/openapi3/client/petstore/dart-dio/oneof_polymorphism_and_inheritance/lib/src/model/entity.dart index 7e27fab47387..6ef67ca37847 100644 --- a/samples/openapi3/client/petstore/dart-dio/oneof_polymorphism_and_inheritance/lib/src/model/entity.dart +++ b/samples/openapi3/client/petstore/dart-dio/oneof_polymorphism_and_inheritance/lib/src/model/entity.dart @@ -29,12 +29,12 @@ abstract class Entity implements Addressable, Extensible { static const String discriminatorFieldName = r'@type'; static const Map discriminatorMapping = { + r'PizzaSpeziale': PizzaSpeziale, r'Bar': Bar, - r'Bar_Create': BarCreate, r'Foo': Foo, r'Pasta': Pasta, + r'Bar_Create': BarCreate, r'Pizza': Pizza, - r'PizzaSpeziale': PizzaSpeziale, }; @BuiltValueSerializer(custom: true) @@ -43,47 +43,47 @@ abstract class Entity implements Addressable, Extensible { extension EntityDiscriminatorExt on Entity { String? get discriminatorValue { + if (this is PizzaSpeziale) { + return r'PizzaSpeziale'; + } if (this is Bar) { return r'Bar'; } - if (this is BarCreate) { - return r'Bar_Create'; - } if (this is Foo) { return r'Foo'; } if (this is Pasta) { return r'Pasta'; } + if (this is BarCreate) { + return r'Bar_Create'; + } if (this is Pizza) { return r'Pizza'; } - if (this is PizzaSpeziale) { - return r'PizzaSpeziale'; - } return null; } } extension EntityBuilderDiscriminatorExt on EntityBuilder { String? get discriminatorValue { + if (this is PizzaSpezialeBuilder) { + return r'PizzaSpeziale'; + } if (this is BarBuilder) { return r'Bar'; } - if (this is BarCreateBuilder) { - return r'Bar_Create'; - } if (this is FooBuilder) { return r'Foo'; } if (this is PastaBuilder) { return r'Pasta'; } + if (this is BarCreateBuilder) { + return r'Bar_Create'; + } if (this is PizzaBuilder) { return r'Pizza'; } - if (this is PizzaSpezialeBuilder) { - return r'PizzaSpeziale'; - } return null; } } @@ -141,24 +141,24 @@ class _$EntitySerializer implements PrimitiveSerializer { Entity object, { FullType specifiedType = FullType.unspecified, }) { + if (object is PizzaSpeziale) { + return serializers.serialize(object, specifiedType: FullType(PizzaSpeziale))!; + } if (object is Bar) { return serializers.serialize(object, specifiedType: FullType(Bar))!; } - if (object is BarCreate) { - return serializers.serialize(object, specifiedType: FullType(BarCreate))!; - } if (object is Foo) { return serializers.serialize(object, specifiedType: FullType(Foo))!; } if (object is Pasta) { return serializers.serialize(object, specifiedType: FullType(Pasta))!; } + if (object is BarCreate) { + return serializers.serialize(object, specifiedType: FullType(BarCreate))!; + } if (object is Pizza) { return serializers.serialize(object, specifiedType: FullType(Pizza))!; } - if (object is PizzaSpeziale) { - return serializers.serialize(object, specifiedType: FullType(PizzaSpeziale))!; - } return _serializeProperties(serializers, object, specifiedType: specifiedType).toList(); } @@ -172,18 +172,18 @@ class _$EntitySerializer implements PrimitiveSerializer { final discIndex = serializedList.indexOf(Entity.discriminatorFieldName) + 1; final discValue = serializers.deserialize(serializedList[discIndex], specifiedType: FullType(String)) as String; switch (discValue) { + case r'PizzaSpeziale': + return serializers.deserialize(serialized, specifiedType: FullType(PizzaSpeziale)) as PizzaSpeziale; case r'Bar': return serializers.deserialize(serialized, specifiedType: FullType(Bar)) as Bar; - case r'Bar_Create': - return serializers.deserialize(serialized, specifiedType: FullType(BarCreate)) as BarCreate; case r'Foo': return serializers.deserialize(serialized, specifiedType: FullType(Foo)) as Foo; case r'Pasta': return serializers.deserialize(serialized, specifiedType: FullType(Pasta)) as Pasta; + case r'Bar_Create': + return serializers.deserialize(serialized, specifiedType: FullType(BarCreate)) as BarCreate; case r'Pizza': return serializers.deserialize(serialized, specifiedType: FullType(Pizza)) as Pizza; - case r'PizzaSpeziale': - return serializers.deserialize(serialized, specifiedType: FullType(PizzaSpeziale)) as PizzaSpeziale; default: return serializers.deserialize(serialized, specifiedType: FullType($Entity)) as $Entity; } diff --git a/samples/openapi3/client/petstore/dart-dio/oneof_polymorphism_and_inheritance/lib/src/model/entity_ref.dart b/samples/openapi3/client/petstore/dart-dio/oneof_polymorphism_and_inheritance/lib/src/model/entity_ref.dart index 7502c94dd7f3..2d90d1746bc4 100644 --- a/samples/openapi3/client/petstore/dart-dio/oneof_polymorphism_and_inheritance/lib/src/model/entity_ref.dart +++ b/samples/openapi3/client/petstore/dart-dio/oneof_polymorphism_and_inheritance/lib/src/model/entity_ref.dart @@ -35,8 +35,8 @@ abstract class EntityRef implements Addressable, Extensible { static const String discriminatorFieldName = r'@type'; static const Map discriminatorMapping = { - r'BarRef': BarRef, r'FooRef': FooRef, + r'BarRef': BarRef, }; @BuiltValueSerializer(custom: true) @@ -45,23 +45,23 @@ abstract class EntityRef implements Addressable, Extensible { extension EntityRefDiscriminatorExt on EntityRef { String? get discriminatorValue { - if (this is BarRef) { - return r'BarRef'; - } if (this is FooRef) { return r'FooRef'; } + if (this is BarRef) { + return r'BarRef'; + } return null; } } extension EntityRefBuilderDiscriminatorExt on EntityRefBuilder { String? get discriminatorValue { - if (this is BarRefBuilder) { - return r'BarRef'; - } if (this is FooRefBuilder) { return r'FooRef'; } + if (this is BarRefBuilder) { + return r'BarRef'; + } return null; } } @@ -133,12 +133,12 @@ class _$EntityRefSerializer implements PrimitiveSerializer { EntityRef object, { FullType specifiedType = FullType.unspecified, }) { - if (object is BarRef) { - return serializers.serialize(object, specifiedType: FullType(BarRef))!; - } if (object is FooRef) { return serializers.serialize(object, specifiedType: FullType(FooRef))!; } + if (object is BarRef) { + return serializers.serialize(object, specifiedType: FullType(BarRef))!; + } return _serializeProperties(serializers, object, specifiedType: specifiedType).toList(); } @@ -152,10 +152,10 @@ class _$EntityRefSerializer implements PrimitiveSerializer { final discIndex = serializedList.indexOf(EntityRef.discriminatorFieldName) + 1; final discValue = serializers.deserialize(serializedList[discIndex], specifiedType: FullType(String)) as String; switch (discValue) { - case r'BarRef': - return serializers.deserialize(serialized, specifiedType: FullType(BarRef)) as BarRef; case r'FooRef': return serializers.deserialize(serialized, specifiedType: FullType(FooRef)) as FooRef; + case r'BarRef': + return serializers.deserialize(serialized, specifiedType: FullType(BarRef)) as BarRef; default: return serializers.deserialize(serialized, specifiedType: FullType($EntityRef)) as $EntityRef; } diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/animal.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/animal.dart index 20b3f9f50b71..d4d2d9595a6f 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/animal.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/model/animal.dart @@ -26,8 +26,8 @@ abstract class Animal { static const String discriminatorFieldName = r'className'; static const Map discriminatorMapping = { - r'CAT': Cat, r'DOG': Dog, + r'CAT': Cat, }; @BuiltValueSerializer(custom: true) @@ -36,23 +36,23 @@ abstract class Animal { extension AnimalDiscriminatorExt on Animal { String? get discriminatorValue { - if (this is Cat) { - return r'CAT'; - } if (this is Dog) { return r'DOG'; } + if (this is Cat) { + return r'CAT'; + } return null; } } extension AnimalBuilderDiscriminatorExt on AnimalBuilder { String? get discriminatorValue { - if (this is CatBuilder) { - return r'CAT'; - } if (this is DogBuilder) { return r'DOG'; } + if (this is CatBuilder) { + return r'CAT'; + } return null; } } @@ -89,12 +89,12 @@ class _$AnimalSerializer implements PrimitiveSerializer { Animal object, { FullType specifiedType = FullType.unspecified, }) { - if (object is Cat) { - return serializers.serialize(object, specifiedType: FullType(Cat))!; - } if (object is Dog) { return serializers.serialize(object, specifiedType: FullType(Dog))!; } + if (object is Cat) { + return serializers.serialize(object, specifiedType: FullType(Cat))!; + } return _serializeProperties(serializers, object, specifiedType: specifiedType).toList(); } @@ -108,10 +108,10 @@ class _$AnimalSerializer implements PrimitiveSerializer { final discIndex = serializedList.indexOf(Animal.discriminatorFieldName) + 1; final discValue = serializers.deserialize(serializedList[discIndex], specifiedType: FullType(String)) as String; switch (discValue) { - case r'CAT': - return serializers.deserialize(serialized, specifiedType: FullType(Cat)) as Cat; case r'DOG': return serializers.deserialize(serialized, specifiedType: FullType(Dog)) as Dog; + case r'CAT': + return serializers.deserialize(serialized, specifiedType: FullType(Cat)) as Cat; default: return serializers.deserialize(serialized, specifiedType: FullType($Animal)) as $Animal; } From 522b0e787513482ba94107f22af08ae5423577ba Mon Sep 17 00:00:00 2001 From: felixstotz Date: Wed, 30 Aug 2023 11:40:33 +0200 Subject: [PATCH 3/6] [dart-dio] added logging --- .../codegen/languages/DartDioClientCodegen.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java index ade4419e30f8..b99ae7bd044d 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java @@ -576,7 +576,8 @@ private boolean isParentRecursive(CodegenModel codegenModel, CodegenModel parent final String classname = parentModel.getClassname(); final String childClassName = codegenModel.getClassname(); - if ((codegenModel.parent == classname) + if (classname == childClassName + || (codegenModel.parent == classname) || (codegenModel.getAllParents() != null && codegenModel.getAllParents().contains(classname)) || (codegenModel.interfaces != null && codegenModel.interfaces.contains(classname)) || parentModel.anyOf.contains(childClassName) @@ -616,8 +617,6 @@ private void filterMappedModels(CodegenModel cm) { if (cm.discriminator != null && cm.discriminator.getMappedModels() != null) { final CodegenDiscriminator discriminator = cm.getDiscriminator(); final String classname = cm.getClassname(); - LOGGER.info("anyOf " + classname + " : " + cm.anyOf); - LOGGER.info("oneOf " + classname + " : " + cm.oneOf); final Set filteredModels = new HashSet(); final Set removedModels = new HashSet(); for (MappedModel mappedModel : discriminator.getMappedModels()) { @@ -626,6 +625,7 @@ private void filterMappedModels(CodegenModel cm) { if (isParentRecursive(mappedCodegenModel, cm, true)) { filteredModels.add(mappedModel); } else { + LOGGER.info("Removing model {} from discriminator of model {} because it is not a submodel", mappedCodegenModel.getClassname(), classname); removedModels.add(mappedModel); } } From d3caf874afc052761a291da94d8b7a94731e992e Mon Sep 17 00:00:00 2001 From: felixstotz Date: Mon, 25 Sep 2023 12:28:50 +0200 Subject: [PATCH 4/6] [dart-dio] cleanup --- .java-version | 2 +- .../codegen/languages/DartDioClientCodegen.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.java-version b/.java-version index 2dbc24b32d3c..b4de39476753 100644 --- a/.java-version +++ b/.java-version @@ -1 +1 @@ -11.0 +11 diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java index b99ae7bd044d..bfa874b77e96 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java @@ -572,17 +572,17 @@ protected CodegenDiscriminator createDiscriminator(String schemaName, Schema sch return sub; } - private boolean isParentRecursive(CodegenModel codegenModel, CodegenModel parentModel, boolean acceptAllParentsNull) { + private boolean isParentRecursive(CodegenModel codegenModel, CodegenModel parentModel, boolean allowParentIsModel) { final String classname = parentModel.getClassname(); final String childClassName = codegenModel.getClassname(); - if (classname == childClassName + if ((allowParentIsModel && classname == childClassName) || (codegenModel.parent == classname) || (codegenModel.getAllParents() != null && codegenModel.getAllParents().contains(classname)) || (codegenModel.interfaces != null && codegenModel.interfaces.contains(classname)) || parentModel.anyOf.contains(childClassName) || parentModel.oneOf.contains(childClassName) - || (codegenModel.parentModel != null && isParentRecursive(codegenModel.parentModel, parentModel, false))) { + || (codegenModel.parentModel != null && isParentRecursive(codegenModel.parentModel, parentModel, true))) { return true; } @@ -595,7 +595,7 @@ private Set sortFilteredModels(Set unSortedModels) { final Set notSortedModels = new HashSet(); for (MappedModel mappedModel : unSortedModels) { final CodegenModel mappedCodegenModel = mappedModel.getModel(); - if (unSortedModels.stream().anyMatch(m -> m != mappedModel && isParentRecursive(mappedCodegenModel, m.getModel(), false))) { + if (unSortedModels.stream().anyMatch(m -> m != mappedModel && isParentRecursive(mappedCodegenModel, m.getModel(), true))) { notSortedModels.add(mappedModel); } else { sortedModels.add(mappedModel); @@ -622,7 +622,7 @@ private void filterMappedModels(CodegenModel cm) { for (MappedModel mappedModel : discriminator.getMappedModels()) { final CodegenModel mappedCodegenModel = mappedModel.getModel(); // filter out all the models, which are not submodels of this model - if (isParentRecursive(mappedCodegenModel, cm, true)) { + if (isParentRecursive(mappedCodegenModel, cm, false)) { filteredModels.add(mappedModel); } else { LOGGER.info("Removing model {} from discriminator of model {} because it is not a submodel", mappedCodegenModel.getClassname(), classname); From 7eac64fc360547866095c4d1178fdb497a7a2bcd Mon Sep 17 00:00:00 2001 From: felixstotz Date: Tue, 26 Sep 2023 15:02:41 +0200 Subject: [PATCH 5/6] [dart-dio] fix infinite loop deserialize in multiple layered discriminators --- .../org/openapitools/codegen/CodegenDiscriminator.java | 10 ++++++++++ .../codegen/languages/DartDioClientCodegen.java | 10 +++++++++- .../built_value/class_discriminator.mustache | 4 ++-- .../serialization/built_value/class_members.mustache | 3 ++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java index 6c2b91caa932..b02d7ba63cd4 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java @@ -173,6 +173,16 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(mappingName, modelName); } + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("MappedModel{"); + sb.append("mappingName='").append(mappingName).append('\''); + sb.append(", modelName='").append(modelName).append('\''); + sb.append(", model='").append(model).append('\''); + sb.append('}'); + return sb.toString(); + } } @Override diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java index bfa874b77e96..d8f75be54c34 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java @@ -400,6 +400,7 @@ private void syncRootTypesWithInnerVars(Map objs, CodegenM private final String kSelfAndAncestorOnlyProps = "x-self-and-ancestor-only-props"; private final String kHasSelfAndAncestorOnlyProps = "x-has-self-and-ancestor-only-props"; private final String kParentDiscriminator = "x-parent-discriminator"; + private final String kDiscriminatorSelfMappedModel = "x-discriminator-self-mapped-model"; // adapts codegen models and property to dart rules of inheritance private void adaptToDartInheritance(Map objs) { @@ -625,7 +626,14 @@ private void filterMappedModels(CodegenModel cm) { if (isParentRecursive(mappedCodegenModel, cm, false)) { filteredModels.add(mappedModel); } else { - LOGGER.info("Removing model {} from discriminator of model {} because it is not a submodel", mappedCodegenModel.getClassname(), classname); +// set the default for the model, which is the same as the model itself + final String mappedCodegenModelClassname = mappedCodegenModel.getClassname(); + if(classname == mappedCodegenModelClassname) { + LOGGER.info("Removing model {} from discriminator of model {} because it is the model itself", mappedCodegenModel.getClassname(), classname); + discriminator.getVendorExtensions().put(kDiscriminatorSelfMappedModel, mappedModel); + } else { + LOGGER.info("Removing model {} from discriminator of model {} because it is not a submodel", mappedCodegenModel.getClassname(), classname); + } removedModels.add(mappedModel); } } diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_discriminator.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_discriminator.mustache index f867345883b1..511cddd409e8 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_discriminator.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_discriminator.mustache @@ -5,7 +5,7 @@ extension {{classname}}DiscriminatorExt on {{classname}} { return r'{{mappingName}}'; } {{/mappedModels}} - return null; + return {{#discriminator.vendorExtensions.x-discriminator-self-mapped-model}}r'{{mappingName}}'{{/discriminator.vendorExtensions.x-discriminator-self-mapped-model}}{{^discriminator.vendorExtensions.x-discriminator-self-mapped-model}}null{{/discriminator.vendorExtensions.x-discriminator-self-mapped-model}}; } } extension {{classname}}BuilderDiscriminatorExt on {{classname}}Builder { @@ -15,6 +15,6 @@ extension {{classname}}BuilderDiscriminatorExt on {{classname}}Builder { return r'{{mappingName}}'; } {{/mappedModels}} - return null; + return {{#discriminator.vendorExtensions.x-discriminator-self-mapped-model}}r'{{mappingName}}'{{/discriminator.vendorExtensions.x-discriminator-self-mapped-model}}{{^discriminator.vendorExtensions.x-discriminator-self-mapped-model}}null{{/discriminator.vendorExtensions.x-discriminator-self-mapped-model}}; } } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_members.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_members.mustache index 0df06e1e3073..a7c190583354 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_members.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_members.mustache @@ -24,7 +24,8 @@ {{#mappedModels}} r'{{mappingName}}': {{modelName}}, {{/mappedModels}} - };{{/hasDiscriminatorWithNonEmptyMapping}} +{{#vendorExtensions.x-discriminator-self-mapped-model}} r'{{mappingName}}': {{modelName}}, +{{/vendorExtensions.x-discriminator-self-mapped-model}} };{{/hasDiscriminatorWithNonEmptyMapping}} {{/discriminator}}{{^vendorExtensions.x-is-parent}} {{classname}}._(); From e436453bba84f125bcebf68f6755571b1eac172b Mon Sep 17 00:00:00 2001 From: felixstotz Date: Mon, 2 Oct 2023 13:12:21 +0200 Subject: [PATCH 6/6] [dart-dio] fix infinite loop tests --- .../main/java/org/openapitools/codegen/CodegenDiscriminator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java index 595786bbc706..e81bdd039622 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenDiscriminator.java @@ -193,7 +193,6 @@ public String toString() { final StringBuffer sb = new StringBuffer("MappedModel{"); sb.append("mappingName='").append(mappingName).append('\''); sb.append(", modelName='").append(modelName).append('\''); - sb.append(", model='").append(model).append('\''); sb.append('}'); return sb.toString(); }