From 773177cc57c51f6b6a2d681cfd054793e4fde8c0 Mon Sep 17 00:00:00 2001 From: Richard Alm Date: Wed, 18 Dec 2024 17:50:07 +0100 Subject: [PATCH 1/8] Added so equals and hashcode is generated in models. --- .../generator/deployment/CodegenConfig.java | 3 +- .../deployment/CommonItemConfig.java | 7 + .../codegen/OpenApiGeneratorCodeGenBase.java | 3 + .../OpenApiClientGeneratorWrapper.java | 6 + .../libraries/microprofile/pojo.qute | 43 ++++++ .../integration-tests/equals-hashcode/pom.xml | 93 +++++++++++++ .../quarkus-equals-hashcode-openapi.yaml | 125 ++++++++++++++++++ .../quarkus-non-equals-hashcode-openapi.yaml | 125 ++++++++++++++++++ .../src/main/resources/application.properties | 6 + .../generator/it/EqualsHashcodeTest.java | 52 ++++++++ .../generator/it/VerifyGenerationTest.java | 47 +++++++ client/integration-tests/pom.xml | 1 + docs/modules/ROOT/pages/client.adoc | 5 + .../ROOT/pages/includes/equals-hashcode.adoc | 9 ++ 14 files changed, 524 insertions(+), 1 deletion(-) create mode 100644 client/integration-tests/equals-hashcode/pom.xml create mode 100644 client/integration-tests/equals-hashcode/src/main/openapi/quarkus-equals-hashcode-openapi.yaml create mode 100644 client/integration-tests/equals-hashcode/src/main/openapi/quarkus-non-equals-hashcode-openapi.yaml create mode 100644 client/integration-tests/equals-hashcode/src/main/resources/application.properties create mode 100644 client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/EqualsHashcodeTest.java create mode 100644 client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java create mode 100644 docs/modules/ROOT/pages/includes/equals-hashcode.adoc diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java index aa707bc7e..02192c6a6 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java @@ -74,7 +74,8 @@ public enum ConfigName { GENERATE_APIS("generate-apis"), GENERATE_MODELS("generate-models"), BEAN_VALIDATION("use-bean-validation"), - SERIALIZABLE_MODEL("serializable-model"); + SERIALIZABLE_MODEL("serializable-model"), + EQUALS_HASHCODE("equals-hashcode"); private final String name; diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java index 926ea95ef..6d65cf4b8 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java @@ -172,4 +172,11 @@ public class CommonItemConfig { */ @ConfigItem(name = "generate-models") public Optional generateModels; + + /** + * Enable the generation of equals and hashcode in models. If you set this to {@code false}, the models + * will not have equals and hashcode. + */ + @ConfigItem(name = "equals-hashcode") + public Optional equalsHashcode; } diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java index c4f69013b..619611011 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java @@ -320,6 +320,9 @@ protected void generate(OpenApiGeneratorOptions options) { getValues(smallRyeConfig, openApiFilePath, CodegenConfig.ConfigName.SERIALIZABLE_MODEL, Boolean.class) .ifPresent(generator::withSerialiableModel); + getValues(smallRyeConfig, openApiFilePath, CodegenConfig.ConfigName.EQUALS_HASHCODE, Boolean.class) + .ifPresent(generator::withEqualsHashcode); + getValues(smallRyeConfig, openApiFilePath, CodegenConfig.ConfigName.NORMALIZER, String.class, String.class) .ifPresent(generator::withOpenApiNormalizer); diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java index 12147ece2..4f06bc514 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java @@ -112,6 +112,7 @@ private void setDefaults() { this.configurator.addAdditionalProperty("use-field-name-in-part-filename", FALSE); this.configurator.addAdditionalProperty("verbose", FALSE); this.configurator.addAdditionalProperty(CodegenConstants.SERIALIZABLE_MODEL, FALSE); + this.configurator.addAdditionalProperty("equals-hashcode", TRUE); } /** @@ -202,6 +203,11 @@ public OpenApiClientGeneratorWrapper withSerialiableModel(final Boolean serialia return this; } + public OpenApiClientGeneratorWrapper withEqualsHashcode(final Boolean equalsHashcode) { + this.configurator.addAdditionalProperty("equals-hashcode", equalsHashcode); + return this; + } + /** * Sets the global 'additionalModelTypeAnnotations' setting. If not set this setting will default to empty. * diff --git a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute index ae5542c1e..a15175f4c 100644 --- a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute +++ b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute @@ -1,5 +1,6 @@ {@org.openapitools.codegen.CodegenModel m} import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; {#if m.description} /** @@ -134,6 +135,48 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if serializabl sb.append("}"); return sb.toString(); } + {#if equals-hashcode} + {#if m.vars.size > 0} + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + {m.classname} model = ({m.classname}) o; + + {#if m.vars.size == 1} + return Objects.equals({m.vars.0.name}, model.{m.vars.0.name}); + {#else} + {#for v in m.vars} + {#if v_isFirst} + return Objects.equals({v.name}, model.{v.name}) && + {#else if v_isLast} + Objects.equals({v.name}, model.{v.name}); + {#else} + Objects.equals({v.name}, model.{v.name}) && + {/if} + {/for} + {/if} + } + + @Override + public int hashCode() { + {#if m.vars.size == 1} + return Objects.hash({m.vars.0.name}); + {#else} + {#for v in m.vars} + {#if v_isFirst} + return Objects.hash({v.name}, + {#else if v_isLast} + {v.name}); + {#else} + {v.name}, + {/if} + {/for} + {/if} + } + {/if} + {/if} /** * Convert the given object to string with each line indented by 4 spaces diff --git a/client/integration-tests/equals-hashcode/pom.xml b/client/integration-tests/equals-hashcode/pom.xml new file mode 100644 index 000000000..80d46519a --- /dev/null +++ b/client/integration-tests/equals-hashcode/pom.xml @@ -0,0 +1,93 @@ + + + + quarkus-openapi-generator-integration-tests + io.quarkiverse.openapi.generator + 3.0.0-SNAPSHOT + + 4.0.0 + + quarkus-openapi-generator-it-equals-hashcode + Quarkus - Openapi Generator - Integration Tests - Client - Equals hashcode + Example project for general usage + + + + io.quarkiverse.openapi.generator + quarkus-openapi-generator + + + org.assertj + assertj-core + test + + + io.quarkus + quarkus-junit5 + test + + + + + + io.quarkus + quarkus-maven-plugin + true + + + + build + generate-code + generate-code-tests + + + + + + + + + native-image + + + native + + + + + + maven-surefire-plugin + + ${native.surefire.skip} + + + + maven-failsafe-plugin + + + + integration-test + verify + + + + + ${project.build.directory}/${project.build.finalName}-runner + + org.jboss.logmanager.LogManager + + ${maven.home} + + + + + + + + + native + + + + + \ No newline at end of file diff --git a/client/integration-tests/equals-hashcode/src/main/openapi/quarkus-equals-hashcode-openapi.yaml b/client/integration-tests/equals-hashcode/src/main/openapi/quarkus-equals-hashcode-openapi.yaml new file mode 100644 index 000000000..ec431be5e --- /dev/null +++ b/client/integration-tests/equals-hashcode/src/main/openapi/quarkus-equals-hashcode-openapi.yaml @@ -0,0 +1,125 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "Animals - OpenAPI 3.0", + "version": "1.0.5" + }, + "servers": [ + { + "url": "/api/v3" + } + ], + "tags": [ + { + "name": "primate", + "description": "Everything about Primates" + } + ], + "paths": { + "/primate/{id}": { + "get": { + "tags": [ + "primate" + ], + "summary": "Find primate by ID", + "description": "Returns a single primate", + "operationId": "getPrimateById", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of primate to return", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Primate" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Primate not found" + } + } + } + } + }, + "components": { + "schemas": { + "Animal": { + "type": "object", + "properties": { + "born": { + "type": "string", + "description": "Dated Base extension.", + "format": "date-time" + }, + "deceased": { + "type": "string", + "description": "Dated Base extension.", + "format": "date-time" + } + }, + "xml": { + "name": "animal" + } + }, + "Mammal": { + "type": "object", + "allOf": [ { + "$ref": "#/components/schemas/Animal" + } ], + "properties": { + "gender": { + "type": "string", + "enum": [ + "female", + "male" + ] + } + }, + "xml": { + "name": "mammal" + } + }, + "Primate": { + "required": [ + "name" + ], + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/Mammal" + } + ], + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "name": { + "type": "string", + "example": "jane doe" + } + }, + "xml": { + "name": "primate" + } + } + } + } +} diff --git a/client/integration-tests/equals-hashcode/src/main/openapi/quarkus-non-equals-hashcode-openapi.yaml b/client/integration-tests/equals-hashcode/src/main/openapi/quarkus-non-equals-hashcode-openapi.yaml new file mode 100644 index 000000000..ec431be5e --- /dev/null +++ b/client/integration-tests/equals-hashcode/src/main/openapi/quarkus-non-equals-hashcode-openapi.yaml @@ -0,0 +1,125 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "Animals - OpenAPI 3.0", + "version": "1.0.5" + }, + "servers": [ + { + "url": "/api/v3" + } + ], + "tags": [ + { + "name": "primate", + "description": "Everything about Primates" + } + ], + "paths": { + "/primate/{id}": { + "get": { + "tags": [ + "primate" + ], + "summary": "Find primate by ID", + "description": "Returns a single primate", + "operationId": "getPrimateById", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "ID of primate to return", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Primate" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Primate not found" + } + } + } + } + }, + "components": { + "schemas": { + "Animal": { + "type": "object", + "properties": { + "born": { + "type": "string", + "description": "Dated Base extension.", + "format": "date-time" + }, + "deceased": { + "type": "string", + "description": "Dated Base extension.", + "format": "date-time" + } + }, + "xml": { + "name": "animal" + } + }, + "Mammal": { + "type": "object", + "allOf": [ { + "$ref": "#/components/schemas/Animal" + } ], + "properties": { + "gender": { + "type": "string", + "enum": [ + "female", + "male" + ] + } + }, + "xml": { + "name": "mammal" + } + }, + "Primate": { + "required": [ + "name" + ], + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/Mammal" + } + ], + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "name": { + "type": "string", + "example": "jane doe" + } + }, + "xml": { + "name": "primate" + } + } + } + } +} diff --git a/client/integration-tests/equals-hashcode/src/main/resources/application.properties b/client/integration-tests/equals-hashcode/src/main/resources/application.properties new file mode 100644 index 000000000..929c6beeb --- /dev/null +++ b/client/integration-tests/equals-hashcode/src/main/resources/application.properties @@ -0,0 +1,6 @@ +quarkus.openapi-generator.codegen.spec.quarkus_equals_hashcode_openapi_yaml.base-package=org.acme.equals.hashcode + +quarkus.openapi-generator.codegen.spec.quarkus_non_equals_hashcode_openapi_yaml.base-package=org.acme.non.equals.hashcode +quarkus.openapi-generator.codegen.spec.quarkus_non_equals_hashcode_openapi_yaml.equals-hashcode=false + +quarkus.keycloak.devservices.enabled=false \ No newline at end of file diff --git a/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/EqualsHashcodeTest.java b/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/EqualsHashcodeTest.java new file mode 100644 index 000000000..c9bf43842 --- /dev/null +++ b/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/EqualsHashcodeTest.java @@ -0,0 +1,52 @@ +package io.quarkiverse.openapi.generator.it; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import java.time.OffsetDateTime; + +import org.acme.equals.hashcode.model.Animal; +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +class EqualsHashcodeTest { + + @Test + void verifyModelNotEquals() { + var object1 = new Animal(); + object1.setDeceased(OffsetDateTime.now().minusHours(2)); + + var object2 = new Animal(); + object2.setBorn(OffsetDateTime.now().minusYears(1)); + + assertNotEquals(object1, object2); + } + + @Test + void verifyModelEquals() { + var offset = OffsetDateTime.now().minusHours(2); + + var object1 = new Animal(); + object1.setDeceased(offset); + + var object2 = new Animal(); + object2.setDeceased(offset); + + assertEquals(object1, object2); + } + + @Test + void verifyModelHasHashCode() { + var offset = OffsetDateTime.now().minusHours(2); + + var object1 = new Animal(); + object1.setDeceased(offset); + + var object2 = new Animal(); + object2.setDeceased(offset); + + assertEquals(object1.hashCode(), object2.hashCode()); + } +} diff --git a/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java b/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java new file mode 100644 index 000000000..22a73cdd9 --- /dev/null +++ b/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java @@ -0,0 +1,47 @@ +package io.quarkiverse.openapi.generator.it; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.stream.Stream; + +import org.acme.non.equals.hashcode.model.Animal; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +class VerifyGenerationTest { + + @ParameterizedTest + @MethodSource("provideStringsForIsBlank") + void verify(Class clazz, String methodName, Class expectedDeclaringClass) { + var equalsMethod = getMethod(clazz, methodName); + + Class declaringClass = equalsMethod.getDeclaringClass(); + + assertEquals(declaringClass, expectedDeclaringClass); + } + + private static Stream provideStringsForIsBlank() { + return Stream.of( + Arguments.of(Animal.class, "equals", Object.class), + Arguments.of(Animal.class, "hashCode", Object.class), + Arguments.of(org.acme.equals.hashcode.model.Animal.class, "equals", + org.acme.equals.hashcode.model.Animal.class), + Arguments.of(org.acme.equals.hashcode.model.Animal.class, "hashCode", + org.acme.equals.hashcode.model.Animal.class)); + } + + public static Method getMethod(Class clazz, String methodName) { + var methods = clazz.getMethods(); + + return Arrays.stream(methods) + .filter(method -> method.getName().equals(methodName)) + .findAny() + .orElseThrow(); + } +} diff --git a/client/integration-tests/pom.xml b/client/integration-tests/pom.xml index e1efcf5b3..e164c1a39 100644 --- a/client/integration-tests/pom.xml +++ b/client/integration-tests/pom.xml @@ -45,6 +45,7 @@ github without-oidc serializable-model + equals-hashcode diff --git a/docs/modules/ROOT/pages/client.adoc b/docs/modules/ROOT/pages/client.adoc index 7ea4386b0..aa6bf61c2 100644 --- a/docs/modules/ROOT/pages/client.adoc +++ b/docs/modules/ROOT/pages/client.adoc @@ -194,6 +194,11 @@ to true: quarkus.openapi-generator.codegen.spec.my_openapi_yaml.serializable-model=true ---- +[[equals-hashcode]] +== Equals and hashcode + +include::./includes/equals-hashcode.adoc[leveloffset=+1, opts=optional] + == Known Limitations === Supported Arguments diff --git a/docs/modules/ROOT/pages/includes/equals-hashcode.adoc b/docs/modules/ROOT/pages/includes/equals-hashcode.adoc new file mode 100644 index 000000000..3189b7ab8 --- /dev/null +++ b/docs/modules/ROOT/pages/includes/equals-hashcode.adoc @@ -0,0 +1,9 @@ +`Hashcode` and `equals` are by default generated. It adds all the variables in the model +to the model to the methods. + +To disable set `equals-hashcode` to false: + +[source,properties] +---- +quarkus.openapi-generator.codegen.spec.my_openapi_yaml.equals-hashcode=false +---- \ No newline at end of file From 9e302e4fa6fa26df86569fd9e85ab37426d2a734 Mon Sep 17 00:00:00 2001 From: Richard Alm Date: Wed, 18 Dec 2024 18:08:17 +0100 Subject: [PATCH 2/8] Added extra empty row between toString and equals --- .../main/resources/templates/libraries/microprofile/pojo.qute | 1 + 1 file changed, 1 insertion(+) diff --git a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute index a15175f4c..76e11a659 100644 --- a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute +++ b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute @@ -135,6 +135,7 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if serializabl sb.append("}"); return sb.toString(); } + {#if equals-hashcode} {#if m.vars.size > 0} @Override From a5cd95b450b7044c35e4c6ee329c68886048464c Mon Sep 17 00:00:00 2001 From: Richard Alm Date: Wed, 18 Dec 2024 23:14:57 +0100 Subject: [PATCH 3/8] Updated the documentation --- docs/modules/ROOT/pages/includes/equals-hashcode.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/includes/equals-hashcode.adoc b/docs/modules/ROOT/pages/includes/equals-hashcode.adoc index 3189b7ab8..e35d3704f 100644 --- a/docs/modules/ROOT/pages/includes/equals-hashcode.adoc +++ b/docs/modules/ROOT/pages/includes/equals-hashcode.adoc @@ -1,5 +1,5 @@ -`Hashcode` and `equals` are by default generated. It adds all the variables in the model -to the model to the methods. +`hashcode` and `equals` are by default generated to all models. `hashcode` and `equals` is based on all the variables +in the model and can't be customized. To disable set `equals-hashcode` to false: From 3d02cc2e7d8293643ed06835976ace4724565b39 Mon Sep 17 00:00:00 2001 From: Richard Alm Date: Wed, 18 Dec 2024 23:15:11 +0100 Subject: [PATCH 4/8] Added javadoc to the equals and hashcode methods --- .../libraries/microprofile/pojo.qute | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute index 76e11a659..e9e3204eb 100644 --- a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute +++ b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute @@ -138,12 +138,22 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if serializabl {#if equals-hashcode} {#if m.vars.size > 0} + /** + * Compares this object to the specified object. The result is + * \{@code true\} if and only if the argument is not + * \{@code null\} and is a \{@code {m.classname}\} object that + * contains the same values as this object. + * + * @param obj the object to compare with. + * @return \{@code true\} if the objects are the same; + * \{@code false\} otherwise. + **/ @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; - {m.classname} model = ({m.classname}) o; + {m.classname} model = ({m.classname}) obj; {#if m.vars.size == 1} return Objects.equals({m.vars.0.name}, model.{m.vars.0.name}); @@ -160,6 +170,11 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if serializabl {/if} } + /** + * Returns a hash code for a \{@code {m.classname}\}. + * + * @return a hash code value for a \{@code {m.classname}\}. + **/ @Override public int hashCode() { {#if m.vars.size == 1} From ac665fe184af7b49dda157a8c5fbdf89e7b8d52c Mon Sep 17 00:00:00 2001 From: Richard Alm <44467351+denvitaharen@users.noreply.github.com> Date: Fri, 20 Dec 2024 14:11:55 +0100 Subject: [PATCH 5/8] Update docs/modules/ROOT/pages/includes/equals-hashcode.adoc Co-authored-by: Matheus Cruz <56329339+mcruzdev@users.noreply.github.com> --- docs/modules/ROOT/pages/includes/equals-hashcode.adoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/includes/equals-hashcode.adoc b/docs/modules/ROOT/pages/includes/equals-hashcode.adoc index e35d3704f..b916c4c8f 100644 --- a/docs/modules/ROOT/pages/includes/equals-hashcode.adoc +++ b/docs/modules/ROOT/pages/includes/equals-hashcode.adoc @@ -1,5 +1,4 @@ -`hashcode` and `equals` are by default generated to all models. `hashcode` and `equals` is based on all the variables -in the model and can't be customized. +By default, `hashcode` and `equals` methods are automatically generated for all models. These methods are based on all the variables in the model and can not be customized. To disable set `equals-hashcode` to false: From 53db5f994b6fbacca5968007dd0c41920e391e08 Mon Sep 17 00:00:00 2001 From: Richard Alm Date: Fri, 20 Dec 2024 15:26:35 +0100 Subject: [PATCH 6/8] Changed so we use FCQN instead of importin java.util.Objects. --- .../templates/libraries/microprofile/pojo.qute | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute index e9e3204eb..8a0c4ec3a 100644 --- a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute +++ b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute @@ -1,6 +1,5 @@ {@org.openapitools.codegen.CodegenModel m} import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Objects; {#if m.description} /** @@ -156,15 +155,15 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if serializabl {m.classname} model = ({m.classname}) obj; {#if m.vars.size == 1} - return Objects.equals({m.vars.0.name}, model.{m.vars.0.name}); + return java.util.Objects.equals({m.vars.0.name}, model.{m.vars.0.name}); {#else} {#for v in m.vars} {#if v_isFirst} - return Objects.equals({v.name}, model.{v.name}) && + return java.util.Objects.equals({v.name}, model.{v.name}) && {#else if v_isLast} - Objects.equals({v.name}, model.{v.name}); + java.util.Objects.equals({v.name}, model.{v.name}); {#else} - Objects.equals({v.name}, model.{v.name}) && + java.util.Objects.equals({v.name}, model.{v.name}) && {/if} {/for} {/if} @@ -178,11 +177,11 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if serializabl @Override public int hashCode() { {#if m.vars.size == 1} - return Objects.hash({m.vars.0.name}); + return java.util.Objects.hash({m.vars.0.name}); {#else} {#for v in m.vars} {#if v_isFirst} - return Objects.hash({v.name}, + return java.util.Objects.hash({v.name}, {#else if v_isLast} {v.name}); {#else} From cd63c11125f3907c70d6637597f9a7481aec0923 Mon Sep 17 00:00:00 2001 From: Richard Alm Date: Fri, 20 Dec 2024 15:50:22 +0100 Subject: [PATCH 7/8] Refactored VerifyGenerationTest so it tests the generation better. --- .../generator/it/VerifyGenerationTest.java | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java b/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java index 22a73cdd9..ccc3fb489 100644 --- a/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java +++ b/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java @@ -1,42 +1,37 @@ package io.quarkiverse.openapi.generator.it; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import java.lang.reflect.Method; import java.util.Arrays; -import java.util.stream.Stream; -import org.acme.non.equals.hashcode.model.Animal; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.api.Test; import io.quarkus.test.junit.QuarkusTest; @QuarkusTest class VerifyGenerationTest { - @ParameterizedTest - @MethodSource("provideStringsForIsBlank") - void verify(Class clazz, String methodName, Class expectedDeclaringClass) { - var equalsMethod = getMethod(clazz, methodName); + @Test + void verifyThatGeneratedModelDoesntHaveMethods() { + var equalsMethod = getMethod(org.acme.equals.hashcode.model.Animal.class, "equals"); + var hashCodeMethod = getMethod(org.acme.equals.hashcode.model.Animal.class, "hashCode"); - Class declaringClass = equalsMethod.getDeclaringClass(); - - assertEquals(declaringClass, expectedDeclaringClass); + assertEquals(equalsMethod.getDeclaringClass(), org.acme.equals.hashcode.model.Animal.class); + assertEquals(hashCodeMethod.getDeclaringClass(), org.acme.equals.hashcode.model.Animal.class); } - private static Stream provideStringsForIsBlank() { - return Stream.of( - Arguments.of(Animal.class, "equals", Object.class), - Arguments.of(Animal.class, "hashCode", Object.class), - Arguments.of(org.acme.equals.hashcode.model.Animal.class, "equals", - org.acme.equals.hashcode.model.Animal.class), - Arguments.of(org.acme.equals.hashcode.model.Animal.class, "hashCode", - org.acme.equals.hashcode.model.Animal.class)); + @Test + void verifyThatGeneratedModelDoesHaveMethods() { + var equalsMethod = getMethod(org.acme.non.equals.hashcode.model.Animal.class, "equals"); + var hashCodeMethod = getMethod(org.acme.non.equals.hashcode.model.Animal.class, "hashCode"); + + assertNotEquals(equalsMethod.getDeclaringClass(), org.acme.equals.hashcode.model.Animal.class); + assertNotEquals(hashCodeMethod.getDeclaringClass(), org.acme.equals.hashcode.model.Animal.class); } - public static Method getMethod(Class clazz, String methodName) { + private static Method getMethod(Class clazz, String methodName) { var methods = clazz.getMethods(); return Arrays.stream(methods) From 5121a39a66965125be387fbb43a32c3612e69e81 Mon Sep 17 00:00:00 2001 From: Richard Alm Date: Sun, 22 Dec 2024 10:29:05 +0100 Subject: [PATCH 8/8] Corrected name of methods in VerifyGenerationTest. --- .../openapi/generator/it/VerifyGenerationTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java b/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java index ccc3fb489..30224b75a 100644 --- a/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java +++ b/client/integration-tests/equals-hashcode/src/test/java/io/quarkiverse/openapi/generator/it/VerifyGenerationTest.java @@ -14,7 +14,7 @@ class VerifyGenerationTest { @Test - void verifyThatGeneratedModelDoesntHaveMethods() { + void verifyThatGeneratedModelDoesHaveMethods() { var equalsMethod = getMethod(org.acme.equals.hashcode.model.Animal.class, "equals"); var hashCodeMethod = getMethod(org.acme.equals.hashcode.model.Animal.class, "hashCode"); @@ -23,7 +23,7 @@ void verifyThatGeneratedModelDoesntHaveMethods() { } @Test - void verifyThatGeneratedModelDoesHaveMethods() { + void verifyThatGeneratedModelDoesntHaveMethods() { var equalsMethod = getMethod(org.acme.non.equals.hashcode.model.Animal.class, "equals"); var hashCodeMethod = getMethod(org.acme.non.equals.hashcode.model.Animal.class, "hashCode");