Line data Source code
1 : #region Copyright
2 : // // -----------------------------------------------------------------------
3 : // // <copyright company="cdmdotnet Limited">
4 : // // Copyright cdmdotnet Limited. All rights reserved.
5 : // // </copyright>
6 : // // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Collections.Generic;
11 : using System.Linq;
12 : using cdmdotnet.Logging;
13 : using Cqrs.Domain.Exceptions;
14 : using Cqrs.Domain.Factories;
15 : using Cqrs.Events;
16 :
17 : namespace Cqrs.Domain
18 : {
19 : public class Repository<TAuthenticationToken> : IRepository<TAuthenticationToken>
20 0 : {
21 : protected IEventStore<TAuthenticationToken> EventStore { get; private set; }
22 :
23 : protected IEventPublisher<TAuthenticationToken> Publisher { get; private set; }
24 :
25 : protected IAggregateFactory AggregateFactory { get; private set; }
26 :
27 : protected ICorrelationIdHelper CorrelationIdHelper { get; private set; }
28 :
29 0 : public Repository(IAggregateFactory aggregateFactory, IEventStore<TAuthenticationToken> eventStore, IEventPublisher<TAuthenticationToken> publisher, ICorrelationIdHelper correlationIdHelper)
30 : {
31 : EventStore = eventStore;
32 : Publisher = publisher;
33 : CorrelationIdHelper = correlationIdHelper;
34 : AggregateFactory = aggregateFactory;
35 : }
36 :
37 0 : public virtual void Save<TAggregateRoot>(TAggregateRoot aggregate, int? expectedVersion = null)
38 : where TAggregateRoot : IAggregateRoot<TAuthenticationToken>
39 : {
40 : IList<IEvent<TAuthenticationToken>> uncommittedChanges = aggregate.GetUncommittedChanges().ToList();
41 : if (!uncommittedChanges.Any())
42 : return;
43 :
44 : if (expectedVersion != null)
45 : {
46 : IEnumerable<IEvent<TAuthenticationToken>> eventStoreResults = EventStore.Get(aggregate.GetType(), aggregate.Id, false, expectedVersion.Value);
47 : if (eventStoreResults.Any())
48 : throw new ConcurrencyException(aggregate.Id);
49 : }
50 :
51 : var eventsToPublish = new List<IEvent<TAuthenticationToken>>();
52 :
53 : int i = 0;
54 : foreach (IEvent<TAuthenticationToken> @event in uncommittedChanges)
55 : {
56 : if (@event.Id == Guid.Empty)
57 : @event.Id = aggregate.Id;
58 : if (@event.Id == Guid.Empty)
59 : throw new AggregateOrEventMissingIdException(aggregate.GetType(), @event.GetType());
60 :
61 : i++;
62 :
63 : @event.Version = aggregate.Version + i;
64 : @event.TimeStamp = DateTimeOffset.UtcNow;
65 : @event.CorrelationId = CorrelationIdHelper.GetCorrelationId();
66 : EventStore.Save(aggregate.GetType(), @event);
67 : eventsToPublish.Add(@event);
68 : }
69 :
70 : aggregate.MarkChangesAsCommitted();
71 : foreach (IEvent<TAuthenticationToken> @event in eventsToPublish)
72 : PublishEvent(@event);
73 : }
74 :
75 0 : protected virtual void PublishEvent(IEvent<TAuthenticationToken> @event)
76 : {
77 : Publisher.Publish(@event);
78 : }
79 :
80 0 : public virtual TAggregateRoot Get<TAggregateRoot>(Guid aggregateId, IList<IEvent<TAuthenticationToken>> events = null)
81 : where TAggregateRoot : IAggregateRoot<TAuthenticationToken>
82 : {
83 : return LoadAggregate<TAggregateRoot>(aggregateId, events);
84 : }
85 :
86 0 : protected virtual TAggregateRoot CreateAggregate<TAggregateRoot>(Guid id)
87 : where TAggregateRoot : IAggregateRoot<TAuthenticationToken>
88 : {
89 : var aggregate = AggregateFactory.CreateAggregate<TAggregateRoot>(id);
90 :
91 : return aggregate;
92 : }
93 :
94 0 : protected virtual TAggregateRoot LoadAggregate<TAggregateRoot>(Guid id, IList<IEvent<TAuthenticationToken>> events = null)
95 : where TAggregateRoot : IAggregateRoot<TAuthenticationToken>
96 : {
97 : var aggregate = AggregateFactory.CreateAggregate<TAggregateRoot>(id);
98 :
99 : LoadAggregateHistory(aggregate, events);
100 : return aggregate;
101 : }
102 :
103 0 : public virtual void LoadAggregateHistory<TAggregateRoot>(TAggregateRoot aggregate, IList<IEvent<TAuthenticationToken>> events = null, bool throwExceptionOnNoEvents = true)
104 : where TAggregateRoot : IAggregateRoot<TAuthenticationToken>
105 : {
106 : IList<IEvent<TAuthenticationToken>> theseEvents = events ?? EventStore.Get<TAggregateRoot>(aggregate.Id).ToList();
107 : if (!theseEvents.Any())
108 : {
109 : if (throwExceptionOnNoEvents)
110 : throw new AggregateNotFoundException<TAggregateRoot, TAuthenticationToken>(aggregate.Id);
111 : return;
112 : }
113 :
114 : var duplicatedEvents =
115 : theseEvents.GroupBy(x => x.Version)
116 : .Select(x => new { Version = x.Key, Total = x.Count() })
117 : .FirstOrDefault(x => x.Total > 1);
118 : if (duplicatedEvents != null)
119 : throw new DuplicateEventException<TAggregateRoot, TAuthenticationToken>(aggregate.Id, duplicatedEvents.Version);
120 :
121 : aggregate.LoadFromHistory(theseEvents);
122 : }
123 : }
124 : }
|