PageRenderTime 18ms CodeModel.GetById 11ms app.highlight 5ms RepoModel.GetById 0ms app.codeStats 1ms

/Source/Bifrost/Sagas/SagaConverter.cs

#
C# | 167 lines | 113 code | 26 blank | 28 comment | 13 complexity | b089af8e34d4a17b5b8d7d53a163f9aa 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.Collections.Generic;
 24using System.Linq;
 25using Bifrost.Events;
 26using Bifrost.Execution;
 27using Bifrost.Serialization;
 28
 29namespace Bifrost.Sagas
 30{
 31    /// <summary>
 32    /// Represents a <see cref="ISagaConverter"/>
 33    /// </summary>
 34	public class SagaConverter : ISagaConverter
 35	{
 36		static readonly string[] SagaProperties = typeof(ISaga).GetProperties().Select(t => t.Name).ToArray();
 37
 38		static readonly SerializationOptions SerializationOptions =
 39			new SerializationOptions
 40				{
 41					ShouldSerializeProperty = (t, p) =>
 42					                          	{
 43					                          		if (typeof (ISaga).IsAssignableFrom(t))
 44					                          			return !SagaProperties.Any(sp => sp == p);
 45
 46					                          		return true;
 47					                          	}
 48				};
 49
 50		readonly IContainer _container;
 51		readonly IEventConverter _eventConverter;
 52		readonly ISerializer _serializer;
 53
 54        /// <summary>
 55        /// Initializes a new instance of <see cref="SagaConverter"/>
 56        /// </summary>
 57        /// <param name="container">A <see cref="IContainer"/> for creating instances of types</param>
 58        /// <param name="eventConverter">A <see cref="IEventConverter"/> for converting any <see cref="IEvent">events</see> in a <see cref="ISaga"/></param>
 59        /// <param name="serializer">A <see cref="ISerializer"/> to use for serialization</param>
 60		public SagaConverter(IContainer container, IEventConverter eventConverter, ISerializer serializer)
 61		{
 62			_container = container;
 63			_eventConverter = eventConverter;
 64			_serializer = serializer;
 65		}
 66
 67#pragma warning disable 1591 // Xml Commentsz
 68        public ISaga ToSaga(SagaHolder sagaHolder)
 69		{
 70			if (string.IsNullOrEmpty(sagaHolder.Type))
 71				return null;
 72
 73			var type = Type.GetType(sagaHolder.Type);
 74
 75			Type currentChapterType = null;
 76			if (!string.IsNullOrEmpty(sagaHolder.CurrentChapterType))
 77				currentChapterType = Type.GetType(sagaHolder.CurrentChapterType);
 78
 79			ISaga saga;
 80			if (string.IsNullOrEmpty(sagaHolder.SerializedSaga))
 81				saga = _container.Get(type) as ISaga;
 82			else
 83				saga = (ISaga) _serializer.FromJson(type,sagaHolder.SerializedSaga, SerializationOptions);
 84
 85			saga.Id = sagaHolder.Id;
 86			saga.Partition = sagaHolder.Partition;
 87			saga.Key = sagaHolder.Key;
 88		    saga.CurrentState = sagaHolder.State;
 89
 90			if (!string.IsNullOrEmpty(sagaHolder.UncommittedEvents))
 91			{
 92				var uncommittedEvents = new List<EventHolder>();
 93				_serializer.FromJson(uncommittedEvents,sagaHolder.UncommittedEvents);
 94				var actualEvents = _eventConverter.ToEvents(uncommittedEvents);
 95				saga.SetUncommittedEvents(actualEvents);
 96			}
 97
 98			DeserializeChapters(sagaHolder, saga, currentChapterType);
 99			
100
101			return saga;
102		}
103
104		public SagaHolder ToSagaHolder(ISaga saga)
105		{
106			var sagaHolder = new SagaHolder();
107			Populate(sagaHolder, saga);
108			return sagaHolder;
109		}
110
111		public void Populate(SagaHolder sagaHolder, ISaga saga)
112		{
113			sagaHolder.Id = saga.Id;
114			sagaHolder.Name = saga.GetType().Name;
115			sagaHolder.Type = saga.GetType().AssemblyQualifiedName;
116			sagaHolder.Key = saga.Key;
117			sagaHolder.Partition = saga.Partition;
118		    sagaHolder.State = saga.CurrentState.ToString();
119			sagaHolder.SerializedSaga = _serializer.ToJson(saga, SerializationOptions);
120			sagaHolder.UncommittedEvents = _serializer.ToJson(_eventConverter.ToEventHolders(saga.GetUncommittedEvents()));
121
122			var chapterHolders = (from c in saga.Chapters
123			                      select GetChapterHolderFromChapter(c)).ToArray();
124
125			sagaHolder.SerializedChapters = _serializer.ToJson(chapterHolders);
126
127			if (saga.CurrentChapter != null)
128				sagaHolder.CurrentChapterType = saga.CurrentChapter.GetType().AssemblyQualifiedName;
129		}
130#pragma warning restore 1591 // Xml Comments
131
132
133
134        ChapterHolder GetChapterHolderFromChapter(IChapter chapter)
135		{
136			var chapterHolder = new ChapterHolder
137			                    	{
138			                    		Type = chapter.GetType().AssemblyQualifiedName,
139			                    		SerializedChapter = _serializer.ToJson(chapter)
140			                    	};
141			return chapterHolder;
142		}
143
144		void DeserializeChapters(SagaHolder sagaHolder, ISaga saga, Type currentChapterType)
145		{
146			if (!string.IsNullOrEmpty(sagaHolder.SerializedChapters))
147			{
148				var chapterHolders = new List<ChapterHolder>();
149				_serializer.FromJson(chapterHolders,sagaHolder.SerializedChapters);
150				foreach (var chapterHolder in chapterHolders)
151				{
152					var chapterType = Type.GetType(chapterHolder.Type);
153					var chapter = _container.Get(chapterType) as IChapter;
154
155					if (!string.IsNullOrEmpty(chapterHolder.SerializedChapter))
156						_serializer.FromJson(chapter, chapterHolder.SerializedChapter);
157
158					saga.AddChapter(chapter);
159
160					if (currentChapterType != null &&
161						chapterType == currentChapterType)
162						saga.SetCurrentChapter(chapter);
163				}
164			}
165		}
166	}
167}