From 48e8375166d3ef4475450c97a61d0845c7d3ee00 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 29 Oct 2024 10:24:59 +0800 Subject: [PATCH] fix ref to allOf wrapper, add tests (#19986) --- .../openapitools/codegen/DefaultCodegen.java | 23 ++++++- .../codegen/utils/ModelUtils.java | 12 ++++ ...points-models-for-testing-okhttp-gson.yaml | 10 +++ .../java/okhttp-gson/api/openapi.yaml | 10 +++ .../petstore/java/okhttp-gson/docs/NewPet.md | 2 + .../org/openapitools/client/model/NewPet.java | 62 ++++++++++++++++++- 6 files changed, 117 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 527b9bca0561..d4e30f305595 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -3861,8 +3861,29 @@ public CodegenProperty fromProperty(String name, Schema p, boolean required, boo } Schema original = null; + // process the dereference schema if it's a ref to allOf with a single item + // and certain field(s) (e.g. description, readyOnly, etc) is set + if (p.get$ref() != null) { + Schema derefSchema = ModelUtils.getReferencedSchema(openAPI, p); + if (ModelUtils.isAllOfWithSingleItem(derefSchema) && ( + derefSchema.getReadOnly() != null || + derefSchema.getWriteOnly() != null || + derefSchema.getDeprecated() != null || + derefSchema.getDescription() != null || + derefSchema.getMaxLength() != null || + derefSchema.getMinLength() != null || + derefSchema.getMinimum() != null || + derefSchema.getMaximum() != null || + derefSchema.getMaximum() != null || + derefSchema.getMinItems() != null || + derefSchema.getTitle() != null + )) { + p = ModelUtils.getReferencedSchema(openAPI, p); + } + } + // check if it's allOf (only 1 sub schema) with or without default/nullable/etc set in the top level - if (ModelUtils.isAllOf(p) && p.getAllOf().size() == 1) { + if (ModelUtils.isAllOfWithSingleItem(p)) { if (p.getAllOf().get(0) instanceof Schema) { original = p; p = (Schema) p.getAllOf().get(0); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java index c46de7746322..c0a6b6acf787 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java @@ -2031,6 +2031,18 @@ public static boolean isAllOf(Schema schema) { return false; } + + /** + * Returns true if the schema contains allOf with a single item but + * no properties/oneOf/anyOf defined + * + * @param schema the schema + * @return true if the schema contains allOf but no properties/oneOf/anyOf defined. + */ + public static boolean isAllOfWithSingleItem(Schema schema) { + return (isAllOf(schema) && schema.getAllOf().size() == 1); + } + /** * Returns true if the schema contains allOf and may or may not have * properties/oneOf/anyOf defined. diff --git a/modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml b/modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml index 1f8285397936..f0354608d319 100644 --- a/modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml @@ -2610,6 +2610,10 @@ components: minItems: 1 items: $ref: '#/components/schemas/Scalar' + AllOfRefToString: + allOf: + - $ref: '#/components/schemas/OuterString' + description: testing allOf with a ref to string NewPet: type: object required: @@ -2620,6 +2624,12 @@ components: type: integer format: int64 x-is-unique: true + category_ref_to_inline_allof_string: + $ref: '#/components/schemas/AllOfRefToString' + category_inline_allof_string: + allOf: + - $ref: '#/components/schemas/OuterString' + description: testing allOf with a ref to string category_inline_allof: allOf: - type: object diff --git a/samples/client/petstore/java/okhttp-gson/api/openapi.yaml b/samples/client/petstore/java/okhttp-gson/api/openapi.yaml index bf5b3d880975..edfc304ae253 100644 --- a/samples/client/petstore/java/okhttp-gson/api/openapi.yaml +++ b/samples/client/petstore/java/okhttp-gson/api/openapi.yaml @@ -2689,12 +2689,22 @@ components: $ref: '#/components/schemas/Scalar' minItems: 1 type: array + AllOfRefToString: + allOf: + - $ref: '#/components/schemas/OuterString' + description: testing allOf with a ref to string NewPet: properties: id: format: int64 type: integer x-is-unique: true + category_ref_to_inline_allof_string: + $ref: '#/components/schemas/AllOfRefToString' + category_inline_allof_string: + allOf: + - $ref: '#/components/schemas/OuterString' + description: testing allOf with a ref to string category_inline_allof: $ref: '#/components/schemas/NewPet_category_inline_allof' category_allOf_ref: diff --git a/samples/client/petstore/java/okhttp-gson/docs/NewPet.md b/samples/client/petstore/java/okhttp-gson/docs/NewPet.md index 3cfa8c0076fe..5fe53d159080 100644 --- a/samples/client/petstore/java/okhttp-gson/docs/NewPet.md +++ b/samples/client/petstore/java/okhttp-gson/docs/NewPet.md @@ -8,6 +8,8 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| |**id** | **Long** | | [optional] | +|**categoryRefToInlineAllofString** | **String** | testing allOf with a ref to string | [optional] | +|**categoryInlineAllofString** | **String** | testing allOf with a ref to string | [optional] | |**categoryInlineAllof** | [**NewPetCategoryInlineAllof**](NewPetCategoryInlineAllof.md) | | [optional] | |**categoryAllOfRef** | [**Category**](Category.md) | | [optional] | |**categoryAllOfRefDescription** | [**Category**](Category.md) | Adding description to property using allOf | [optional] | diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/NewPet.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/NewPet.java index 7a9b9f0c0774..65a5fae37331 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/NewPet.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/NewPet.java @@ -60,6 +60,16 @@ public class NewPet { @javax.annotation.Nullable private Long id; + public static final String SERIALIZED_NAME_CATEGORY_REF_TO_INLINE_ALLOF_STRING = "category_ref_to_inline_allof_string"; + @SerializedName(SERIALIZED_NAME_CATEGORY_REF_TO_INLINE_ALLOF_STRING) + @javax.annotation.Nullable + private String categoryRefToInlineAllofString; + + public static final String SERIALIZED_NAME_CATEGORY_INLINE_ALLOF_STRING = "category_inline_allof_string"; + @SerializedName(SERIALIZED_NAME_CATEGORY_INLINE_ALLOF_STRING) + @javax.annotation.Nullable + private String categoryInlineAllofString; + public static final String SERIALIZED_NAME_CATEGORY_INLINE_ALLOF = "category_inline_allof"; @SerializedName(SERIALIZED_NAME_CATEGORY_INLINE_ALLOF) @javax.annotation.Nullable @@ -183,6 +193,44 @@ public void setId(@javax.annotation.Nullable Long id) { } + public NewPet categoryRefToInlineAllofString(@javax.annotation.Nullable String categoryRefToInlineAllofString) { + this.categoryRefToInlineAllofString = categoryRefToInlineAllofString; + return this; + } + + /** + * testing allOf with a ref to string + * @return categoryRefToInlineAllofString + */ + @javax.annotation.Nullable + public String getCategoryRefToInlineAllofString() { + return categoryRefToInlineAllofString; + } + + public void setCategoryRefToInlineAllofString(@javax.annotation.Nullable String categoryRefToInlineAllofString) { + this.categoryRefToInlineAllofString = categoryRefToInlineAllofString; + } + + + public NewPet categoryInlineAllofString(@javax.annotation.Nullable String categoryInlineAllofString) { + this.categoryInlineAllofString = categoryInlineAllofString; + return this; + } + + /** + * testing allOf with a ref to string + * @return categoryInlineAllofString + */ + @javax.annotation.Nullable + public String getCategoryInlineAllofString() { + return categoryInlineAllofString; + } + + public void setCategoryInlineAllofString(@javax.annotation.Nullable String categoryInlineAllofString) { + this.categoryInlineAllofString = categoryInlineAllofString; + } + + public NewPet categoryInlineAllof(@javax.annotation.Nullable NewPetCategoryInlineAllof categoryInlineAllof) { this.categoryInlineAllof = categoryInlineAllof; return this; @@ -398,6 +446,8 @@ public boolean equals(Object o) { } NewPet newPet = (NewPet) o; return Objects.equals(this.id, newPet.id) && + Objects.equals(this.categoryRefToInlineAllofString, newPet.categoryRefToInlineAllofString) && + Objects.equals(this.categoryInlineAllofString, newPet.categoryInlineAllofString) && Objects.equals(this.categoryInlineAllof, newPet.categoryInlineAllof) && Objects.equals(this.categoryAllOfRef, newPet.categoryAllOfRef) && Objects.equals(this.categoryAllOfRefDescription, newPet.categoryAllOfRefDescription) && @@ -411,7 +461,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(id, categoryInlineAllof, categoryAllOfRef, categoryAllOfRefDescription, categoryAllOfRefDescriptionReadonly, name, photoUrls, tags, status, additionalProperties); + return Objects.hash(id, categoryRefToInlineAllofString, categoryInlineAllofString, categoryInlineAllof, categoryAllOfRef, categoryAllOfRefDescription, categoryAllOfRefDescriptionReadonly, name, photoUrls, tags, status, additionalProperties); } @Override @@ -419,6 +469,8 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class NewPet {\n"); sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" categoryRefToInlineAllofString: ").append(toIndentedString(categoryRefToInlineAllofString)).append("\n"); + sb.append(" categoryInlineAllofString: ").append(toIndentedString(categoryInlineAllofString)).append("\n"); sb.append(" categoryInlineAllof: ").append(toIndentedString(categoryInlineAllof)).append("\n"); sb.append(" categoryAllOfRef: ").append(toIndentedString(categoryAllOfRef)).append("\n"); sb.append(" categoryAllOfRefDescription: ").append(toIndentedString(categoryAllOfRefDescription)).append("\n"); @@ -451,6 +503,8 @@ private String toIndentedString(Object o) { // a set of all properties/fields (JSON key names) openapiFields = new HashSet(); openapiFields.add("id"); + openapiFields.add("category_ref_to_inline_allof_string"); + openapiFields.add("category_inline_allof_string"); openapiFields.add("category_inline_allof"); openapiFields.add("category_allOf_ref"); openapiFields.add("category_allOf_ref_description"); @@ -486,6 +540,12 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti } } JsonObject jsonObj = jsonElement.getAsJsonObject(); + if ((jsonObj.get("category_ref_to_inline_allof_string") != null && !jsonObj.get("category_ref_to_inline_allof_string").isJsonNull()) && !jsonObj.get("category_ref_to_inline_allof_string").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format("Expected the field `category_ref_to_inline_allof_string` to be a primitive type in the JSON string but got `%s`", jsonObj.get("category_ref_to_inline_allof_string").toString())); + } + if ((jsonObj.get("category_inline_allof_string") != null && !jsonObj.get("category_inline_allof_string").isJsonNull()) && !jsonObj.get("category_inline_allof_string").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format("Expected the field `category_inline_allof_string` to be a primitive type in the JSON string but got `%s`", jsonObj.get("category_inline_allof_string").toString())); + } // validate the optional field `category_inline_allof` if (jsonObj.get("category_inline_allof") != null && !jsonObj.get("category_inline_allof").isJsonNull()) { NewPetCategoryInlineAllof.validateJsonElement(jsonObj.get("category_inline_allof"));