PageRenderTime 11ms CodeModel.GetById 2ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/Bifrost/Events/EventSource.cs

#
C# | 167 lines | 102 code | 31 blank | 34 comment | 7 complexity | b43ac6fda56705cc6571b53b50937525 MD5 | raw file
  1#region License
  2//
  3// Copyright (c) 2008-2012, DoLittle Studios and Komplett ASA
  4//
  5// Licensed under the Microsoft Permissive License (Ms-PL), Version 1.1 (the "License")
  6// With one exception :
  7//   Commercial libraries that is based partly or fully on Bifrost and is sold commercially, 
  8//   must obtain a commercial license.
  9//
 10// You may not use this file except in compliance with the License.
 11// You may obtain a copy of the license at 
 12//
 13//   http://bifrost.codeplex.com/license
 14//
 15// Unless required by applicable law or agreed to in writing, software
 16// distributed under the License is distributed on an "AS IS" BASIS,
 17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 18// See the License for the specific language governing permissions and
 19// limitations under the License.
 20//
 21#endregion
 22using System;
 23using System.Linq.Expressions;
 24using Bifrost.Lifecycle;
 25
 26namespace Bifrost.Events
 27{
 28    /// <summary>
 29    /// Represents a <see cref="IEventSource">IEventSource</see>
 30    ///
 31    /// This is a base abstract class for any EventSource
 32    /// </summary>
 33    public abstract class EventSource : IEventSource, IUnitOfWork
 34    {
 35        /// <summary>
 36        /// Initializes an instance of <see cref="EventSource">EventSource</see>
 37        /// </summary>
 38        /// <param name="id">Id of the event source</param>
 39        protected EventSource(Guid id)
 40        {
 41            Id = id;
 42            UncommittedEvents = new UncommittedEventStream(id);
 43        }
 44
 45#pragma warning disable 1591 // Xml Comments
 46        public Guid Id { get; set; }
 47
 48        public EventSourceVersion Version { get; private set; }
 49
 50        public UncommittedEventStream UncommittedEvents { get; private set; }
 51
 52        public void Apply(IEvent @event)
 53        {
 54            Apply(@event, true);
 55        }
 56
 57        public void Apply(Expression<Action> expression)
 58        {
 59            var eventToApply = MethodEventFactory.CreateMethodEventFromExpression(Id, expression);
 60            Apply(eventToApply);
 61
 62        }
 63
 64        public virtual void ReApply(CommittedEventStream eventStream)
 65        {
 66            ValidateEventStream(eventStream);
 67
 68            foreach (var @event in eventStream)
 69                ReApply(@event);
 70
 71            Version = Version.NextCommit();
 72        }
 73
 74        public void FastForward(EventSourceVersion lastVersion)
 75        {
 76            ThrowIfStateful();
 77            ThrowIfNotInitialVersion();
 78
 79            Version = lastVersion.NextCommit();
 80        }
 81
 82        public virtual void Commit()
 83        {
 84            UncommittedEvents = new UncommittedEventStream(Id);
 85            Version = Version.NextCommit();
 86        }
 87
 88
 89        public virtual void Rollback()
 90        {
 91            UncommittedEvents = new UncommittedEventStream(Id);
 92            Version = Version.PreviousCommit();
 93        }
 94
 95		public void Dispose()
 96		{
 97			Commit();
 98		}
 99
100        
101
102#pragma warning restore 1591 // Xml Comments
103
104
105        /// <summary>
106        /// Get the aggregated root type
107        /// </summary>
108		protected virtual Type AggregatedRootType { get { return GetType(); } }
109
110        /// <summary>
111        /// Get the event source type
112        /// </summary>
113		protected virtual Type EventSourceType { get { return GetType(); } }
114
115
116        void ReApply(IEvent @event)
117        {
118            Apply(@event, false);
119        }
120
121        void Apply(IEvent @event, bool isNew)
122        {
123            if (isNew)
124            {
125                @event.AggregatedRoot = AggregatedRootType.AssemblyQualifiedName;
126            	@event.EventSourceName = EventSourceType.AssemblyQualifiedName;
127                UncommittedEvents.Append(@event);
128                Version = Version.NextSequence();
129                @event.Version = Version;
130            }
131            HandleInternally(@event);
132        }
133
134        void HandleInternally(IEvent @event)
135        {
136            var handleMethod = this.GetHandleMethod(@event);
137            if (handleMethod != null)
138                handleMethod.Invoke(this, new[] { @event });
139            Version = @event.Version;
140        }
141
142
143        void ValidateEventStream(EventStream eventStream)
144        {
145            if (!IsForThisEventSource(eventStream.EventSourceId))
146                throw new InvalidOperationException("Cannot apply an EventStream belonging to a different event source." +
147                    string.Format(@"Expected events for Id {0} but got events for Id {1}", Id, eventStream.EventSourceId));
148        }
149
150        bool IsForThisEventSource(Guid targetEventSourceId)
151        {
152            return targetEventSourceId == Id;
153        }
154
155        void ThrowIfStateful()
156        {
157            if (!this.IsStateless())
158                throw new InvalidFastForwardException(ExceptionStrings.CannotFastForwardStatefulEventSource);
159        }
160
161        void ThrowIfNotInitialVersion()
162        {
163            if (!Version.Equals(EventSourceVersion.Zero))
164                throw new InvalidFastForwardException(ExceptionStrings.CannotFastForwardEventSourceThatIsNotInitialVersion);
165        }
166    }
167}