ObjectLinkStorage.cs

143 lines | 4.627 kB Blame History Raw Download
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using ManagetLinkCollection.LinkStorage;
using ManagetLinkCollection.LinkStorage.Entities;

using ManagetLinkCollection.ObjectLinkStorage.Entities;

namespace ManagetLinkCollection.ObjectLinkStorage
{

    /// <summary>
    /// Хранилище ссылок на данные.
    /// Хранящее данные о множестве объектов, ссылающихся на запись.
    /// </summary>
    /// <typeparam name="TKey">Ключ</typeparam>
    /// <typeparam name="TData">Данные</typeparam>
    /// <typeparam name="TObject">Объект, ссылающийся на данные</typeparam>
    public class ObjectLinkStorage<TKey, TData, TObject>
        where TObject : class
    {

        #region

        public IReadOnlyDictionary<TKey, ILinkItem<TKey, ObjectLinkContainer<TData, TObject>>> Storage { private set; get; }

        private readonly LinkStorage<TKey, ObjectLinkContainer<TData, TObject>> _Storage
            = new LinkStorage<TKey, ObjectLinkContainer<TData, TObject>>();

        #endregion


        #region

        public ObjectLinkStorage()
        {
            Storage = _Storage.Storage;
        }

        #endregion


        #region

        /// <summary>
        /// Добавить ссылку на запись
        /// </summary>
        /// <param name="key">Ключ</param>
        /// <param name="value">Ссылающийся объект</param>
        /// <param name="addFactory">Фабрика создания данных записи</param>
        /// <param name="updateFactory">Фабрика обновления данных по ключу</param>
        public ILinkItem<TKey, ObjectLinkContainer<TData, TObject>> AddLink(
            TKey key,
            TObject value,
            Func<TKey, TData> addFactory,
            Func<ILinkItem<TKey, ObjectLinkContainer<TData, TObject>>, TData> updateFactory
            )
        {
            return _Storage.AddLink
                (
                key,
                (_key) =>
                    CreateBuilder()
                        .AddObject(value)
                        .UpdateData(addFactory != null ? addFactory(_key) : default(TData))
                        .Result(),
                (ILinkItem<TKey, ObjectLinkContainer<TData, TObject>> oldValue) =>
                    CreateBuilder(oldValue.Data)
                        .AddObject(value)
                        .UpdateData(updateFactory != null ? updateFactory(oldValue) : oldValue.Data.Data)
                        .Result()
                );
        }

        public ILinkItem<TKey, ObjectLinkContainer<TData, TObject>> AddLink(
            TKey key,
            TObject value,
            Func<TKey, TData> addFactory
            )
        {
            return AddLink(key, value, addFactory, null);
        }

        public ILinkItem<TKey, ObjectLinkContainer<TData, TObject>> AddLink(
            TKey key,
            TObject value,
            Func<ILinkItem<TKey, ObjectLinkContainer<TData, TObject>>, TData> updateFactory
            )
        {
            return AddLink(key, value, null, updateFactory);
        }

        public ILinkItem<TKey, ObjectLinkContainer<TData, TObject>> AddLink(
            TKey key,
            TObject value
            )
        {
            return AddLink(key, value, null, null);
        }


        public ILinkItem<TKey, ObjectLinkContainer<TData, TObject>> RemoveLink(
            TKey key,
            TObject value,
            Func<ILinkItem<TKey, ObjectLinkContainer<TData, TObject>>, TData> updateFactory
            )
        {
            return _Storage.RemoveLink(
                key,
                (ILinkItem<TKey, ObjectLinkContainer<TData, TObject>> oldValue) =>
                    new ContainerBuilder<TData, TObject>(oldValue.Data)
                        .RemoveObject(value)
                        .UpdateData(updateFactory != null ? updateFactory(oldValue) : oldValue.Data.Data)
                        .Result()
                );
        }

        public ILinkItem<TKey, ObjectLinkContainer<TData, TObject>> RemoveLink(
            TKey key,
            TObject value
            )
        {
            return RemoveLink(key, value, null);
        }

        #endregion



        private ContainerBuilder<TData, TObject> CreateBuilder(ObjectLinkContainer<TData, TObject> container = null) 
        {
            return
                container != null
                ? new ContainerBuilder<TData, TObject>(container)
                : new ContainerBuilder<TData, TObject>();                
        }

    }
}