|
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; |
@@ -608,6 +613,7 @@ public ModelsMap postProcessModels(ModelsMap objs) { |
608 | 613 | @Override |
609 | 614 | public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) { |
610 | 615 | final Map<String, ModelsMap> processed = super.postProcessAllModels(objs); |
| 616 | + final Set<String> operationInputModels = getOperationInputModels(); |
611 | 617 |
|
612 | 618 | Map<String, CodegenModel> enumRefs = new HashMap<>(); |
613 | 619 | for (Map.Entry<String, ModelsMap> entry : processed.entrySet()) { |
@@ -637,6 +643,9 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) |
637 | 643 | continue; |
638 | 644 | } |
639 | 645 |
|
| 646 | + if (operationInputModels.contains(entry.getKey()) || operationInputModels.contains(model.schemaName)) { |
| 647 | + model.vendorExtensions.put(X_MODEL_IS_OPERATION_INPUT, true); |
| 648 | + } |
640 | 649 | model.vendorExtensions.put(X_MODEL_IS_MUTABLE, modelIsMutable(model, null)); |
641 | 650 |
|
642 | 651 | CodegenComposedSchemas composedSchemas = model.getComposedSchemas(); |
@@ -710,6 +719,77 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) |
710 | 719 | return processed; |
711 | 720 | } |
712 | 721 |
|
| 722 | + private Set<String> getOperationInputModels() { |
| 723 | + Set<String> operationInputModels = new HashSet<>(); |
| 724 | + Set<String> visitedModels = new HashSet<>(); |
| 725 | + if (openAPI == null || openAPI.getPaths() == null) { |
| 726 | + return operationInputModels; |
| 727 | + } |
| 728 | + |
| 729 | + for (PathItem pathItem : openAPI.getPaths().values()) { |
| 730 | + collectOperationInputModels(pathItem.getParameters(), operationInputModels, visitedModels); |
| 731 | + for (Operation operation : pathItem.readOperations()) { |
| 732 | + collectOperationInputModels(operation.getParameters(), operationInputModels, visitedModels); |
| 733 | + RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, operation.getRequestBody()); |
| 734 | + if (requestBody != null) { |
| 735 | + collectOperationInputModels(requestBody.getContent(), operationInputModels, visitedModels); |
| 736 | + } |
| 737 | + } |
| 738 | + } |
| 739 | + return operationInputModels; |
| 740 | + } |
| 741 | + |
| 742 | + private void collectOperationInputModels(List<Parameter> parameters, Set<String> operationInputModels, Set<String> visitedModels) { |
| 743 | + if (parameters == null) { |
| 744 | + return; |
| 745 | + } |
| 746 | + for (Parameter unresolvedParameter : parameters) { |
| 747 | + Parameter parameter = ModelUtils.getReferencedParameter(openAPI, unresolvedParameter); |
| 748 | + if (parameter != null) { |
| 749 | + collectOperationInputModels(parameter.getSchema(), operationInputModels, visitedModels); |
| 750 | + collectOperationInputModels(parameter.getContent(), operationInputModels, visitedModels); |
| 751 | + } |
| 752 | + } |
| 753 | + } |
| 754 | + |
| 755 | + private void collectOperationInputModels(Content content, Set<String> operationInputModels, Set<String> visitedModels) { |
| 756 | + if (content == null) { |
| 757 | + return; |
| 758 | + } |
| 759 | + content.values().forEach(mediaType -> collectOperationInputModels(mediaType.getSchema(), operationInputModels, visitedModels)); |
| 760 | + } |
| 761 | + |
| 762 | + private void collectOperationInputModels(Schema schema, Set<String> operationInputModels, Set<String> visitedModels) { |
| 763 | + if (schema == null || Boolean.TRUE.equals(schema.getReadOnly())) { |
| 764 | + return; |
| 765 | + } |
| 766 | + if (schema.get$ref() != null) { |
| 767 | + String modelName = ModelUtils.getSimpleRef(schema.get$ref()); |
| 768 | + operationInputModels.add(modelName); |
| 769 | + if (visitedModels.add(modelName)) { |
| 770 | + collectOperationInputModels(ModelUtils.getSchema(openAPI, modelName), operationInputModels, visitedModels); |
| 771 | + } |
| 772 | + } |
| 773 | + if (schema.getOneOf() != null) { |
| 774 | + schema.getOneOf().forEach(child -> collectOperationInputModels((Schema) child, operationInputModels, visitedModels)); |
| 775 | + } |
| 776 | + if (schema.getAllOf() != null) { |
| 777 | + schema.getAllOf().forEach(child -> collectOperationInputModels((Schema) child, operationInputModels, visitedModels)); |
| 778 | + } |
| 779 | + if (schema.getAnyOf() != null) { |
| 780 | + schema.getAnyOf().forEach(child -> collectOperationInputModels((Schema) child, operationInputModels, visitedModels)); |
| 781 | + } |
| 782 | + // TODO: Traverse OAS 3.1 schema keywords that can reference operation-input models, |
| 783 | + // such as prefixItems, contains, if/then/else, dependentSchemas, and unevaluatedProperties. |
| 784 | + collectOperationInputModels(ModelUtils.getSchemaItems(schema), operationInputModels, visitedModels); // in case schema has array type |
| 785 | + if (schema.getAdditionalProperties() instanceof Schema) { |
| 786 | + collectOperationInputModels((Schema) schema.getAdditionalProperties(), operationInputModels, visitedModels); |
| 787 | + } |
| 788 | + if (schema.getProperties() != null) { |
| 789 | + schema.getProperties().values().forEach(property -> collectOperationInputModels((Schema) property, operationInputModels, visitedModels)); |
| 790 | + } |
| 791 | + } |
| 792 | + |
713 | 793 | /** |
714 | 794 | * Returns true if the model contains any properties with a public setter |
715 | 795 | * If true, the model's constructor accessor should be made public to ensure end users |
|
0 commit comments