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 6bcb112fe93c..41cc9a0497a0 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 @@ -2464,6 +2464,14 @@ public class DefaultCodegen implements CodegenConfig { protected String getSingleSchemaType(Schema schema) { Schema unaliasSchema = unaliasSchema(schema); + if (ModelUtils.isRefToSchemaWithProperties(unaliasSchema.get$ref())) { + // ref to schema's properties, e.g. #/components/schemas/Pet/properties/category + Schema refSchema = ModelUtils.getReferencedSchema(openAPI, unaliasSchema); + if (refSchema != null) { + return getSingleSchemaType(refSchema); + } + } + if (StringUtils.isNotBlank(unaliasSchema.get$ref())) { // reference to another definition/schema // get the schema/model name from $ref String schemaName = ModelUtils.getSimpleRef(unaliasSchema.get$ref()); @@ -3354,7 +3362,7 @@ public class DefaultCodegen implements CodegenConfig { String modelName = ModelUtils.getSimpleRef(((Schema) oneOf).get$ref()); CodegenProperty thisCp = discriminatorFound(composedSchemaName, (Schema) oneOf, discPropName, visitedSchemas); if (thisCp == null) { - LOGGER.warn( + once(LOGGER).warn( "'{}' defines discriminator '{}', but the referenced OneOf schema '{}' is missing {}", composedSchemaName, discPropName, modelName, discPropName); } @@ -3363,7 +3371,7 @@ public class DefaultCodegen implements CodegenConfig { continue; } if (cp != thisCp) { - LOGGER.warn( + once(LOGGER).warn( "'{}' defines discriminator '{}', but the OneOf schema '{}' has a different {} definition than the prior OneOf schema's. Make sure the {} type and required values are the same", composedSchemaName, discPropName, modelName, discPropName, discPropName); } @@ -3377,7 +3385,7 @@ public class DefaultCodegen implements CodegenConfig { String modelName = ModelUtils.getSimpleRef(((Schema) anyOf).get$ref()); CodegenProperty thisCp = discriminatorFound(composedSchemaName, (Schema) anyOf, discPropName, visitedSchemas); if (thisCp == null) { - LOGGER.warn( + once(LOGGER).warn( "'{}' defines discriminator '{}', but the referenced AnyOf schema '{}' is missing {}", composedSchemaName, discPropName, modelName, discPropName); } @@ -3386,7 +3394,7 @@ public class DefaultCodegen implements CodegenConfig { continue; } if (cp != thisCp) { - LOGGER.warn( + once(LOGGER).warn( "'{}' defines discriminator '{}', but the AnyOf schema '{}' has a different {} definition than the prior AnyOf schema's. Make sure the {} type and required values are the same", composedSchemaName, discPropName, modelName, discPropName, discPropName); } @@ -3454,7 +3462,7 @@ public class DefaultCodegen implements CodegenConfig { } } if (discriminatorsPropNames.size() > 1) { - LOGGER.warn("The oneOf schemas have conflicting discriminator property names. " + + once(LOGGER).warn("The oneOf schemas have conflicting discriminator property names. " + "oneOf schemas must have the same property name, but found " + String.join(", ", discriminatorsPropNames)); } if (foundDisc != null && (hasDiscriminatorCnt + hasNullTypeCnt) == composedSchema.getOneOf().size() && discriminatorsPropNames.size() == 1) { @@ -3483,7 +3491,7 @@ public class DefaultCodegen implements CodegenConfig { } } if (discriminatorsPropNames.size() > 1) { - LOGGER.warn("The anyOf schemas have conflicting discriminator property names. " + + once(LOGGER).warn("The anyOf schemas have conflicting discriminator property names. " + "anyOf schemas must have the same property name, but found " + String.join(", ", discriminatorsPropNames)); } if (foundDisc != null && (hasDiscriminatorCnt + hasNullTypeCnt) == composedSchema.getAnyOf().size() && discriminatorsPropNames.size() == 1) { @@ -3532,7 +3540,7 @@ public class DefaultCodegen implements CodegenConfig { // schemas also has inline composed schemas // Note: if it is only inline one level, then the inline model resolver will move it into its own // schema and make it a $ref schema in the oneOf/anyOf location - LOGGER.warn( + once(LOGGER).warn( "Invalid inline schema defined in oneOf/anyOf in '{}'. Per the OpenApi spec, for this case when a composed schema defines a discriminator, the oneOf/anyOf schemas must use $ref. Change this inline definition to a $ref definition", composedSchemaName); } @@ -3554,14 +3562,14 @@ public class DefaultCodegen implements CodegenConfig { msgSuffix += spacer + "invalid optional definition of " + discPropName + ", include it in required"; } } - LOGGER.warn("'{}' defines discriminator '{}', but the referenced schema '{}' is incorrect. {}", + once(LOGGER).warn("'{}' defines discriminator '{}', but the referenced schema '{}' is incorrect. {}", composedSchemaName, discPropName, modelName, msgSuffix); } MappedModel mm = new MappedModel(modelName, toModelName(modelName)); descendentSchemas.add(mm); Schema cs = ModelUtils.getSchema(openAPI, modelName); if (cs == null) { // cannot lookup the model based on the name - LOGGER.error("Failed to lookup the schema '{}' when processing oneOf/anyOf. Please check to ensure it's defined properly.", modelName); + once(LOGGER).error("Failed to lookup the schema '{}' when processing oneOf/anyOf. Please check to ensure it's defined properly.", modelName); } else { Map vendorExtensions = cs.getExtensions(); if (vendorExtensions != null && !vendorExtensions.isEmpty() && vendorExtensions.containsKey("x-discriminator-value")) { @@ -3674,7 +3682,7 @@ public class DefaultCodegen implements CodegenConfig { if (e.getValue().indexOf('/') >= 0) { name = ModelUtils.getSimpleRef(e.getValue()); if (ModelUtils.getSchema(openAPI, name) == null) { - LOGGER.error("Failed to lookup the schema '{}' when processing the discriminator mapping of oneOf/anyOf. Please check to ensure it's defined properly.", name); + once(LOGGER).error("Failed to lookup the schema '{}' when processing the discriminator mapping of oneOf/anyOf. Please check to ensure it's defined properly.", name); } } else { name = e.getValue(); @@ -3983,6 +3991,13 @@ public class DefaultCodegen implements CodegenConfig { return cpc; } + // if it's ref to schema's properties, get the actual schema defined in the properties + Schema refToPropertiesSchema = ModelUtils.getSchemaFromRefToSchemaWithProperties(openAPI, p.get$ref()); + if (refToPropertiesSchema != null) { + p = refToPropertiesSchema; + return fromProperty(name, refToPropertiesSchema, required, schemaIsFromAdditionalProperties); + } + Schema original = null; // 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) { 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 207f34e89f65..99f2d70ee6f7 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 @@ -929,16 +929,76 @@ public class ModelUtils { * @return schema without '$ref' */ public static Schema getReferencedSchema(OpenAPI openAPI, Schema schema) { - if (schema != null && StringUtils.isNotEmpty(schema.get$ref())) { - String name = getSimpleRef(schema.get$ref()); - Schema referencedSchema = getSchema(openAPI, name); - if (referencedSchema != null) { - return referencedSchema; - } + if (schema == null) { + return null; } + + if (StringUtils.isEmpty(schema.get$ref())) { + return schema; + } + + try { + Schema refSchema = getSchemaFromRefToSchemaWithProperties(openAPI, schema.get$ref()); + if (refSchema != null) { + // it's ref to schema's properties, #/components/schemas/Pet/properties/category for example + return refSchema; + } + } catch (Exception e) { + LOGGER.warn("Failed to parse $ref {}. Please report the issue to openapi-generator GitHub repo.", schema.get$ref()); + } + + // a simple ref, e.g. #/components/schemas/Pet + String name = getSimpleRef(schema.get$ref()); + Schema referencedSchema = getSchema(openAPI, name); + if (referencedSchema != null) { + return referencedSchema; + } + return schema; } + /** + * Get the schema referenced by $ref to schema's properties, e.g. #/components/schemas/Pet/properties/category. + * + * @param openAPI specification being checked + * @param refString schema reference + * @return schema + */ + public static Schema getSchemaFromRefToSchemaWithProperties(OpenAPI openAPI, String refString) { + if (refString == null) { + return null; + } + + String[] parts = refString.split("/"); + // #/components/schemas/Pet/properties/category + if (parts.length == 6 && "properties".equals(parts[4])) { + Schema referencedSchema = getSchema(openAPI, parts[3]); // parts[3] is Pet + return (Schema) referencedSchema.getProperties().get(parts[5]); // parts[5] is category + } else { + return null; + } + } + + /** + * Returns true if $ref to a reference to schema's properties, e.g. #/components/schemas/Pet/properties/category. + * + * @param refString schema reference + * @return true if $ref to a reference to schema's properties + */ + public static boolean isRefToSchemaWithProperties(String refString) { + if (refString == null) { + return false; + } + + String[] parts = refString.split("/"); + // #/components/schemas/Pet/properties/category + if (parts.length == 6 && "properties".equals(parts[4])) { + return true; + } else { + return false; + } + } + public static Schema getSchema(OpenAPI openAPI, String name) { if (name == null) { return null; @@ -1272,7 +1332,9 @@ public class ModelUtils { } Schema ref = allSchemas.get(simpleRef); if (ref == null) { - once(LOGGER).warn("{} is not defined", schema.get$ref()); + if (!isRefToSchemaWithProperties(schema.get$ref())) { + once(LOGGER).warn("{} is not defined", schema.get$ref()); + } return schema; } else if (ref.getEnum() != null && !ref.getEnum().isEmpty()) { // top-level enum class diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java index ac6cc875d939..76bd51b43a5f 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java @@ -295,6 +295,25 @@ public class ModelUtilsTest { Assert.assertEquals(decoded, "~1 Hallo/Welt"); } + @Test + public void testRefToSchemaProperties() { + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/petstore.yaml"); + + Schema category = ModelUtils.getSchemaFromRefToSchemaWithProperties(openAPI, "#/components/schemas/Pet/properties/category"); + Assert.assertEquals(category.get$ref(), "#/components/schemas/Category"); + + Schema name = ModelUtils.getSchemaFromRefToSchemaWithProperties(openAPI, "#/components/schemas/Pet/properties/name"); + Assert.assertEquals(name.getType(), "string"); + + Schema id = ModelUtils.getSchemaFromRefToSchemaWithProperties(openAPI, "#/components/schemas/Pet/properties/id"); + Assert.assertEquals(id.getType(), "integer"); + Assert.assertEquals(id.getFormat(), "int64"); + + Assert.assertEquals(null, ModelUtils.getSchemaFromRefToSchemaWithProperties(openAPI, "#/components/schemas/Pet/prop/category")); + Assert.assertEquals(null, ModelUtils.getSchemaFromRefToSchemaWithProperties(openAPI, "#/components/schemas/Pet/properties/categoryyyy")); + Assert.assertEquals(null, ModelUtils.getSchemaFromRefToSchemaWithProperties(openAPI, "#/components/schemas/Pet")); + } + // 3.0 spec tests @Test 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 44bc0a2788bb..9e353005e13c 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 @@ -2655,3 +2655,23 @@ components: PetComposition: allOf: - $ref: '#/components/schemas/Pet' + PetRef: + type: object + required: + - name + - photoUrls + properties: + id: + $ref: '#/components/schemas/Pet/properties/id' + category: + $ref: '#/components/schemas/Pet/properties/category' + name: + $ref: '#/components/schemas/Pet/properties/name' + photoUrls: + $ref: '#/components/schemas/Pet/properties/photoUrls' + tags: + $ref: '#/components/schemas/Pet/properties/tags' + status: + $ref: '#/components/schemas/Pet/properties/status' + xml: + name: Pet diff --git a/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES b/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES index bebe3898e9e8..0eaba6aa6170 100644 --- a/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES +++ b/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES @@ -79,6 +79,7 @@ docs/ParentPet.md docs/Pet.md docs/PetApi.md docs/PetComposition.md +docs/PetRef.md docs/PetUsingAllOf.md docs/PetWithRequiredTags.md docs/Pig.md @@ -213,6 +214,7 @@ src/main/java/org/openapitools/client/model/OuterEnumIntegerDefaultValue.java src/main/java/org/openapitools/client/model/ParentPet.java src/main/java/org/openapitools/client/model/Pet.java src/main/java/org/openapitools/client/model/PetComposition.java +src/main/java/org/openapitools/client/model/PetRef.java src/main/java/org/openapitools/client/model/PetUsingAllOf.java src/main/java/org/openapitools/client/model/PetWithRequiredTags.java src/main/java/org/openapitools/client/model/Pig.java diff --git a/samples/client/petstore/java/okhttp-gson/README.md b/samples/client/petstore/java/okhttp-gson/README.md index c88dcf33692d..63c167c60e86 100644 --- a/samples/client/petstore/java/okhttp-gson/README.md +++ b/samples/client/petstore/java/okhttp-gson/README.md @@ -235,6 +235,7 @@ Class | Method | HTTP request | Description - [ParentPet](docs/ParentPet.md) - [Pet](docs/Pet.md) - [PetComposition](docs/PetComposition.md) + - [PetRef](docs/PetRef.md) - [PetUsingAllOf](docs/PetUsingAllOf.md) - [PetWithRequiredTags](docs/PetWithRequiredTags.md) - [Pig](docs/Pig.md) diff --git a/samples/client/petstore/java/okhttp-gson/api/openapi.yaml b/samples/client/petstore/java/okhttp-gson/api/openapi.yaml index 0d7cf7f37284..7a956b341e42 100644 --- a/samples/client/petstore/java/okhttp-gson/api/openapi.yaml +++ b/samples/client/petstore/java/okhttp-gson/api/openapi.yaml @@ -2691,6 +2691,26 @@ components: PetComposition: allOf: - $ref: '#/components/schemas/Pet' + PetRef: + properties: + id: + $ref: '#/components/schemas/Pet/properties/id' + category: + $ref: '#/components/schemas/Pet/properties/category' + name: + $ref: '#/components/schemas/Pet/properties/name' + photoUrls: + $ref: '#/components/schemas/Pet/properties/photoUrls' + tags: + $ref: '#/components/schemas/Pet/properties/tags' + status: + $ref: '#/components/schemas/Pet/properties/status' + required: + - name + - photoUrls + type: object + xml: + name: Pet _foo_get_default_response: example: string: diff --git a/samples/client/petstore/java/okhttp-gson/docs/PetRef.md b/samples/client/petstore/java/okhttp-gson/docs/PetRef.md new file mode 100644 index 000000000000..256faf704c49 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/docs/PetRef.md @@ -0,0 +1,28 @@ + + +# PetRef + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**id** | **Long** | | [optional] | +|**category** | [**Category**](Category.md) | | [optional] | +|**name** | **String** | | | +|**photoUrls** | **List<String>** | | | +|**tags** | [**List<Tag>**](Tag.md) | | [optional] | +|**status** | [**StatusEnum**](#StatusEnum) | pet status in the store | [optional] | + + + +## Enum: StatusEnum + +| Name | Value | +|---- | -----| +| AVAILABLE | "available" | +| PENDING | "pending" | +| SOLD | "sold" | + + + diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/JSON.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/JSON.java index 9a6e991cb5a6..767d24dc3168 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/JSON.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/JSON.java @@ -298,6 +298,7 @@ public class JSON { gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.ParentPet.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.Pet.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.PetComposition.CustomTypeAdapterFactory()); + gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.PetRef.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.PetUsingAllOf.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.PetWithRequiredTags.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.Pig.CustomTypeAdapterFactory()); diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/PetRef.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/PetRef.java new file mode 100644 index 000000000000..040f77c705de --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/PetRef.java @@ -0,0 +1,531 @@ +/* + * OpenAPI Petstore + * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.openapitools.client.model; + +import java.util.Objects; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.openapitools.client.model.Category; +import org.openapitools.client.model.Tag; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.openapitools.client.JSON; + +/** + * PetRef + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.5.0-SNAPSHOT") +public class PetRef { + public static final String SERIALIZED_NAME_ID = "id"; + @SerializedName(SERIALIZED_NAME_ID) + private Long id; + + public static final String SERIALIZED_NAME_CATEGORY = "category"; + @SerializedName(SERIALIZED_NAME_CATEGORY) + private Category category; + + public static final String SERIALIZED_NAME_NAME = "name"; + @SerializedName(SERIALIZED_NAME_NAME) + private String name; + + public static final String SERIALIZED_NAME_PHOTO_URLS = "photoUrls"; + @SerializedName(SERIALIZED_NAME_PHOTO_URLS) + private List photoUrls = new ArrayList<>(); + + public static final String SERIALIZED_NAME_TAGS = "tags"; + @SerializedName(SERIALIZED_NAME_TAGS) + private List tags = new ArrayList<>(); + + /** + * pet status in the store + */ + @JsonAdapter(StatusEnum.Adapter.class) + public enum StatusEnum { + AVAILABLE("available"), + + PENDING("pending"), + + SOLD("sold"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + public static StatusEnum fromValue(String value) { + for (StatusEnum b : StatusEnum.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + + public static class Adapter extends TypeAdapter { + @Override + public void write(final JsonWriter jsonWriter, final StatusEnum enumeration) throws IOException { + jsonWriter.value(enumeration.getValue()); + } + + @Override + public StatusEnum read(final JsonReader jsonReader) throws IOException { + String value = jsonReader.nextString(); + return StatusEnum.fromValue(value); + } + } + + public static void validateJsonElement(JsonElement jsonElement) throws IOException { + String value = jsonElement.getAsString(); + StatusEnum.fromValue(value); + } + } + + public static final String SERIALIZED_NAME_STATUS = "status"; + @SerializedName(SERIALIZED_NAME_STATUS) + private StatusEnum status; + + public PetRef() { + } + + public PetRef id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @javax.annotation.Nullable + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + + public PetRef category(Category category) { + this.category = category; + return this; + } + + /** + * Get category + * @return category + **/ + @javax.annotation.Nullable + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } + + + public PetRef name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @javax.annotation.Nonnull + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + public PetRef photoUrls(List photoUrls) { + this.photoUrls = photoUrls; + return this; + } + + public PetRef addPhotoUrlsItem(String photoUrlsItem) { + if (this.photoUrls == null) { + this.photoUrls = new ArrayList<>(); + } + this.photoUrls.add(photoUrlsItem); + return this; + } + + /** + * Get photoUrls + * @return photoUrls + **/ + @javax.annotation.Nonnull + public List getPhotoUrls() { + return photoUrls; + } + + public void setPhotoUrls(List photoUrls) { + this.photoUrls = photoUrls; + } + + + public PetRef tags(List tags) { + this.tags = tags; + return this; + } + + public PetRef addTagsItem(Tag tagsItem) { + if (this.tags == null) { + this.tags = new ArrayList<>(); + } + this.tags.add(tagsItem); + return this; + } + + /** + * Get tags + * @return tags + **/ + @javax.annotation.Nullable + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + + public PetRef status(StatusEnum status) { + this.status = status; + return this; + } + + /** + * pet status in the store + * @return status + **/ + @javax.annotation.Nullable + public StatusEnum getStatus() { + return status; + } + + public void setStatus(StatusEnum status) { + this.status = status; + } + + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + private Map additionalProperties; + + /** + * Set the additional (undeclared) property with the specified name and value. + * If the property does not already exist, create it otherwise replace it. + * + * @param key name of the property + * @param value value of the property + * @return the PetRef instance itself + */ + public PetRef putAdditionalProperty(String key, Object value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) property. + * + * @return a map of objects + */ + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + * + * @param key name of the property + * @return an object + */ + public Object getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PetRef petRef = (PetRef) o; + return Objects.equals(this.id, petRef.id) && + Objects.equals(this.category, petRef.category) && + Objects.equals(this.name, petRef.name) && + Objects.equals(this.photoUrls, petRef.photoUrls) && + Objects.equals(this.tags, petRef.tags) && + Objects.equals(this.status, petRef.status)&& + Objects.equals(this.additionalProperties, petRef.additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(id, category, name, photoUrls, tags, status, additionalProperties); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class PetRef {\n"); + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" category: ").append(toIndentedString(category)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" photoUrls: ").append(toIndentedString(photoUrls)).append("\n"); + sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + + public static HashSet openapiFields; + public static HashSet openapiRequiredFields; + + static { + // a set of all properties/fields (JSON key names) + openapiFields = new HashSet(); + openapiFields.add("id"); + openapiFields.add("category"); + openapiFields.add("name"); + openapiFields.add("photoUrls"); + openapiFields.add("tags"); + openapiFields.add("status"); + + // a set of required properties/fields (JSON key names) + openapiRequiredFields = new HashSet(); + openapiRequiredFields.add("name"); + openapiRequiredFields.add("photoUrls"); + } + + /** + * Validates the JSON Element and throws an exception if issues found + * + * @param jsonElement JSON Element + * @throws IOException if the JSON Element is invalid with respect to PetRef + */ + public static void validateJsonElement(JsonElement jsonElement) throws IOException { + if (jsonElement == null) { + if (!PetRef.openapiRequiredFields.isEmpty()) { // has required fields but JSON element is null + throw new IllegalArgumentException(String.format("The required field(s) %s in PetRef is not found in the empty JSON string", PetRef.openapiRequiredFields.toString())); + } + } + + // check to make sure all required properties/fields are present in the JSON string + for (String requiredField : PetRef.openapiRequiredFields) { + if (jsonElement.getAsJsonObject().get(requiredField) == null) { + throw new IllegalArgumentException(String.format("The required field `%s` is not found in the JSON string: %s", requiredField, jsonElement.toString())); + } + } + JsonObject jsonObj = jsonElement.getAsJsonObject(); + // validate the optional field `category` + if (jsonObj.get("category") != null && !jsonObj.get("category").isJsonNull()) { + Category.validateJsonElement(jsonObj.get("category")); + } + if (!jsonObj.get("name").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format("Expected the field `name` to be a primitive type in the JSON string but got `%s`", jsonObj.get("name").toString())); + } + // ensure the required json array is present + if (jsonObj.get("photoUrls") == null) { + throw new IllegalArgumentException("Expected the field `linkedContent` to be an array in the JSON string but got `null`"); + } else if (!jsonObj.get("photoUrls").isJsonArray()) { + throw new IllegalArgumentException(String.format("Expected the field `photoUrls` to be an array in the JSON string but got `%s`", jsonObj.get("photoUrls").toString())); + } + if (jsonObj.get("tags") != null && !jsonObj.get("tags").isJsonNull()) { + JsonArray jsonArraytags = jsonObj.getAsJsonArray("tags"); + if (jsonArraytags != null) { + // ensure the json data is an array + if (!jsonObj.get("tags").isJsonArray()) { + throw new IllegalArgumentException(String.format("Expected the field `tags` to be an array in the JSON string but got `%s`", jsonObj.get("tags").toString())); + } + + // validate the optional field `tags` (array) + for (int i = 0; i < jsonArraytags.size(); i++) { + Tag.validateJsonElement(jsonArraytags.get(i)); + }; + } + } + if ((jsonObj.get("status") != null && !jsonObj.get("status").isJsonNull()) && !jsonObj.get("status").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format("Expected the field `status` to be a primitive type in the JSON string but got `%s`", jsonObj.get("status").toString())); + } + // validate the optional field `status` + if (jsonObj.get("status") != null && !jsonObj.get("status").isJsonNull()) { + StatusEnum.validateJsonElement(jsonObj.get("status")); + } + } + + public static class CustomTypeAdapterFactory implements TypeAdapterFactory { + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (!PetRef.class.isAssignableFrom(type.getRawType())) { + return null; // this class only serializes 'PetRef' and its subtypes + } + final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); + final TypeAdapter thisAdapter + = gson.getDelegateAdapter(this, TypeToken.get(PetRef.class)); + + return (TypeAdapter) new TypeAdapter() { + @Override + public void write(JsonWriter out, PetRef value) throws IOException { + JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject(); + obj.remove("additionalProperties"); + // serialize additional properties + if (value.getAdditionalProperties() != null) { + for (Map.Entry entry : value.getAdditionalProperties().entrySet()) { + if (entry.getValue() instanceof String) + obj.addProperty(entry.getKey(), (String) entry.getValue()); + else if (entry.getValue() instanceof Number) + obj.addProperty(entry.getKey(), (Number) entry.getValue()); + else if (entry.getValue() instanceof Boolean) + obj.addProperty(entry.getKey(), (Boolean) entry.getValue()); + else if (entry.getValue() instanceof Character) + obj.addProperty(entry.getKey(), (Character) entry.getValue()); + else { + JsonElement jsonElement = gson.toJsonTree(entry.getValue()); + if (jsonElement.isJsonArray()) { + obj.add(entry.getKey(), jsonElement.getAsJsonArray()); + } else { + obj.add(entry.getKey(), jsonElement.getAsJsonObject()); + } + } + } + } + elementAdapter.write(out, obj); + } + + @Override + public PetRef read(JsonReader in) throws IOException { + JsonElement jsonElement = elementAdapter.read(in); + validateJsonElement(jsonElement); + JsonObject jsonObj = jsonElement.getAsJsonObject(); + // store additional fields in the deserialized instance + PetRef instance = thisAdapter.fromJsonTree(jsonObj); + for (Map.Entry entry : jsonObj.entrySet()) { + if (!openapiFields.contains(entry.getKey())) { + if (entry.getValue().isJsonPrimitive()) { // primitive type + if (entry.getValue().getAsJsonPrimitive().isString()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsString()); + else if (entry.getValue().getAsJsonPrimitive().isNumber()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsNumber()); + else if (entry.getValue().getAsJsonPrimitive().isBoolean()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsBoolean()); + else + throw new IllegalArgumentException(String.format("The field `%s` has unknown primitive type. Value: %s", entry.getKey(), entry.getValue().toString())); + } else if (entry.getValue().isJsonArray()) { + instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), List.class)); + } else { // JSON object + instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), HashMap.class)); + } + } + } + return instance; + } + + }.nullSafe(); + } + } + + /** + * Create an instance of PetRef given an JSON string + * + * @param jsonString JSON string + * @return An instance of PetRef + * @throws IOException if the JSON string is invalid with respect to PetRef + */ + public static PetRef fromJson(String jsonString) throws IOException { + return JSON.getGson().fromJson(jsonString, PetRef.class); + } + + /** + * Convert an instance of PetRef to an JSON string + * + * @return JSON string + */ + public String toJson() { + return JSON.getGson().toJson(this); + } +} + diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/model/PetRefTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/model/PetRefTest.java new file mode 100644 index 000000000000..cbad73a0cdec --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/model/PetRefTest.java @@ -0,0 +1,48 @@ +/* + * OpenAPI Petstore + * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.openapitools.client.model; + +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.Arrays; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +/** + * Model tests for PetRef + */ +public class PetRefTest { + private final PetRef model = new PetRef(); + + /** + * Model tests for PetRef + */ + @Test + public void testPetRef() { + // TODO: test PetRef + } + + /** + * Test the property 'status' + */ + @Test + public void statusTest() { + // TODO: test status + } + +}