diff --git a/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/Association.java b/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/Association.java index 9d3b8f7..6d27df7 100644 --- a/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/Association.java +++ b/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/Association.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 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. @@ -27,4 +27,60 @@ * @see (() -> aggregate.getId()); + } + + /** + * Creates an {@link Association} pointing to the given {@link Identifier}. + * + * @param the concrete {@link AggregateRoot} type. + * @param the concrete {@link Identifier} type. + * @param identifier must not be {@literal null}. + * @return an {@link Association} pointing to the given {@link Identifier}, will never be {@literal null}. + * @since 1.2 + */ + static , ID extends Identifier> Association forId(ID identifier) { + + if (identifier == null) { + throw new IllegalArgumentException("Identifier must not be null!"); + } + + return new SimpleAssociation<>(() -> identifier); + } + + /** + * Returns whether the current {@link Association} points to the same {@link AggregateRoot} as the given one. Unlike + * {@link #equals(Object)} and {@link #hashCode()} that also check for type equality of the {@link Association} + * itself, this only compares the target {@link Identifier} instances. + * + * @param other must not be {@literal null}. + * @return whether the current {@link Association} points to the same {@link AggregateRoot} as the given one. + * @since 1.2 + */ + default boolean pointsToSameAggregateAs(Association other) { + + if (other == null) { + throw new IllegalArgumentException("Other association must not be null!"); + } + + return getId().equals(other.getId()); + } +} diff --git a/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/SimpleAssociation.java b/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/SimpleAssociation.java new file mode 100644 index 0000000..66b5c6c --- /dev/null +++ b/jmolecules-ddd/src/main/java/org/jmolecules/ddd/types/SimpleAssociation.java @@ -0,0 +1,75 @@ +/* + * Copyright 2021 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 + * + * https://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; + +import java.util.function.Supplier; + +/** + * @author Oliver Drotbohm + */ +class SimpleAssociation, ID extends Identifier> implements Association { + + private final Supplier identifier; + + SimpleAssociation(Supplier identifier) { + this.identifier = identifier; + } + + /* + * (non-Javadoc) + * @see org.jmolecules.ddd.types.Identifiable#getId() + */ + @Override + public ID getId() { + return identifier.get(); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return getId().toString(); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + + if (obj == this) { + return true; + } + + if (obj == null || !obj.getClass().equals(this.getClass())) { + return false; + } + + return ((Association) obj).getId().equals(identifier.get()); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return getId().hashCode(); + } +} diff --git a/jmolecules-ddd/src/test/java/org/jmolecules/ddd/types/AssociationUnitTests.java b/jmolecules-ddd/src/test/java/org/jmolecules/ddd/types/AssociationUnitTests.java new file mode 100644 index 0000000..288b33e --- /dev/null +++ b/jmolecules-ddd/src/test/java/org/jmolecules/ddd/types/AssociationUnitTests.java @@ -0,0 +1,120 @@ +/* + * Copyright 2021 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 + * + * https://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; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link Association}. + * + * @author Oliver Drotbohm + */ +public class AssociationUnitTests { + + @Test // #48 + void createsAssociationFromIdentifier() { + + SampleIdentifier id = new SampleIdentifier(); + + assertThat(Association.forId(id).getId()).isEqualTo(id); + } + + @Test // #48 + void createsAssoctionFromAggregate() { + + SampleIdentifier identifier = new SampleIdentifier(); + SampleAggregate aggregate = new SampleAggregate(identifier); + + assertThat(Association.forAggregate(aggregate).getId()).isEqualTo(identifier); + } + + @Test // #48 + void rejectsNullIdentifier() { + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> Association.forId(null)); + } + + @Test // #48 + void rejectsNullAggregate() { + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> Association.forAggregate(null)); + } + + @Test // #48 + void associationsEqualIfTheyPointToTheSameId() { + + SampleIdentifier identifier = new SampleIdentifier(); + SampleAggregate aggregate = new SampleAggregate(identifier); + + assertThat(Association.forId(identifier)).isEqualTo(Association.forAggregate(aggregate)); + } + + @Test // #48 + void pointsToSameAggregate() { + + SampleIdentifier identifier = new SampleIdentifier(); + Association simpleAssociation = Association.forId(identifier); + SampleAssociation sampleAssociation = new SampleAssociation(identifier); + + assertThat(simpleAssociation.pointsToSameAggregateAs(sampleAssociation)); + assertThat(sampleAssociation.pointsToSameAggregateAs(simpleAssociation)); + } + + @Test // #48 + void rejectsNullReferenceAggregate() { + + assertThatIllegalArgumentException() + .isThrownBy(() -> Association.forId(new SampleIdentifier()).pointsToSameAggregateAs(null)); + } + + static class SampleIdentifier implements Identifier {} + + static class SampleAggregate implements AggregateRoot { + + private final SampleIdentifier id; + + SampleAggregate(SampleIdentifier id) { + this.id = id; + } + + /* + * (non-Javadoc) + * @see org.jmolecules.ddd.types.Identifiable#getId() + */ + @Override + public SampleIdentifier getId() { + return id; + } + } + + static class SampleAssociation implements Association { + + SampleIdentifier id; + + public SampleAssociation(SampleIdentifier id) { + this.id = id; + } + + /* + * (non-Javadoc) + * @see org.jmolecules.ddd.types.Identifiable#getId() + */ + @Override + public SampleIdentifier getId() { + return id; + } + } +} diff --git a/pom.xml b/pom.xml index 317fbf4..365267d 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,8 @@ UTF-8 + 3.18.1 + 5.7.0 @@ -104,6 +106,21 @@ + + + + org.junit.jupiter + junit-jupiter + ${junit.version} + test + + + org.assertj + assertj-core + ${assertj.version} + test + +