|
21 | 21 | import com.samskivert.mustache.Mustache; |
22 | 22 | import com.samskivert.mustache.Mustache.Lambda; |
23 | 23 | import com.samskivert.mustache.Template; |
| 24 | +import io.swagger.v3.oas.models.Operation; |
| 25 | +import io.swagger.v3.oas.models.PathItem; |
| 26 | +import io.swagger.v3.oas.models.media.Content; |
24 | 27 | import io.swagger.v3.oas.models.media.Schema; |
| 28 | +import io.swagger.v3.oas.models.parameters.Parameter; |
| 29 | +import io.swagger.v3.oas.models.parameters.RequestBody; |
25 | 30 | import lombok.Getter; |
26 | 31 | import lombok.Setter; |
27 | 32 | import org.apache.commons.io.FilenameUtils; |
@@ -616,6 +621,7 @@ public ModelsMap postProcessModels(ModelsMap objs) { |
616 | 621 | @Override |
617 | 622 | public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) { |
618 | 623 | final Map<String, ModelsMap> processed = super.postProcessAllModels(objs); |
| 624 | + final Set<String> operationInputModels = getOperationInputModels(); |
619 | 625 |
|
620 | 626 | Map<String, CodegenModel> enumRefs = new HashMap<>(); |
621 | 627 | for (Map.Entry<String, ModelsMap> entry : processed.entrySet()) { |
@@ -645,6 +651,9 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) |
645 | 651 | continue; |
646 | 652 | } |
647 | 653 |
|
| 654 | + if (operationInputModels.contains(entry.getKey()) || operationInputModels.contains(model.schemaName)) { |
| 655 | + model.vendorExtensions.put(X_MODEL_IS_OPERATION_INPUT, true); |
| 656 | + } |
648 | 657 | model.vendorExtensions.put(X_MODEL_IS_MUTABLE, modelIsMutable(model, null)); |
649 | 658 |
|
650 | 659 | CodegenComposedSchemas composedSchemas = model.getComposedSchemas(); |
@@ -718,6 +727,77 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) |
718 | 727 | return processed; |
719 | 728 | } |
720 | 729 |
|
| 730 | + private Set<String> getOperationInputModels() { |
| 731 | + Set<String> operationInputModels = new HashSet<>(); |
| 732 | + Set<String> visitedModels = new HashSet<>(); |
| 733 | + if (openAPI == null || openAPI.getPaths() == null) { |
| 734 | + return operationInputModels; |
| 735 | + } |
| 736 | + |
| 737 | + for (PathItem pathItem : openAPI.getPaths().values()) { |
| 738 | + collectOperationInputModels(pathItem.getParameters(), operationInputModels, visitedModels); |
| 739 | + for (Operation operation : pathItem.readOperations()) { |
| 740 | + collectOperationInputModels(operation.getParameters(), operationInputModels, visitedModels); |
| 741 | + RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, operation.getRequestBody()); |
| 742 | + if (requestBody != null) { |
| 743 | + collectOperationInputModels(requestBody.getContent(), operationInputModels, visitedModels); |
| 744 | + } |
| 745 | + } |
| 746 | + } |
| 747 | + return operationInputModels; |
| 748 | + } |
| 749 | + |
| 750 | + private void collectOperationInputModels(List<Parameter> parameters, Set<String> operationInputModels, Set<String> visitedModels) { |
| 751 | + if (parameters == null) { |
| 752 | + return; |
| 753 | + } |
| 754 | + for (Parameter unresolvedParameter : parameters) { |
| 755 | + Parameter parameter = ModelUtils.getReferencedParameter(openAPI, unresolvedParameter); |
| 756 | + if (parameter != null) { |
| 757 | + collectOperationInputModels(parameter.getSchema(), operationInputModels, visitedModels); |
| 758 | + collectOperationInputModels(parameter.getContent(), operationInputModels, visitedModels); |
| 759 | + } |
| 760 | + } |
| 761 | + } |
| 762 | + |
| 763 | + private void collectOperationInputModels(Content content, Set<String> operationInputModels, Set<String> visitedModels) { |
| 764 | + if (content == null) { |
| 765 | + return; |
| 766 | + } |
| 767 | + content.values().forEach(mediaType -> collectOperationInputModels(mediaType.getSchema(), operationInputModels, visitedModels)); |
| 768 | + } |
| 769 | + |
| 770 | + private void collectOperationInputModels(Schema schema, Set<String> operationInputModels, Set<String> visitedModels) { |
| 771 | + if (schema == null || Boolean.TRUE.equals(schema.getReadOnly())) { |
| 772 | + return; |
| 773 | + } |
| 774 | + if (schema.get$ref() != null) { |
| 775 | + String modelName = ModelUtils.getSimpleRef(schema.get$ref()); |
| 776 | + operationInputModels.add(modelName); |
| 777 | + if (visitedModels.add(modelName)) { |
| 778 | + collectOperationInputModels(ModelUtils.getSchema(openAPI, modelName), operationInputModels, visitedModels); |
| 779 | + } |
| 780 | + } |
| 781 | + if (schema.getOneOf() != null) { |
| 782 | + schema.getOneOf().forEach(child -> collectOperationInputModels((Schema) child, operationInputModels, visitedModels)); |
| 783 | + } |
| 784 | + if (schema.getAllOf() != null) { |
| 785 | + schema.getAllOf().forEach(child -> collectOperationInputModels((Schema) child, operationInputModels, visitedModels)); |
| 786 | + } |
| 787 | + if (schema.getAnyOf() != null) { |
| 788 | + schema.getAnyOf().forEach(child -> collectOperationInputModels((Schema) child, operationInputModels, visitedModels)); |
| 789 | + } |
| 790 | + // TODO: Traverse OAS 3.1 schema keywords that can reference operation-input models, |
| 791 | + // such as prefixItems, contains, if/then/else, dependentSchemas, and unevaluatedProperties. |
| 792 | + collectOperationInputModels(ModelUtils.getSchemaItems(schema), operationInputModels, visitedModels); // in case schema has array type |
| 793 | + if (schema.getAdditionalProperties() instanceof Schema) { |
| 794 | + collectOperationInputModels((Schema) schema.getAdditionalProperties(), operationInputModels, visitedModels); |
| 795 | + } |
| 796 | + if (schema.getProperties() != null) { |
| 797 | + schema.getProperties().values().forEach(property -> collectOperationInputModels((Schema) property, operationInputModels, visitedModels)); |
| 798 | + } |
| 799 | + } |
| 800 | + |
721 | 801 | /** |
722 | 802 | * Returns true if the model contains any properties with a public setter |
723 | 803 | * If true, the model's constructor accessor should be made public to ensure end users |
|
0 commit comments