diff --git a/src/main/java/org/springframework/data/domain/AbstractAggregateRoot.java b/src/main/java/org/springframework/data/domain/AbstractAggregateRoot.java index 4164520b4..a6a89fbf6 100644 --- a/src/main/java/org/springframework/data/domain/AbstractAggregateRoot.java +++ b/src/main/java/org/springframework/data/domain/AbstractAggregateRoot.java @@ -33,7 +33,7 @@ import org.springframework.util.Assert; * @author Christoph Strobl * @since 1.13 */ -public class AbstractAggregateRoot { +public class AbstractAggregateRoot> { private transient final @Transient List domainEvents = new ArrayList<>(); @@ -41,7 +41,8 @@ public class AbstractAggregateRoot { * Registers the given event object for publication on a call to a Spring Data repository's save methods. * * @param event must not be {@literal null}. - * @return + * @return the event that has been added. + * @see #andEvent(Object) */ protected T registerEvent(T event) { @@ -67,4 +68,34 @@ public class AbstractAggregateRoot { protected Collection domainEvents() { return Collections.unmodifiableList(domainEvents); } + + /** + * Adds all events contained in the given aggregate to the current one. + * + * @param aggregate must not be {@literal null}. + * @return the aggregate + */ + protected final A andEventsFrom(A aggregate) { + + Assert.notNull(aggregate, "Aggregate must not be null!"); + + this.domainEvents.addAll(aggregate.domainEvents()); + + return (A) this; + } + + /** + * Adds the given event to the aggregate for later publication when calling a Spring Data repository's save-method. + * Does the same as {@link #registerEvent(Object)} but returns the aggregate instead of the event. + * + * @param event must not be {@literal null}. + * @return the aggregate + * @see #registerEvent(Object) + */ + protected final A andEvent(Object event) { + + registerEvent(event); + + return (A) this; + } } diff --git a/src/test/java/org/springframework/data/domain/AbstractAggregateRootUnitTests.java b/src/test/java/org/springframework/data/domain/AbstractAggregateRootUnitTests.java new file mode 100644 index 000000000..75d70f374 --- /dev/null +++ b/src/test/java/org/springframework/data/domain/AbstractAggregateRootUnitTests.java @@ -0,0 +1,106 @@ +/* + * Copyright 2017 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.springframework.data.domain; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.Test; + +/** + * Unit tests for {@link AbstractAggregateRoot}. + * + * @author Oliver Gierke + */ +public class AbstractAggregateRootUnitTests { + + @Test // DATACMNS-928 + public void registersEvent() { + + Object event = new Object(); + + SampleAggregate aggregate = new SampleAggregate(); + aggregate.registerEvent(event); + + assertThat(aggregate.domainEvents()).containsExactly(event); + } + + @Test // DATACMNS-928 + public void clearsEvents() { + + Object event = new Object(); + + SampleAggregate aggregate = new SampleAggregate(); + aggregate.registerEvent(event); + + assertThat(aggregate.domainEvents()).isNotEmpty(); + + aggregate.clearDomainEvents(); + + assertThat(aggregate.domainEvents()).isEmpty(); + } + + @Test // DATACMNS-928, DATACMNS-1162 + public void copiesEventsFromExistingAggregate() { + + SampleAggregate aggregate = new SampleAggregate(); + aggregate.registerEvent(new Object()); + + SampleAggregate result = new SampleAggregate().andEventsFrom(aggregate); + + assertThat(result.domainEvents()).isEqualTo(aggregate.domainEvents()); + } + + @Test // DATACMNS-928, DATACMNS-1162 + public void addsEventAndReturnsAggregate() { + + Object first = new Object(); + Object second = new Object(); + + SampleAggregate aggregate = new SampleAggregate(); + aggregate.registerEvent(first); + + SampleAggregate result = aggregate.andEvent(second); + + assertThat(result).isSameAs(aggregate); + assertThat(result.domainEvents()).containsExactly(first, second); + } + + @Test // DATACMNS-928, DATACMNS-1162 + @SuppressWarnings("null") + public void rejectsNullEvent() { + + assertThatExceptionOfType(IllegalArgumentException.class) // + .isThrownBy(() -> new SampleAggregate().andEvent(null)); + } + + @Test // DATACMNS-928 + @SuppressWarnings("null") + public void rejectsNullEventForRegistration() { + + assertThatExceptionOfType(IllegalArgumentException.class) // + .isThrownBy(() -> new SampleAggregate().registerEvent(null)); + } + + @Test // DATACMNS-928, DATACMNS-1162 + @SuppressWarnings("null") + public void rejectsNullAggregate() { + + assertThatExceptionOfType(IllegalArgumentException.class) // + .isThrownBy(() -> new SampleAggregate().andEventsFrom(null)); + } + + static class SampleAggregate extends AbstractAggregateRoot {} +}