diff --git a/jmolecules-ddd/pom.xml b/jmolecules-ddd/pom.xml index 95750d6..48da087 100644 --- a/jmolecules-ddd/pom.xml +++ b/jmolecules-ddd/pom.xml @@ -13,6 +13,20 @@ jMolecules - DDD + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + + org.assertj + assertj-core + ${assertj.version} + test + + org.projectlombok lombok diff --git a/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/AbstractEntity.java b/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/AbstractEntity.java new file mode 100644 index 0000000..5757055 --- /dev/null +++ b/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/AbstractEntity.java @@ -0,0 +1,68 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jmolecules.ddd.types; + +/** + * An abstract base for entities. + * Provides implementations for {@code equals()}, {@code hashCode()}, and {@code toString()} that are based on the identity of the entity. + */ +@org.jmolecules.ddd.annotation.Entity +public abstract class AbstractEntity, ID> implements Entity { + + private final ID identity; + + protected AbstractEntity(ID identity) { + if (identity == null) { + throw new IllegalArgumentException("identity must not be null"); + } + + this.identity = identity; + } + + @Override + public final ID getId() { + return identity; + } + + @Override + public String toString() { + return getClass().getSimpleName() + " [id=" + identity + "]"; + } + + @Override + public final boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + @SuppressWarnings("rawtypes") + AbstractEntity other = (AbstractEntity) obj; + if (identity == null) { + if (other.identity != null) + return false; + } else if (!identity.equals(other.identity)) + return false; + return true; + } + + @Override + public final int hashCode() { + return identity.hashCode(); + } + +} diff --git a/jmolecules-ddd/src/test/java/org/jmolecules/ddd/types/AbstractEntityTest.java b/jmolecules-ddd/src/test/java/org/jmolecules/ddd/types/AbstractEntityTest.java new file mode 100644 index 0000000..c9a9667 --- /dev/null +++ b/jmolecules-ddd/src/test/java/org/jmolecules/ddd/types/AbstractEntityTest.java @@ -0,0 +1,85 @@ +package org.jmolecules.ddd.types; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +import lombok.Value; + +class AbstractEntityTest { + + @Value + static class Id implements Identifier { + + long id; + + public static Id of(long id) { + return new Id(id); + } + + public String toString() { + return "" + id; + } + + } + + static class ConcreteEntity extends AbstractEntity implements AggregateRoot { + + public ConcreteEntity(Id id) { + super(id); + } + + } + + @Test + void givenANewEntity_whenGetId_thenEqual() { + // given + ConcreteEntity entityUnderTest = new ConcreteEntity(Id.of(47L)) { + }; + + // when + Id id = entityUnderTest.getId(); + + // then + assertThat(id).isEqualTo(Id.of(47L)); + } + + @Test + void givenTwoEntitiesOfSameTypeWithSameId_whenEquals_thenTrue() { + // given + ConcreteEntity entity1 = new ConcreteEntity(Id.of(47L)); + ConcreteEntity entity2 = new ConcreteEntity(Id.of(47L)); + + // when + boolean equal = entity1.equals(entity2); + + // then + assertThat(equal).isTrue(); + } + + @Test + void givenTwoEntitiesOfDifferentTypeWithSameId_whenEquals_thenFalse() { + // given + ConcreteEntity entity1 = new ConcreteEntity(Id.of(47L)) { }; + ConcreteEntity entity2 = new ConcreteEntity(Id.of(47L)) { }; + + // when + boolean equal = entity1.equals(entity2); + + // then + assertThat(equal).isFalse(); + } + + @Test + void givenAnEntity_whenToString_thenClassnamePlusId() { + // given + ConcreteEntity entityUnderTest = new ConcreteEntity(Id.of(47L)); + + // when + String string = entityUnderTest.toString(); + + // then + assertThat(string).isEqualTo("ConcreteEntity [id=47]"); + } + +}