1 | package com.reallifedeveloper.common.application.eventstore; | |
2 | ||
3 | import static com.reallifedeveloper.common.domain.LogUtil.removeCRLF; | |
4 | ||
5 | import java.util.List; | |
6 | ||
7 | import org.slf4j.Logger; | |
8 | import org.slf4j.LoggerFactory; | |
9 | ||
10 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; | |
11 | ||
12 | import com.reallifedeveloper.common.domain.ErrorHandling; | |
13 | import com.reallifedeveloper.common.domain.ObjectSerializer; | |
14 | import com.reallifedeveloper.common.domain.event.DomainEvent; | |
15 | ||
16 | /** | |
17 | * An {@code EventStore} saves {@link DomainEvent DomainEvents} in a database as {@link StoredEvent StoredEvents}. | |
18 | * | |
19 | * @author RealLifeDeveloper | |
20 | */ | |
21 | public final class EventStore { | |
22 | ||
23 | private static final Logger LOG = LoggerFactory.getLogger(EventStore.class); | |
24 | ||
25 | private final ObjectSerializer<String> serializer; | |
26 | ||
27 | private final StoredEventRepository repository; | |
28 | ||
29 | /** | |
30 | * Creates a new {@code EventStore} with the given serializer and repository. | |
31 | * | |
32 | * @param serializer the {@code DomainEventSerializer} to use to serialize and deserialize {@code DomainEvents} | |
33 | * @param repository the {@code StoredEventRepository} to use to work with persisted {@code StoredEvents} | |
34 | */ | |
35 | @SuppressFBWarnings(value = "CRLF_INJECTION_LOGS", justification = "Logging only of objects, not user data") | |
36 | public EventStore(ObjectSerializer<String> serializer, StoredEventRepository repository) { | |
37 |
1
1. <init> : removed call to com/reallifedeveloper/common/domain/ErrorHandling::checkNull → KILLED |
ErrorHandling.checkNull("Arguments must not be null: serializer=%s, repository=%s", serializer, repository); |
38 | LOG.info("Creating new EventStore: serializer={}, repository={}", serializer, repository); | |
39 | this.serializer = serializer; | |
40 | this.repository = repository; | |
41 | } | |
42 | ||
43 | /** | |
44 | * Adds a new {@link StoredEvent} representing the given {@link DomainEvent} to the event store. | |
45 | * | |
46 | * @param event the {@code DomainEvent} to add | |
47 | * @return the saved {@code StoredEvent} representing {@code event} | |
48 | */ | |
49 | public StoredEvent add(DomainEvent event) { | |
50 | if (LOG.isTraceEnabled()) { | |
51 | LOG.trace("add: event={}", removeCRLF(event)); | |
52 | } | |
53 |
1
1. add : removed call to com/reallifedeveloper/common/domain/ErrorHandling::checkNull → KILLED |
ErrorHandling.checkNull("event must not be null", event); |
54 | String serializedEvent = serializer.serialize(event); | |
55 | StoredEvent storedEvent = new StoredEvent(event.getClass().getName(), serializedEvent, event.eventOccurredOn(), | |
56 | event.eventVersion()); | |
57 |
1
1. add : replaced return value with null for com/reallifedeveloper/common/application/eventstore/EventStore::add → KILLED |
return repository.save(storedEvent); |
58 | } | |
59 | ||
60 | /** | |
61 | * Gives all {@code StoredEvents} with IDs greater than {@code storedEventId}, i.e., all events that occurred after the event with the | |
62 | * given ID. | |
63 | * | |
64 | * @param storedEventId return all events with IDs greater than this | |
65 | * @return a list of {@code StoredEvents} with IDs greater than or equal to {@code firstStoredEventId} | |
66 | */ | |
67 | public List<StoredEvent> allEventsSince(long storedEventId) { | |
68 | LOG.trace("allEventsSince: storedEventId={}", storedEventId); | |
69 |
1
1. allEventsSince : replaced return value with Collections.emptyList for com/reallifedeveloper/common/application/eventstore/EventStore::allEventsSince → KILLED |
return repository.allEventsSince(storedEventId); |
70 | } | |
71 | ||
72 | /** | |
73 | * Gives all {@code StoredEvents} with IDs greater than or equal to {@code firstStoredEventId} and less than or equals to | |
74 | * {@code lastStoredEventId}, i.e., all events that occurred between the events with the given IDs, inclusive. | |
75 | * | |
76 | * @param firstStoredEventId ID of the first {@code StoredEvent} to retrieve | |
77 | * @param lastStoredEventId ID of the last {@code StoredEvent} to retrieve | |
78 | * @return a list of all {@code StoredEvents} with IDs between {@code firstStoredEventId} and {@code lastStoredEventId}, inclusive | |
79 | */ | |
80 | public List<StoredEvent> allEventsBetween(long firstStoredEventId, long lastStoredEventId) { | |
81 | LOG.trace("allEventsBetween: firstStoredEventId={}, lastStoredEventId={}", firstStoredEventId, lastStoredEventId); | |
82 |
1
1. allEventsBetween : replaced return value with Collections.emptyList for com/reallifedeveloper/common/application/eventstore/EventStore::allEventsBetween → KILLED |
return repository.allEventsBetween(firstStoredEventId, lastStoredEventId); |
83 | } | |
84 | ||
85 | /** | |
86 | * Converts a {@link StoredEvent} back to its original {@code DomainEvent}. | |
87 | * <p> | |
88 | * This is only guaranteed to work if the same kind of {@code EventStore}, using the same type of {@code DomainEventSerializer}, was | |
89 | * used to add the {@code DomainEvent}. | |
90 | * | |
91 | * @param storedEvent the {@code StoredEvent} to convert | |
92 | * @param <T> the type of {@code DomainEvent} to return | |
93 | * @return the original {@code DomainEvent} represented by {@code storedEvent} | |
94 | * @throws IllegalArgumentException if {@code storedEvent} is {@code null} | |
95 | * @throws IllegalStateException if loading of the class {@code T} failed | |
96 | */ | |
97 | public <T extends DomainEvent> T toDomainEvent(StoredEvent storedEvent) { | |
98 | if (LOG.isTraceEnabled()) { | |
99 | LOG.trace("toDomainEvent: storedEvent={}", removeCRLF(storedEvent)); | |
100 | } | |
101 |
1
1. toDomainEvent : removed call to com/reallifedeveloper/common/domain/ErrorHandling::checkNull → KILLED |
ErrorHandling.checkNull("storedEvent must not be null", storedEvent); |
102 | try { | |
103 | @SuppressWarnings("unchecked") | |
104 | Class<T> eventClass = (Class<T>) Class.forName(storedEvent.eventType()); | |
105 |
1
1. toDomainEvent : replaced return value with null for com/reallifedeveloper/common/application/eventstore/EventStore::toDomainEvent → KILLED |
return serializer.deserialize(storedEvent.eventBody(), eventClass); |
106 | } catch (ClassNotFoundException e) { | |
107 | throw new IllegalStateException("Failed to load class " + storedEvent.eventType(), e); | |
108 | } | |
109 | } | |
110 | ||
111 | /** | |
112 | * Gives the ID of the most recently added {@code StoredEvents}. | |
113 | * | |
114 | * @return the ID of the most recently added {@code StoredEvent} | |
115 | */ | |
116 | public long lastStoredEventId() { | |
117 | LOG.trace("lastStoredEventId"); | |
118 |
1
1. lastStoredEventId : replaced long return with 0 for com/reallifedeveloper/common/application/eventstore/EventStore::lastStoredEventId → KILLED |
return repository.lastStoredEventId().orElse(0L); |
119 | } | |
120 | } | |
Mutations | ||
37 |
1.1 |
|
53 |
1.1 |
|
57 |
1.1 |
|
69 |
1.1 |
|
82 |
1.1 |
|
101 |
1.1 |
|
105 |
1.1 |
|
118 |
1.1 |