From 0877e946a996abad24248c6a87aa4727ec038181 Mon Sep 17 00:00:00 2001 From: Benjamin Eckstein <13351939+benjamineckstein@users.noreply.github.com> Date: Tue, 19 Nov 2019 16:04:22 +0100 Subject: [PATCH] TSK-950: Test pojo implementation of equals and hashcode --- lib/taskana-core/pom.xml | 6 ++ .../src/main/java/pro/taskana/KeyDomain.java | 2 +- .../java/pro/taskana/ObjectReference.java | 2 +- .../main/java/pro/taskana/TimeInterval.java | 2 +- .../java/pro/taskana/impl/AttachmentImpl.java | 2 +- .../taskana/impl/AttachmentSummaryImpl.java | 2 +- .../pro/taskana/impl/ClassificationImpl.java | 16 ++++- .../impl/ClassificationSummaryImpl.java | 16 ++++- .../main/java/pro/taskana/impl/TaskImpl.java | 2 +- .../pro/taskana/impl/TaskSummaryImpl.java | 2 +- .../impl/WorkbasketAccessItemImpl.java | 18 +++++- .../java/pro/taskana/impl/WorkbasketImpl.java | 4 +- .../taskana/impl/WorkbasketSummaryImpl.java | 2 +- .../pro/taskana/EqualsAndHashCodeTest.java | 59 +++++++++++++++++++ pom.xml | 1 + 15 files changed, 124 insertions(+), 12 deletions(-) create mode 100644 lib/taskana-core/src/test/java/pro/taskana/EqualsAndHashCodeTest.java diff --git a/lib/taskana-core/pom.xml b/lib/taskana-core/pom.xml index bb78db67b..6f937a947 100644 --- a/lib/taskana-core/pom.xml +++ b/lib/taskana-core/pom.xml @@ -102,6 +102,12 @@ ${version.log4j} test + + nl.jqno.equalsverifier + equalsverifier + ${version.equalsverifier} + test + diff --git a/lib/taskana-core/src/main/java/pro/taskana/KeyDomain.java b/lib/taskana-core/src/main/java/pro/taskana/KeyDomain.java index bf6f07763..370a7b818 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/KeyDomain.java +++ b/lib/taskana-core/src/main/java/pro/taskana/KeyDomain.java @@ -56,7 +56,7 @@ public class KeyDomain { if (obj == null) { return false; } - if (getClass() != obj.getClass()) { + if (!getClass().isAssignableFrom(obj.getClass())) { return false; } KeyDomain other = (KeyDomain) obj; diff --git a/lib/taskana-core/src/main/java/pro/taskana/ObjectReference.java b/lib/taskana-core/src/main/java/pro/taskana/ObjectReference.java index acdae406f..4e9b6298b 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/ObjectReference.java +++ b/lib/taskana-core/src/main/java/pro/taskana/ObjectReference.java @@ -90,7 +90,7 @@ public class ObjectReference { if (other == null) { return false; } - if (other.getClass() != getClass()) { + if (!getClass().isAssignableFrom(other.getClass())) { return false; } ObjectReference o = (ObjectReference) other; diff --git a/lib/taskana-core/src/main/java/pro/taskana/TimeInterval.java b/lib/taskana-core/src/main/java/pro/taskana/TimeInterval.java index 67c1d9e14..d2aa40945 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/TimeInterval.java +++ b/lib/taskana-core/src/main/java/pro/taskana/TimeInterval.java @@ -73,7 +73,7 @@ public class TimeInterval { if (obj == null) { return false; } - if (getClass() != obj.getClass()) { + if (!getClass().isAssignableFrom(obj.getClass())) { return false; } TimeInterval other = (TimeInterval) obj; diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/AttachmentImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/AttachmentImpl.java index 32ff9e775..58ab95021 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/AttachmentImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/AttachmentImpl.java @@ -166,7 +166,7 @@ public class AttachmentImpl implements Attachment { if (obj == null) { return false; } - if (getClass() != obj.getClass()) { + if (!getClass().isAssignableFrom(obj.getClass())) { return false; } AttachmentImpl other = (AttachmentImpl) obj; diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/AttachmentSummaryImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/AttachmentSummaryImpl.java index 8491094ce..543b6d25c 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/AttachmentSummaryImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/AttachmentSummaryImpl.java @@ -161,7 +161,7 @@ public class AttachmentSummaryImpl implements AttachmentSummary { if (obj == null) { return false; } - if (!(obj instanceof AttachmentSummaryImpl)) { + if (!getClass().isAssignableFrom(obj.getClass())) { return false; } AttachmentSummaryImpl other = (AttachmentSummaryImpl) obj; diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationImpl.java index ddff3fc44..cf1557bbd 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationImpl.java @@ -134,13 +134,23 @@ public class ClassificationImpl extends ClassificationSummaryImpl implements Cla if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) { + if (o == null) { return false; } + + if (!getClass().isAssignableFrom(o.getClass())) { + return false; + } + if (!super.equals(o)) { return false; } ClassificationImpl that = (ClassificationImpl) o; + + if (!that.canEqual(this)) { + return false; + } + return Objects.equals(isValidInDomain, that.isValidInDomain) && Objects.equals(created, that.created) && Objects.equals(modified, that.modified) @@ -148,6 +158,10 @@ public class ClassificationImpl extends ClassificationSummaryImpl implements Cla && Objects.equals(applicationEntryPoint, that.applicationEntryPoint); } + protected boolean canEqual(Object other) { + return (other instanceof ClassificationImpl); + } + @Override public int hashCode() { return Objects.hash(super.hashCode(), isValidInDomain, created, modified, description, applicationEntryPoint); diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationSummaryImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationSummaryImpl.java index 4b7fc829f..09cfab9e8 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationSummaryImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationSummaryImpl.java @@ -198,10 +198,20 @@ public class ClassificationSummaryImpl implements ClassificationSummary { if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) { + if (o == null) { return false; } + + if (!getClass().isAssignableFrom(o.getClass())) { + return false; + } + ClassificationSummaryImpl that = (ClassificationSummaryImpl) o; + + if (!that.canEqual(this)) { + return false; + } + return priority == that.priority && Objects.equals(id, that.id) && Objects.equals(key, that.key) @@ -222,6 +232,10 @@ public class ClassificationSummaryImpl implements ClassificationSummary { && Objects.equals(custom8, that.custom8); } + protected boolean canEqual(Object other) { + return (other instanceof ClassificationSummaryImpl); + } + @Override public int hashCode() { return Objects.hash(id, key, category, type, domain, name, parentId, parentKey, priority, serviceLevel, custom1, diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskImpl.java index d31cc8379..dc7869cf5 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskImpl.java @@ -774,7 +774,7 @@ public class TaskImpl implements Task { if (obj == null) { return false; } - if (getClass() != obj.getClass()) { + if (!getClass().isAssignableFrom(obj.getClass())) { return false; } TaskImpl other = (TaskImpl) obj; diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskSummaryImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskSummaryImpl.java index c15bad255..5bcbd7b47 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskSummaryImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskSummaryImpl.java @@ -552,7 +552,7 @@ public class TaskSummaryImpl implements TaskSummary { if (obj == null) { return false; } - if (getClass() != obj.getClass()) { + if (!getClass().isAssignableFrom(obj.getClass())) { return false; } TaskSummaryImpl other = (TaskSummaryImpl) obj; diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketAccessItemImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketAccessItemImpl.java index 5f140fed0..5e5bf4edf 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketAccessItemImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketAccessItemImpl.java @@ -461,6 +461,8 @@ public class WorkbasketAccessItemImpl implements WorkbasketAccessItem { result = prime * result + (permRead ? 1231 : 1237); result = prime * result + (permTransfer ? 1231 : 1237); result = prime * result + ((workbasketId == null) ? 0 : workbasketId.hashCode()); + result = prime * result + ((workbasketKey == null) ? 0 : workbasketKey.hashCode()); + result = prime * result + ((accessName == null) ? 0 : accessName.hashCode()); return result; } @@ -472,7 +474,7 @@ public class WorkbasketAccessItemImpl implements WorkbasketAccessItem { if (obj == null) { return false; } - if (getClass() != obj.getClass()) { + if (!getClass().isAssignableFrom(obj.getClass())) { return false; } WorkbasketAccessItemImpl other = (WorkbasketAccessItemImpl) obj; @@ -548,6 +550,20 @@ public class WorkbasketAccessItemImpl implements WorkbasketAccessItem { } else if (!workbasketId.equals(other.workbasketId)) { return false; } + if (workbasketKey == null) { + if (other.workbasketKey != null) { + return false; + } + } else if (!workbasketKey.equals(other.workbasketKey)) { + return false; + } + if (accessName == null) { + if (other.accessName != null) { + return false; + } + } else if (!accessName.equals(other.accessName)) { + return false; + } return true; } diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketImpl.java index 92fa76338..200be9422 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketImpl.java @@ -1,6 +1,7 @@ package pro.taskana.impl; import java.time.Instant; + import pro.taskana.Workbasket; import pro.taskana.WorkbasketSummary; import pro.taskana.WorkbasketType; @@ -262,7 +263,8 @@ public class WorkbasketImpl implements Workbasket { if (obj == null) { return false; } - if (getClass() != obj.getClass()) { + + if (!getClass().isAssignableFrom(obj.getClass())) { return false; } WorkbasketImpl other = (WorkbasketImpl) obj; diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketSummaryImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketSummaryImpl.java index ef6515e8d..3d140a9b0 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketSummaryImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketSummaryImpl.java @@ -263,7 +263,7 @@ public class WorkbasketSummaryImpl implements WorkbasketSummary { if (obj == null) { return false; } - if (getClass() != obj.getClass()) { + if (!getClass().isAssignableFrom(obj.getClass())) { return false; } WorkbasketSummaryImpl other = (WorkbasketSummaryImpl) obj; diff --git a/lib/taskana-core/src/test/java/pro/taskana/EqualsAndHashCodeTest.java b/lib/taskana-core/src/test/java/pro/taskana/EqualsAndHashCodeTest.java new file mode 100644 index 000000000..bd237f350 --- /dev/null +++ b/lib/taskana-core/src/test/java/pro/taskana/EqualsAndHashCodeTest.java @@ -0,0 +1,59 @@ +package pro.taskana; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; + +import nl.jqno.equalsverifier.EqualsVerifier; +import nl.jqno.equalsverifier.Warning; +import pro.taskana.impl.AttachmentImpl; +import pro.taskana.impl.AttachmentSummaryImpl; +import pro.taskana.impl.ClassificationImpl; +import pro.taskana.impl.ClassificationSummaryImpl; +import pro.taskana.impl.TaskImpl; +import pro.taskana.impl.TaskSummaryImpl; +import pro.taskana.impl.WorkbasketAccessItemImpl; +import pro.taskana.impl.WorkbasketImpl; +import pro.taskana.impl.WorkbasketSummaryImpl; + +/** + * check classes with a custom equals and hashcode implementation for correctness. + */ +class EqualsAndHashCodeTest { + + @TestFactory + Collection equalsContract() { + return + getPojoClasses().stream() + .map(cl -> DynamicTest.dynamicTest("Check Hash and Equals for " + cl.getSimpleName(), + () -> { + EqualsVerifier.forClass(cl) + .suppress(Warning.NONFINAL_FIELDS, Warning.STRICT_INHERITANCE) + .withRedefinedSuperclass() + .verify(); + })) + .collect(Collectors.toList()); + } + + //TODO find a way to dynamically create a list with custom implemented equals or hash methods. + private List> getPojoClasses() { + return Arrays.asList( + KeyDomain.class, + ObjectReference.class, + TimeInterval.class, + AttachmentImpl.class, + AttachmentSummaryImpl.class, + ClassificationImpl.class, + ClassificationSummaryImpl.class, + TaskImpl.class, + TaskSummaryImpl.class, + WorkbasketAccessItemImpl.class, + WorkbasketImpl.class, + WorkbasketSummaryImpl.class + ); + } +} diff --git a/pom.xml b/pom.xml index b581245fe..8f50e12f2 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,7 @@ 2.8.47 1.7.1 1.3 + 3.1.10 1.4.197