From 228e2e4ecaf0f5e2a2b1b9f67da7bebe0fd5aa0f Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Wed, 17 Dec 2025 14:44:55 +0330 Subject: [PATCH] Refactor Providing Mechanism ... --- Extensions/xFileServiceExtensions.cs | 14 +- Interfaces/IXBaseFileProvider.cs | 145 +---- Interfaces/IXFileProvider.cs | 4 + Models/Dtos/XFileDto.cs | 7 +- Providers/XBaseFileProvider.cs | 896 +++++++++++++++++---------- Providers/XFileProvider.cs | 67 +- 6 files changed, 635 insertions(+), 498 deletions(-) diff --git a/Extensions/xFileServiceExtensions.cs b/Extensions/xFileServiceExtensions.cs index 66e692c..ae054ca 100644 --- a/Extensions/xFileServiceExtensions.cs +++ b/Extensions/xFileServiceExtensions.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using xCommons.Extensions; +using xDataService.Extensions; using xFileService.Models.Dtos; using xFileService.Models.Entities; @@ -31,6 +32,14 @@ namespace xFileService.Extensions nameof(XFile.References), } ); + + + // + // Preparing List ... + if (!source.References.IsNullOrEmpty()) + { + result.References = source.References.ParseXReferenceList(); + } } // @@ -62,8 +71,9 @@ namespace xFileService.Extensions ); // - if (!source.References.IsNull() && source.References.HasChild()) { - result.References = source.References.ToListString(); + if (!source.References.IsNull() && source.References.HasChild()) + { + result.References = source.References.ToXReferenceString(); } } diff --git a/Interfaces/IXBaseFileProvider.cs b/Interfaces/IXBaseFileProvider.cs index a9dc680..e2343fc 100644 --- a/Interfaces/IXBaseFileProvider.cs +++ b/Interfaces/IXBaseFileProvider.cs @@ -1,45 +1,29 @@ using System; using System.Collections.Generic; -using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using xFileService.Models.Dtos; -using xFileService.Models.Entities; using xIdentityModels.Models; -using xModels.Dtos; +using xIdentityService.Interfaces; using XFileDto = xFileService.Models.Dtos.XFileDto; -// using xModels.Dtos; -using xTagService.Interfaces; - namespace xFileService.Interfaces { - public interface IXBaseFileProvider + /// + /// Implementing XBaseFileProvider ... + /// + /// + public interface IXBaseFileProvider : IXIdentityBaseReferencedProvider { // #region Props ... - /// - /// Specified Provider ... - /// - string ProvidedFor { get; } - /// /// Specified Provider Repositroy ... /// - IXFileProvider Provider { get; } + IXFileProvider FileProvider { get; } #endregion - // - #region Helper ... - /// - /// Get Specified Identifier ... - /// - /// - /// - string GetIdentifier(TKey forProvidedId); - #endregion - // #region Tools ... /// @@ -56,7 +40,6 @@ namespace xFileService.Interfaces /// Task Stream(string fileName); - /// /// Download Specified File ... /// @@ -76,14 +59,14 @@ namespace xFileService.Interfaces /// /// /// - /// /// + /// /// Task> Upload( TKey forProvidedId, IFormFileCollection files, - XUserClaimsInfoDto userInfo = null, - string connectionId = null + string connectionId = null, + XUserClaimsInfoDto userInfo = null ); /// @@ -91,14 +74,14 @@ namespace xFileService.Interfaces /// /// /// - /// /// + /// /// - Task> Remove( + Task> RemoveFile( TKey forProvidedId, string ids = null, - XUserClaimsInfoDto userInfo = null, - string connectionId = null + string connectionId = null, + XUserClaimsInfoDto userInfo = null ); /// @@ -115,105 +98,5 @@ namespace xFileService.Interfaces /// Task GetFileDescriptor(string fileName); #endregion - - // - #region Data Model ... - /// - /// Get Specified File Model ... - /// - /// - /// - Task Get( - Guid id - ); - - /// - /// Get All Exists File Models ... - /// - /// - /// - Task> GetAll(); - - /// - /// Get All Exists File Models ... - /// - /// - /// - Task> GetAllFor(TKey forProvidedId); - - /// - /// find an Entity by providing a Conditional Expression ... - /// - /// - Task FindOne(Expression> whereClause); - - /// - /// find a collection of Entities by proving a Conditional Expression ... - /// - /// - /// - Task> FindMany( - Expression> whereClause - ); - - /// - /// retrieve Entities based on XQuery Pagination structure ... - /// - /// - /// - Task> Query( - XQuery query - ); - - /// - /// retrieve Entities based on XQuery Pagination structure by providing a Conditional Expression ... - /// - /// - /// - /// - Task> ConditionalQuery( - Expression> whereClause, - XQuery query - ); - - /// - /// Update an Entity values ... - /// - /// - /// - /// - /// - Task Update( - Guid id, - XFileDto item, - XUserClaimsInfoDto userInfo = null - ); - - /// - /// remove an Entity ... - /// - /// - /// - /// - Task Remove( - Guid id, - XUserClaimsInfoDto userInfo = null - ); - - /// - /// count all exists Entities ... - /// - /// - Task Count(); - - /// - /// Check an Entity exists or not ... - /// - /// - /// - Task IsExists( - Guid id - ); - #endregion } } \ No newline at end of file diff --git a/Interfaces/IXFileProvider.cs b/Interfaces/IXFileProvider.cs index 6bf1bbf..82e2f8a 100644 --- a/Interfaces/IXFileProvider.cs +++ b/Interfaces/IXFileProvider.cs @@ -240,6 +240,7 @@ namespace xFileService.Interfaces /// /// /// + /// /// /// /// @@ -247,6 +248,7 @@ namespace xFileService.Interfaces string providedFor, TKey forProvidedId, Guid id, + int forIndex = 0, XUserClaimsInfoDto userInfo = null, string connectionId = null ); @@ -257,6 +259,7 @@ namespace xFileService.Interfaces /// /// /// + /// /// /// /// @@ -264,6 +267,7 @@ namespace xFileService.Interfaces string providedFor, TKey forProvidedId, Guid id, + int forIndex = 0, XUserClaimsInfoDto userInfo = null, string connectionId = null ); diff --git a/Models/Dtos/XFileDto.cs b/Models/Dtos/XFileDto.cs index 81fdbc0..322b8b0 100644 --- a/Models/Dtos/XFileDto.cs +++ b/Models/Dtos/XFileDto.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using xCommons.Constants; +using xDataService.Models; using xModels.Base; using xModels.Dtos; @@ -9,7 +10,7 @@ namespace xFileService.Models.Dtos public class XFileDto : XBaseDto { public Guid Id { get; set; } - + public XFileType Type { get; set; } public string Name { get; set; } public string Thumb { get; set; } @@ -20,7 +21,7 @@ namespace xFileService.Models.Dtos public string OwnerId { get; set; } public XPersonDto Owner { get; set; } - - public IList References = new List(); + + public IList> References = new List>(); } } \ No newline at end of file diff --git a/Providers/XBaseFileProvider.cs b/Providers/XBaseFileProvider.cs index 2b0e3ee..086d8be 100644 --- a/Providers/XBaseFileProvider.cs +++ b/Providers/XBaseFileProvider.cs @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using MongoDB.Driver.Core.Connections; using xCommons.Extensions; +using xDataService.Extensions; +using xDataService.Models; using xExceptions.Constants; using xFileService.Interfaces; using xFileService.Models.Dtos; @@ -22,43 +22,34 @@ namespace xFileService.Providers // #region Props ... /// - /// Specified Provider ... + /// Provider Identifier ... /// - public string ProvidedFor { get; } + public string Provider { get; } /// - /// Specified Provider Repositroy ... + /// Tag Provider for Maipulating Tags ... /// - public IXFileProvider Provider { get; } + public IXFileProvider FileProvider { get; } #endregion // #region Constructor ... public XBaseFileProvider( string providedFor, - IXFileProvider provider + IXFileProvider fileProvider ) { // - Provider = provider; - ProvidedFor = providedFor; + Provider = providedFor; + FileProvider = fileProvider; } #endregion // - #region Helper ... - /// - /// Get Specified Identifier ... - /// - /// - /// - public string GetIdentifier(TKey forProvidedId) + #region Identifier ... + public async Task LastIndex(TKey providedForId) { - // - return Provider.GetIdentifier( - providedFor: ProvidedFor, - forProvidedId: forProvidedId - ); + return await Task.FromResult(GetLastIndex(providedForId)); } #endregion @@ -80,7 +71,7 @@ namespace xFileService.Providers } // - var result = await Provider.Stream(id); + var result = await FileProvider.Stream(id); return result; } @@ -109,7 +100,7 @@ namespace xFileService.Providers } // - var result = await Provider.Stream(fileName); + var result = await FileProvider.Stream(fileName); return result; } @@ -129,7 +120,7 @@ namespace xFileService.Providers } // - var result = await Provider.Download(id); + var result = await FileProvider.Download(id); return result; } @@ -158,28 +149,28 @@ namespace xFileService.Providers } // - var result = await Provider.Download(fileName); + var result = await FileProvider.Download(fileName); return result; } /// /// Upload Files ... /// - /// + /// /// - /// /// + /// /// public async Task> Upload( - TKey forProvidedId, + TKey providedForId, IFormFileCollection files, - XUserClaimsInfoDto userInfo = null, - string connectionId = null + string connectionId = null, + XUserClaimsInfoDto userInfo = null ) { // // Validate ... - var isValid = !forProvidedId.IsNull(); + var isValid = !providedForId.IsNull(); if (!isValid) { XException.InvalidArgs.Throw(); @@ -187,7 +178,7 @@ namespace xFileService.Providers // // Here we are Following Custom Senario ... - var dtos = await Provider.Upload( + var dtos = await FileProvider.Upload( files: files, userInfo: userInfo, connectionId: connectionId @@ -199,14 +190,30 @@ namespace xFileService.Providers if (isValid) { // + // Preparing Index ... + int index = GetLastIndex(providedForId); + if (index > 0) + { + index++; + } + + // + var isReferenced = false; foreach (var dto in dtos) { // - await AddReference( - id: dto.Id, + // Try to Add Reference to Specified DTO ... + isReferenced = await AddReference( + model: dto, + forIndex: index, userInfo: userInfo, - forProvidedId: forProvidedId + connectionId: connectionId, + providedForId: providedForId ); + if (isReferenced) + { + index++; + } } } @@ -221,7 +228,7 @@ namespace xFileService.Providers foreach (var dto in dtos) { // - var idto = await Provider.Get(dto.Id); + var idto = await FileProvider.Get(dto.Id); isValid = !idto.IsNullOrDefault() && await IsOwned(idto.Id); if (isValid) @@ -238,62 +245,67 @@ namespace xFileService.Providers /// /// Remove Specified Files ... /// - /// + /// /// - /// /// + /// /// - public async Task> Remove( - TKey forProvidedId, + public async Task> RemoveFile( + TKey providedForId, string ids = null, - XUserClaimsInfoDto userInfo = null, - string connectionId = null + string connectionId = null, + XUserClaimsInfoDto userInfo = null ) { // // Validate ... - var isValid = userInfo.IsNullOrDefault(); - if (!isValid) + if (providedForId.IsNull()) { XException.InvalidArgs.Throw(); } // - // if ids Provided, Find all id's Specified Dtos ... - // if not, gell all models which Owned and has Reference to forProvidedId ... - var dtos = await GetAll(); - if (!forProvidedId.IsNull()) - { - // - var identifier = GetIdentifier(forProvidedId); - dtos = dtos - .Where(e => e.References.Any(er => er.ToNormalString() == identifier.ToNormalString())); - } - - // - // Filter Provided IDS ... + // Parse Provided IDS ... + var idsList = new List(); + IEnumerable entities = null; if (!ids.IsNullOrEmpty()) { // - var idsList = ids.ParseListGuid(); - dtos = dtos.Where(d => !idsList.Contains(d.Id)); + idsList = ids + .ParseListGuid() + .ToList(); + } + // + // Retrieve Entities ... + entities = FileProvider.FileRepository + .AsQueryable() + .Where(d => !idsList.Contains(d.Id) && + d.References.Contains(Provider)); + // var result = new List(); - isValid = !dtos.IsNullOrDefault() && dtos.HasChild(); + var isValid = !entities.IsNull() && entities.HasChild(); if (isValid) { // - foreach (var dto in dtos) + foreach (var entity in entities) { // - var dtoIds = new List { dto.Id.ToString() }.ToListString(); - var removeIds = await Provider.Remove(dtoIds, userInfo, connectionId); - isValid = !removeIds.IsNull() && removeIds.HasChild() && removeIds.Contains(dto.Id); + // Remove File ... + var idsToRemove = new List { entity.Id.ToString() }.ToListString(); + var removeIds = await FileProvider.Remove( + ids: idsToRemove, + userInfo: userInfo, + connectionId: connectionId + ); + isValid = !removeIds.IsNull() && + removeIds.HasChild() && + removeIds.Contains(entity.Id); if (isValid) { - result.Add(dto.Id); + result.Add(entity.Id); } } } @@ -326,7 +338,7 @@ namespace xFileService.Providers } // - var result = await Provider.GetFileDescriptor(id); + var result = await FileProvider.GetFileDescriptor(id); return result; } @@ -355,274 +367,585 @@ namespace xFileService.Providers } // - var result = await Provider.GetFileDescriptor(fileName); + var result = await FileProvider.GetFileDescriptor(fileName); return result; } #endregion // - #region Data Model ... + #region Referenced Actions ... /// - /// Get Specified File Model ... + /// Get Specified Indexed Reference for Specific Provided ID ... /// - /// + /// + /// /// - public async Task Get( - Guid id + public async Task GetReference( + TKey providedForId, + int forIndex = 0 ) { // // Validate ... - var isValid = !id.IsNull() && !id.IsDefaultGuid(); - if (!isValid) + if (providedForId.IsNull()) { XException.InvalidArgs.Throw(); } // - // Check Owned ... - isValid = await IsOwned(id); - if (!isValid) + // Normalize ... + if (forIndex < 0) { - XException.NotAllowed.Throw(); + forIndex = 0; } // - var result = await Provider.Get(id); - return result; - } - - /// - /// Get All Exists File Models ... - /// - /// - public async Task> GetAll() - { - // - var result = await Provider - .FindMany(e => e.References.ToNormalString().Contains(ProvidedFor.ToNormalString())); - return result; - } - - /// - /// Get All Exists File Models ... - /// - /// - /// - public async Task> GetAllFor(TKey forProvidedId) - { - // - // Validate ... - if (forProvidedId.IsNull()) + // Retrieve Last Index ... + var lastIndex = GetLastIndex(providedForId); + if (forIndex > lastIndex) { - XException.InvalidArgs.Throw(); + XException.NotFound.Throw(); } // - var identifier = GetIdentifier(forProvidedId); - var result = await Provider - .FindMany(e => e.References.ToNormalString().Contains(identifier.ToNormalString())); - return result; - } - - /// - /// find an Entity by providing a Conditional Expression ... - /// - /// - public async Task FindOne(Expression> whereClause) - { - // - // Validate ... - if (whereClause.IsNull()) - { - XException.InvalidArgs.Throw(); - } - - // - var whereFunc = whereClause.Compile(); - var result = await Provider - .FindOne(e => whereFunc(e) && e.References.ToNormalString().Contains(ProvidedFor.ToNormalString())); - return result; - } - - /// - /// find a collection of Entities by proving a Conditional Expression ... - /// - /// - /// - public async Task> FindMany( - Expression> whereClause - ) - { - // - // Validate ... - if (whereClause.IsNull()) - { - XException.InvalidArgs.Throw(); - } - - // - var whereFunc = whereClause.Compile(); - var result = await Provider - .FindMany(e => whereFunc(e) && e.References.ToNormalString().Contains(ProvidedFor.ToNormalString())); - return result; - } - - /// - /// retrieve Entities based on XQuery Pagination structure ... - /// - /// - /// - public async Task> Query( - XQuery query - ) - { - // - // Define Owning Conditions ... - Expression> whereClause = e => e.References - .ToNormalString() - .Contains(ProvidedFor.ToNormalString()); - - // - var result = await Provider.ConditionalQuery( - query: query, - whereClause: whereClause + var indexedIdentifier = GetIndexedProvidedID( + forIndex: forIndex, + providedForId: providedForId ); + var entity = FileProvider.FileRepository + .AsQueryable() + .Where(t => t.References.Contains(indexedIdentifier)) + .FirstOrDefault(); + if (entity.IsNullOrDefault()) + { + XException.NotFound.Throw(); + } + + // + var result = await FileProvider.ToDto(entity); return result; } /// - /// retrieve Entities based on XQuery Pagination structure by providing a Conditional Expression ... + /// Retrieve all Exists References of Specific Provided ID ... /// - /// - /// + /// /// - public async Task> ConditionalQuery( - Expression> whereClause, - XQuery query - ) + public async Task> GetAllReferences(TKey providedForId) { // // Validate ... - if (whereClause.IsNull()) + if (providedForId.IsNull()) { XException.InvalidArgs.Throw(); } // - // Prepare a Combination Where Condition ... - var whereFunc = whereClause.Compile(); - Expression> condition = e => whereFunc(e) && - e.References.ToNormalString().Contains(ProvidedFor.ToNormalString()); + var identifier = GetProvidedID(providedForId); + var entities = FileProvider.FileRepository + .AsQueryable() + .Where(t => t.References.Contains(identifier)) + .AsEnumerable(); + + // + var dtos = new List(); + foreach (var entity in entities) + { + // + var dto = await FileProvider.ToDto(entity); + if (!dto.IsNullOrDefault()) + { + dtos.Add(dto); + } + } + + // + List result = dtos; + if (dtos.HasChild()) + { + // + // Sorting Result Based on Indexes ... + var lastIndex = GetLastIndex(providedForId); + if (lastIndex > 0) + { + // + result.Clear(); + for (int i = 0; i <= lastIndex; i++) + { + // + var dto = dtos + .FirstOrDefault(d => d.References + .Any(dr => dr.Index == i && dr.ReferencedTo == $"{providedForId}")); + if (!dto.IsNullOrDefault()) + { + result.Add(dto); + } + } + } + } + + // + return await Task.FromResult(result); + } + + /// + /// Retrieve References of Specific Provided ID as Query ... + /// + /// + /// + public async Task> QueryReferences( + XQuery query, + TKey providedForId + ) + { + // + // Validate ... + if (query.IsNull() || providedForId.IsNull()) + { + XException.InvalidArgs.Throw(); + } + + // + // Normalize ... + query = query.NormalizeQuery(FileProvider.DataSercviceConfiguration); + + // + var items = await GetAllReferences(providedForId); + var totalItemsCount = items.Count(); + + // + // Apply Filter ... + if (!query.Filter.IsNullOrEmpty()) + { + // + items = items + .ApplyFilter(query.Filter); + } + int filteredItemsCount = items.Count(); + + // + // Count Pages ... + var totalPagesCount = query.CountPages(totalItemsCount); + var filteredPagesCount = query.CountPages(filteredItemsCount); + + // + // Apply Paging and Sorting ... + if (totalItemsCount > 0 && + filteredItemsCount > 0) + { + // + // Apply Sorting ... + items = items + .ToList() + .ApplySorting( + query.SortBy, + query.IsAscending + ); + + // + // Apply Paging ... + items = items + .ToList() + .ApplyPaging( + query.Page, + query.PageSize + ); + } + + // + // Prepare Result ... + var result = new XQueryResult + { + Page = query.Page, + Items = items.ToList(), + PageSize = query.PageSize, + TotalPages = totalPagesCount, + TotalItems = totalItemsCount, + TotalFilteredPages = filteredPagesCount, + TotalFilteredItems = filteredItemsCount + }; // - var result = await Provider.ConditionalQuery( - query: query, - whereClause: condition - ); return result; } /// - /// Update an Entity values ... + /// Add Reference a Model to Specific Provided ID ... /// - /// - /// + /// + /// + /// + /// /// /// - public async Task Update( - Guid id, - XFileDto item, + public async Task AddReference( + XFileDto model, + TKey providedForId, + int forIndex = 0, + string connectionId = null, + XUserClaimsInfoDto userInfo = null + ) + { + // + var result = false; + + // + // Validate ... + var isValid = !model.IsNullOrDefault() && + !model.Name.IsNullOrEmpty() && + !model.Id.IsNull() && + !model.Id.IsDefaultGuid() && + !providedForId.IsNull(); + if (!isValid) + { + XException.InvalidArgs.Throw(); + } + + // + // Check Model Exists ... + isValid = await FileProvider.IsExists(model.Id); + if (!isValid) + { + XException.NotFound.Throw(); + } + + // + // Update Model by Retrieving ... + model = await FileProvider.Get(model.Id); + + // + var lastIndex = GetLastIndex(providedForId); + if (lastIndex == 0) + { + // + // This Means there isnot any Reference ... + forIndex = 0; + model.References.Add(new XReference + { + Index = forIndex, + ProvidedFor = Provider, + ReferencedTo = $"{providedForId}" + }); + } + else + { + // + // Check Provided Index Exists or not ... + var isExists = model.References.Any(r => r.Index == forIndex); + if (!isExists) + { + // + // Normalize For Index ... + if (forIndex > lastIndex + 1) + { + forIndex = lastIndex + 1; + } + + // + // Add New Reference ... + model.References.Add(new XReference + { + Index = forIndex, + ProvidedFor = Provider, + ReferencedTo = $"{providedForId}" + }); + } + else + { + } + } + + // + // Update Data Base ... + model = await FileProvider + .Update( + item: model, + id: model.Id, + userInfo: userInfo, + connectionId: connectionId + ); + result = !model.IsNullOrDefault(); + + // + return result; + } + + /// + /// Add Reference a Model to Specific XRefence ... + /// + /// + /// + /// + /// + /// + public async Task AddReference( + XFileDto model, + XReference reference, + string connectionId = null, XUserClaimsInfoDto userInfo = null ) { // // Validate ... - var isValid = - !id.IsNull() && - !id.IsDefaultGuid() && - !item.IsNullOrDefault() && - !userInfo.IsNullOrDefault(); - if (!isValid) + // Since other Validations Handled in Calling, we Ignore them here ... + if (model.IsNull() || + reference.IsNullOrDefault() || + (!reference.ProvidedFor.IsNullOrEmpty() && reference.ProvidedFor != Provider)) { XException.InvalidArgs.Throw(); } // - // Validate Own ... - isValid = await IsOwned(item.Id); - if (!isValid) - { - XException.NotAllowed.Throw(); - } + var result = await AddReference( + model: model, + userInfo: userInfo, + connectionId: connectionId, + providedForId: reference.ReferencedTo + ); // - var result = await Provider.Update(item.Id, item, userInfo); return result; } /// - /// remove an Entity ... + /// Remove Reference a Model for Specific Provided ID ... /// - /// + /// + /// + /// if null, removes all + /// /// /// - public async Task Remove( - Guid id, + public async Task RemoveReference( + XFileDto model, + TKey providedForId, + int? forIndex = null, + string connectionId = null, XUserClaimsInfoDto userInfo = null ) { // // Validate ... - var isValid = !id.IsNull() && - !id.IsDefaultGuid() && - !userInfo.IsNullOrDefault(); - if (!isValid) + if (model.IsNull() || + providedForId.IsNull() || + model.Id.IsNull() || + model.Id.IsDefaultGuid()) { XException.InvalidArgs.Throw(); } // - // Validate Owned ... - isValid = await IsOwned(id); - if (!isValid) + // Retrieve Model ... + model = await FileProvider.Get(model.Id); + if (model.IsNullOrDefault()) { - XException.NotAllowed.Throw(); + XException.NotFound.Throw(); } // - var result = await Provider.Remove(id, userInfo); - return result; - } + // Check Model Reference to ID ... + var isReferenced = model.References + .Any(r => r.ProvidedFor == Provider && + r.ReferencedTo == $"{providedForId}" && + (!forIndex.HasValue || r.Index == forIndex.Value)); + + // + var result = false; + if (isReferenced) + { + // + model.References = model.References + .Where(r => r.ProvidedFor != Provider || + (r.ProvidedFor == Provider && + r.ReferencedTo != $"{providedForId}" && + (!forIndex.HasValue || r.Index == forIndex.Value))) + .ToList(); + + // + model = await FileProvider.Update( + item: model, + id: model.Id, + userInfo: userInfo, + connectionId: connectionId + ); + result = !model.IsNullOrDefault(); + } - /// - /// count all exists Entities ... - /// - /// - public async Task Count() - { // - var result = (await GetAll()).Count(); return result; } /// - /// Check an Entity exists or not ... + /// Remove Reference a Model for Specific XRefence ... /// - /// + /// + /// + /// + /// /// - public async Task IsExists( - Guid id + public async Task RemoveReference( + XFileDto model, + XReference reference, + string connectionId = null, + XUserClaimsInfoDto userInfo = null ) { // - var result = await IsOwned(id); + if (model.IsNullOrDefault() || + reference.IsNullOrDefault() || + reference.ReferencedTo.IsNull() || + reference.ProvidedFor != Provider) + { + XException.InvalidArgs.Throw(); + } + + // + var result = await RemoveReference( + model: model, + userInfo: userInfo, + forIndex: reference.Index, + connectionId: connectionId, + providedForId: reference.ReferencedTo + ); + + // + return result; + } + + /// + /// Remove All References to Specified Key ... + /// + /// + /// + /// + /// + public async Task RemoveReferences( + TKey providedForId, + string connectionId = null, + XUserClaimsInfoDto userInfo = null + ) + { + // + // Validate ... + if (providedForId.IsNull()) + { + XException.InvalidArgs.Throw(); + } + + // + var result = false; + var references = await GetAllReferences(providedForId); + if (!references.IsNull() && references.HasChild()) + { + // + foreach (var reference in references) + { + // + // Remove Reference ... + reference.References = reference.References + .Where(r => + r.ProvidedFor != Provider || + (r.ProvidedFor == Provider && + r.ReferencedTo != $"{providedForId}")) + .ToList(); + var updatedModel = await FileProvider.Update( + item: reference, + id: reference.Id, + userInfo: userInfo, + connectionId: connectionId + ); + if (!updatedModel.IsNullOrDefault()) + { + result = true; + } + } + } + + // return result; } #endregion // #region Private ... + private string GetProvidedID( + TKey providedForId, + char splitter = '_' + ) + { + // + // Validate ... + if (providedForId.IsNull()) + { + XException.InvalidArgs.Throw(); + } + + // + var result = $"{Provider}{splitter}{providedForId}"; + return result; + } + + private string GetIndexedProvidedID( + TKey providedForId, + int forIndex, + char splitter = '_' + ) + { + // + var result = $"{GetProvidedID(providedForId, splitter)}{splitter}{providedForId}"; + + // + return result; + } + + private int GetLastIndex(TKey providedForId) + { + // + var result = 0; + + // + // Validate ... + var isValid = !providedForId.IsNull(); + if (!isValid) + { + XException.InvalidArgs.Throw(); + } + + // + var identifier = GetProvidedID(providedForId); + + // + var all = FileProvider.FileRepository + .AsQueryable() + .Where(t => t.References + .Contains(identifier)) + .Select(t => t.References) + .AsEnumerable(); + if (all.IsNull() || !all.HasChild()) + { + result = 0; + } + else + { + // + var references = all + .SelectMany(a => a.ParseXReferenceList()) + .OrderByDescending(r => r.Index) + .ToList(); + if (!references.IsNull() && references.HasChild()) + { + result = references[0].Index; + } + else + { + result = 0; + } + } + + // + return result; + } + /// /// Check Specified Dto is Has Reference to Provider ... /// @@ -640,7 +963,7 @@ namespace xFileService.Providers // // Check Exists ... - result = await Provider.IsExists(id); + result = await FileProvider.IsExists(id); if (!result) { XException.NotFound.Throw(); @@ -648,7 +971,7 @@ namespace xFileService.Providers // // Retrieve Dto ... - var dto = await Provider.Get(id); + var dto = await FileProvider.Get(id); result = !dto.IsNullOrDefault(); if (!result) { @@ -658,7 +981,7 @@ namespace xFileService.Providers // result = !dto.References.IsNull() && dto.References.HasChild() && - dto.References.Any(r => r.ToNormalString().Contains(ProvidedFor.ToNormalString())); + dto.References.Any(r => r.ProvidedFor == Provider); // return result; @@ -681,7 +1004,7 @@ namespace xFileService.Providers try { // - result = await Provider.FindOne(d => + result = await FileProvider.FindOne(d => d.Name == fileName || d.Thumb == fileName || d.FileName == fileName || @@ -705,101 +1028,6 @@ namespace xFileService.Providers // return result; } - - /// - /// Get Specified Provided ID's Related Files ... - /// - /// - /// - private async Task> GetDtos(TKey forProvidedId) - { - // - var result = new List(); - - // - var identifier = GetIdentifier(forProvidedId); - if (!forProvidedId.IsNull()) - { - // - result = (await Provider - .FindMany(e => e.References.ToNormalString().Contains(identifier.ToNormalString()))) - .ToList(); - } - - // - return result; - } - - /// - /// Check Specified File has Refernce to Provider ... - /// - /// - /// - /// - private async Task IsProvidedFor( - TKey forProvidedId, - Guid id - ) - { - // - var result = await Provider.IsProvidedFor( - id: id, - providedFor: ProvidedFor, - forProvidedId: forProvidedId - ); - - // - return result; - } - - /// - /// Add Specified Reference to Specified File ... - /// - /// - /// - /// - /// - /// - private async Task AddReference( - TKey forProvidedId, - Guid id, - XUserClaimsInfoDto userInfo = null, - string connectionId = null - ) - { - // - await Provider.AddReference( - id: id, - userInfo: userInfo, - providedFor: ProvidedFor, - connectionId: connectionId, - forProvidedId: forProvidedId - ); - } - - /// - /// Remove Specified Reference from Specified File ... - /// - /// - /// - /// - /// - private async Task RemoveReference( - TKey forProvidedId, - Guid id, - XUserClaimsInfoDto userInfo = null, - string connectionId = null - ) - { - // - await Provider.RemoveReference( - id: id, - userInfo: userInfo, - providedFor: ProvidedFor, - connectionId: connectionId, - forProvidedId: forProvidedId - ); - } #endregion } } \ No newline at end of file diff --git a/Providers/XFileProvider.cs b/Providers/XFileProvider.cs index f210999..b36cc01 100644 --- a/Providers/XFileProvider.cs +++ b/Providers/XFileProvider.cs @@ -25,6 +25,7 @@ using Microsoft.Extensions.FileProviders; using Microsoft.AspNetCore.StaticFiles; using System.Linq; using xPushService.Constants; +using xDataService.Models; namespace xFileService.Providers { @@ -251,10 +252,10 @@ namespace xFileService.Providers try { // - await TagProvider.Attach( - tag, - id, - connectionId + await TagProvider.AddReference( + tag: tag, + providedForId: id, + connectionId: connectionId ); } catch { } @@ -298,10 +299,10 @@ namespace xFileService.Providers try { // - await TagProvider.Detach( - tag, - id, - connectionId + await TagProvider.RemoveReference( + tag: tag, + providedForId: id, + connectionId: connectionId ); } catch { } @@ -447,7 +448,10 @@ namespace xFileService.Providers try { // - var tags = await TagProvider.RemoveTagsFor(id); + await TagProvider.RemoveReferences( + providedForId: id, + connectionId: connectionId + ); } catch { } } @@ -464,7 +468,7 @@ namespace xFileService.Providers // Validate ... var isValid = !id.IsNull() && !id.IsDefaultGuid(); - if (!isValid) + if (!isValid) { XException.InvalidArgs.Throw(); } @@ -478,7 +482,7 @@ namespace xFileService.Providers } // - var tags = await TagProvider.GetTags(id); + var tags = await TagProvider.GetAllReferences(id); // var result = new List(); @@ -492,7 +496,7 @@ namespace xFileService.Providers // return result; - } + } #endregion // @@ -847,8 +851,8 @@ namespace xFileService.Providers // Here we send Null Connection ID for Preventing Update Push ... // since we Remove Entity ... await DetachTags( - id: id, - userInfo: userInfo, + id: id, + userInfo: userInfo, connectionId: null ); } @@ -1076,14 +1080,11 @@ namespace xFileService.Providers } // - var identifier = GetIdentifier( - providedFor: providedFor, - forProvidedId: forProvidedId - ); var result = dto.References.IsNull() && dto.References.HasChild() && - dto.References.Any(r => r.ToNormalString() == identifier.ToNormalString()); + dto.References.Any(r => r.ProvidedFor == providedFor && + r.ReferencedTo == $"{forProvidedId}"); // return result; @@ -1095,6 +1096,7 @@ namespace xFileService.Providers /// /// /// + /// /// /// /// @@ -1102,6 +1104,7 @@ namespace xFileService.Providers string providedFor, TKey forProvidedId, Guid id, + int forIndex = 0, XUserClaimsInfoDto userInfo = null, string connectionId = null ) @@ -1148,16 +1151,18 @@ namespace xFileService.Providers } // - var identifier = GetIdentifier( - providedFor: providedFor, - forProvidedId: forProvidedId - ); - dto.References.Add(identifier); + var reference = new XReference + { + Index = forIndex, + ProvidedFor = providedFor, + ReferencedTo = $"{forProvidedId}" + }; + dto.References.Add(reference); // dto = await Update( - id: dto.Id, item: dto, + id: dto.Id, userInfo: userInfo, connectionId: connectionId ); @@ -1175,6 +1180,7 @@ namespace xFileService.Providers /// /// /// + /// /// /// /// @@ -1182,6 +1188,7 @@ namespace xFileService.Providers string providedFor, TKey forProvidedId, Guid id, + int forIndex = 0, XUserClaimsInfoDto userInfo = null, string connectionId = null ) @@ -1234,11 +1241,15 @@ namespace xFileService.Providers forProvidedId: forProvidedId ); dto.References = dto.References - .Where(r => r.ToNormalString() != identifier.ToNormalString()) + .Where(r => + r.Index != forIndex && + r.ProvidedFor != providedFor && + r.ReferencedTo != $"{forProvidedId}" + ) .ToList(); dto = await Update( - id: dto.Id, item: dto, + id: dto.Id, userInfo: userInfo, connectionId: connectionId ); @@ -1642,7 +1653,7 @@ namespace xFileService.Providers // // Removing Tags ... - await TagProvider.RemoveTagsFor(result.Id); + await TagProvider.RemoveReferences(result.Id); // await SendPush(