/RapidRepository/RapidRepository/Context/RapidContext.cs
C# | 534 lines | 371 code | 104 blank | 59 comment | 46 complexity | 8f550d823380b26f11ed52a9856975bf MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using RapidRepository.Cache;
- using RapidRepository.Context;
- using RapidRepository.View;
- namespace RapidRepository
- {
- /// <summary>
- /// The RapidContext tracks usage of the repository and manages access to the document storage.
- /// </summary>
- public class RapidContext
- {
- #region Declarations
-
- static object syncRoot = new object();
- static RapidContext context = null;
- IFileManager fileManager;
- ISerialiser serialiser;
- List<OperationRequest> operationRequests = new List<OperationRequest>();
- internal static List<IRapidViewDataInternal> rapidViews = new List<IRapidViewDataInternal>();
- List<EntitiesLoaded> entitiesLoaded = new List<EntitiesLoaded>();
-
- private class RapidViewKey
- {
- public IRapidViewDataInternal RapidViewData { get; set; }
- public ViewKey ViewKey { get; set; }
- }
-
- #endregion
-
- #region Constructors
-
- /// <summary>
- /// Initializes a new instance of the <see cref="RapidContext"/> class.
- /// </summary>
- internal RapidContext() : this(new FileManager(), new Serialiser()) { }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="RapidContext"/> class.
- /// </summary>
- /// <param name="fileManager">The file manager.</param>
- /// <param name="serialiser">The serialiser.</param>
- internal RapidContext(IFileManager fileManager, ISerialiser serialiser)
- {
- Contract.Requires("fileManager", fileManager != null);
- Contract.Requires("serialiser", serialiser != null);
-
- this.fileManager = fileManager;
- this.serialiser = serialiser;
- }
-
- #endregion
-
- #region CurrentContext
-
- /// <summary>
- /// Gets the current context.
- /// </summary>
- /// <value>The current context.</value>
- public static RapidContext CurrentContext
- {
- get
- {
- if (context == null)
- {
- lock (syncRoot)
- {
- if (context == null)
- {
- context = new RapidContext();
- }
- }
- }
- return context;
- }
- }
-
- #endregion
-
- #region SaveChanges
-
- /// <summary>
- /// Saves the changes.
- /// </summary>
- public void SaveChanges()
- {
- List<ViewKey> rapidViews = new List<ViewKey>();
-
- foreach (OperationRequest request in this.operationRequests)
- {
- switch (request.OperationRequestType)
- {
- case OperationRequestType.Add:
- if (((IRapidEntity)request.Entity).Id == Guid.Empty)
- {
- ((IRapidEntity)request.Entity).Id = Guid.NewGuid();
- }
- var addString = this.serialiser.Serialise(request.EntityType, request.Entity);
- this.fileManager.Save(request.EntityType, ((IRapidEntity)request.Entity).Id, addString);
- AddToCache(request.EntityType, (IRapidEntity)request.Entity);
- AddToRapidViewsCollectionForSave(rapidViews, AddToView(request));
- break;
- case OperationRequestType.Update:
- var updateString = this.serialiser.Serialise(request.EntityType, request.Entity);
- this.fileManager.Save(request.EntityType, request.EntityId, updateString);
- EntityCache.Update(request.EntityType, request.EntityId, request.Entity);
- AddToRapidViewsCollectionForSave(rapidViews, UpdateToView(request));
- break;
- case OperationRequestType.Delete:
- this.fileManager.Delete(request.EntityType, request.EntityId);
- EntityCache.Remove(request.EntityType, request.EntityId);
- AddToRapidViewsCollectionForSave(rapidViews, DeleteToView(request));
- break;
- }
- }
-
- SaveViews(rapidViews);
-
- DeleteAllOperationRequests();
- }
-
- #endregion
-
- #region GetOperationRequests
-
- /// <summary>
- /// Gets the operation requests.
- /// </summary>
- /// <value>The operation requests.</value>
- public List<OperationRequest> OperationRequests
- {
- get
- {
- lock (syncRoot)
- {
- return this.operationRequests;
- }
- }
- }
-
- #endregion
-
- #region AddOperationRequest
-
- /// <summary>
- /// Adds the operation request.
- /// </summary>
- /// <param name="operationRequest">The operation request.</param>
- internal void AddOperationRequest(OperationRequest operationRequest)
- {
- Contract.Requires("operationRequest", operationRequest != null);
-
- this.operationRequests.Add(operationRequest);
- }
-
- #endregion
-
- #region DeleteOperationRequest
-
- /// <summary>
- /// Deletes the operation request.
- /// </summary>
- /// <param name="operationRequest">The operation request.</param>
- public void DeleteOperationRequest(OperationRequest operationRequest)
- {
- Contract.Requires("operationRequest", operationRequest != null);
-
- this.operationRequests.Remove(operationRequest);
- }
-
- #endregion
-
- #region DeleteAllOperationRequests
-
- /// <summary>
- /// Deletes all operation requests.
- /// </summary>
- public void DeleteAllOperationRequests()
- {
- this.operationRequests.Clear();
- }
-
- #endregion
-
- #region Exists
-
- /// <summary>
- /// Returns true if the entity exists.
- /// </summary>
- /// <typeparam name="TEntity">The type of the entity.</typeparam>
- /// <param name="id">The id.</param>
- internal bool Exists<TEntity>(Guid id)
- {
- Contract.Requires("id", id != Guid.Empty);
-
- var cachedEntity = EntityCache.GetById<TEntity>(id);
-
- if (cachedEntity != null)
- {
- return true;
- }
-
- return this.fileManager.Exists<TEntity>(id);
- }
-
- #endregion
-
- #region GetById
-
- /// <summary>
- /// Gets the entity by id.
- /// </summary>
- /// <typeparam name="TEntity">The type of the entity.</typeparam>
- /// <param name="id">The id.</param>
- internal TEntity GetById<TEntity>(Guid id)
- {
- Contract.Requires("id", id != Guid.Empty);
-
- var cachedEntity = EntityCache.GetById<TEntity>(id);
-
- if (cachedEntity != null)
- {
- return cachedEntity;
- }
-
- string fileContent = this.fileManager.GetFile<TEntity>(id);
-
- var entity = (IRapidEntity)this.serialiser.Deserialise<TEntity>(fileContent);
-
- AddToCache(typeof(TEntity), entity);
-
- return (TEntity)entity;
- }
-
- #endregion
-
- #region GetAll
-
- /// <summary>
- /// Gets a list of all entities of the specified type.
- /// </summary>
- /// <typeparam name="TEntity">The type of the entity.</typeparam>
- internal IList<TEntity> GetAll<TEntity>()
- {
- lock (syncRoot)
- {
- if (entitiesLoaded.Any(x => x.EntityType == typeof(TEntity)))
- {
- var cachedEntities = EntityCache.GetAll<TEntity>();
-
- if (cachedEntities != null && cachedEntities.Count > 0)
- {
- return cachedEntities;
- }
- }
- }
-
- string[] entityList = this.fileManager.LoadFiles<TEntity>();
-
- IList<TEntity> entities = new List<TEntity>();
-
- foreach (var entityContent in entityList)
- {
- var entity = this.serialiser.Deserialise<TEntity>(entityContent);
- entities.Add(entity);
-
- AddToCache(typeof(TEntity), (IRapidEntity)entity);
- }
-
- SetEntityLoaded<TEntity>();
-
- return entities;
- }
-
- internal void SetEntityLoaded<TEntity>()
- {
- lock (syncRoot)
- {
- entitiesLoaded.Add(new EntitiesLoaded { EntityType = typeof(TEntity) });
- }
- }
-
- #endregion
-
- #region AddView
-
- /// <summary>
- /// Adds a rapid view.
- /// </summary>
- /// <param name="view">The view.</param>
- internal static void AddRapidView(IRapidViewDataInternal view)
- {
- lock (syncRoot)
- {
- if (!rapidViews.Any(x => x.ViewType == view.ViewType))
- {
- rapidViews.Add(view);
- }
- }
- }
-
- #endregion
-
- #region SaveView
-
- private void SaveViews(List<ViewKey> viewsToSave)
- {
- foreach (ViewKey viewToSave in (List<ViewKey>)viewsToSave)
- {
- IRapidViewDataInternal rapidViewData = LoadRapidViewData(viewToSave);
-
- RapidViewKey rapidViewKey = new RapidViewKey
- {
- RapidViewData = rapidViewData,
- ViewKey = viewToSave
- };
-
- if (!rapidViewData.IsLoaded)
- {
- LoadView(rapidViewData.EntityType, rapidViewData.ViewType);
- }
- SaveView(rapidViewKey);
- }
- }
-
- private void SaveView(object rapidViewKey)
- {
- RapidViewKey rapidViewKeyData = (RapidViewKey)rapidViewKey;
-
- System.Collections.IList views = (System.Collections.IList)rapidViewKeyData.RapidViewData.LoadView();
-
- StringBuilder serialisedView = new StringBuilder();
-
- foreach (var view in views)
- {
- serialisedView.AppendLine(this.serialiser.Serialise(rapidViewKeyData.ViewKey.ViewType, view));
- }
-
- this.fileManager.SaveViewFile(rapidViewKeyData.ViewKey.ViewType, serialisedView.ToString());
-
- }
-
- #endregion
-
- #region LoadView
-
- /// <summary>
- /// Loads the view.
- /// </summary>
- /// <typeparam name="TView">The type of the view.</typeparam>
- internal List<TView> LoadView<TView>(Type entityType, Type viewType)
- {
- IRapidViewDataInternal rapidView = LoadRapidViewData(new ViewKey { EntityType = entityType, ViewType = viewType });
-
- if (!rapidView.IsLoaded)
- {
- var viewFile = this.fileManager.GetViewFile(viewType);
- if (viewFile == null)
- {
- return new List<TView>();
- }
-
- List<string> splitView = new List<string>(viewFile.Split(new string[] { Environment.NewLine }, new StringSplitOptions()));
-
- List<object> rapidViews = new List<object>();
-
- foreach (var item in splitView)
- {
- if (!string.IsNullOrEmpty(item))
- {
- rapidViews.Add((IRapidView)this.serialiser.Deserialise(viewType, item));
- }
- }
- rapidView.InsertView(rapidViews);
- rapidView.IsLoaded = true;
- }
-
- var views= rapidView.LoadView();
- List<TView> viewsToReturn = new List<TView>();
- foreach (var view in views)
- {
- viewsToReturn.Add((TView)view);
- }
- return viewsToReturn;
- }
-
- /// <summary>
- /// Loads the view.
- /// </summary>
- /// <typeparam name="TView">The type of the view.</typeparam>
- internal void LoadView(Type entityType, Type viewType)
- {
- IRapidViewDataInternal rapidView = LoadRapidViewData(new ViewKey { EntityType = entityType, ViewType = viewType });
-
- if (!rapidView.IsLoaded)
- {
- var viewFile = this.fileManager.GetViewFile(viewType);
- if (viewFile == null)
- {
- return;
- }
-
- List<string> splitView = new List<string>(viewFile.Split(new string[] { Environment.NewLine }, new StringSplitOptions()));
-
-
- List<object> rapidViews = new List<object>();
-
- foreach (var item in splitView)
- {
- if (!string.IsNullOrEmpty(item))
- {
- rapidViews.Add((IRapidView)this.serialiser.Deserialise(viewType, item));
- }
- }
- rapidView.InsertView(rapidViews);
- rapidView.IsLoaded = true;
- }
- }
-
- #endregion
-
- #region SynchroniseView
-
- internal static void SynchroniseView<TEntity, TView>()
- where TEntity : IRapidEntity
- where TView : IRapidView
- {
- IList<TEntity> entities = CurrentContext.GetAll<TEntity>();
- ViewKey viewKey = new ViewKey { EntityType = typeof(TEntity), ViewType = typeof(TView)};
- IRapidViewDataInternal rapidView = LoadRapidViewData(viewKey);
- RapidViewKey rapidViewKey = new RapidViewKey
- {
- ViewKey = viewKey,
- RapidViewData = rapidView
- };
-
- rapidView.InsertView(new List<object>());
- foreach (var entity in entities)
- {
- rapidView.Add(entity);
- }
- CurrentContext.SaveView(rapidViewKey);
- }
-
- #endregion
-
- #region Private Methods
-
- private static void AddToCache(Type entityType, IRapidEntity entity)
- {
- EntityCache.Add(entityType, ((IRapidEntity)entity).Id, entity);
- }
-
- private static IRapidViewDataInternal LoadRapidViewData(ViewKey viewKey)
- {
- var rapidView = rapidViews.Where(x => x.ViewType == viewKey.ViewType).FirstOrDefault();
- if (rapidView == null)
- {
- throw new InvalidOperationException(string.Format("The view type {0} has not been registered", viewKey.ViewType.FullName));
- }
- return rapidView;
- }
-
- private List<ViewKey> AddToView(OperationRequest request)
- {
- List<ViewKey> viewTypesForSaving = new List<ViewKey>();
- List<IRapidViewDataInternal> views = rapidViews.Where(x => x.EntityType == request.EntityType).ToList();
-
- foreach (var view in views)
- {
- if (!view.IsLoaded)
- {
- LoadView(view.EntityType, view.ViewType);
- }
- view.Add(request.Entity);
- viewTypesForSaving.Add(new ViewKey { EntityType = request.EntityType, ViewType = view.ViewType });
- }
-
- return viewTypesForSaving;
- }
-
- private List<ViewKey> UpdateToView(OperationRequest request)
- {
- List<ViewKey> viewTypesForSaving = new List<ViewKey>();
- List<IRapidViewDataInternal> views = rapidViews.Where(x => x.EntityType == request.EntityType).ToList();
-
- foreach (var view in views)
- {
- if (!view.IsLoaded)
- {
- LoadView(view.EntityType, view.ViewType);
- }
-
- view.Update(request.Entity);
- viewTypesForSaving.Add(new ViewKey { EntityType = request.EntityType, ViewType = view.ViewType });
- }
-
- return viewTypesForSaving;
- }
-
- private List<ViewKey> DeleteToView(OperationRequest request)
- {
- List<ViewKey> viewTypesForSaving = new List<ViewKey>();
- List<IRapidViewDataInternal> views = rapidViews.Where(x => x.EntityType == request.EntityType).ToList();
-
- foreach (var view in views)
- {
- if (!view.IsLoaded)
- {
- LoadView(view.EntityType, view.ViewType);
- }
- view.Delete(request.EntityId);
- viewTypesForSaving.Add(new ViewKey { EntityType = request.EntityType, ViewType = view.ViewType });
- }
-
- return viewTypesForSaving;
- }
-
- private static void AddToRapidViewsCollectionForSave(List<ViewKey> rapidViews, List<ViewKey> viewsToSave)
- {
- foreach (var viewKey in viewsToSave)
- {
- if (!rapidViews.Any(x => x.EntityType == viewKey.EntityType && x.ViewType == viewKey.ViewType))
- {
- rapidViews.Add(viewKey);
- }
- }
- }
-
- #endregion
- }
- }