diff --git a/DI/XDIHelperExtension.cs b/DI/XDIHelperExtension.cs
index 8e561d0..965c7f5 100644
--- a/DI/XDIHelperExtension.cs
+++ b/DI/XDIHelperExtension.cs
@@ -1,3 +1,83 @@
-namespace xStringService.DI {
- public static class XDIHelperExtension { }
+using System;
+using Microsoft.Extensions.DependencyInjection;
+using xExceptions.Constants;
+using xCommons.Extensions;
+using xStringService.Interfaces;
+using xStringService.Providers;
+
+namespace xStringService.DI
+{
+ public static class XDIHelperExtension
+ {
+ ///
+ /// Register Module Provided Service on DI
+ ///
+ ///
+ ///
+ public static void AddXStringService(
+ this IServiceCollection services,
+ ServiceLifetime lifeTime
+ )
+ {
+ AddStringService(
+ services,
+ lifeTime
+ );
+ }
+
+ //
+ #region Private ...
+ ///
+ /// a LogTag for XStringService ...
+ ///
+ private static string XLogTag = "XStringService";
+
+ ///
+ /// print a log in Console ...
+ ///
+ ///
+ private static void Log(string message)
+ {
+ Console.WriteLine($"{XLogTag} => {message}");
+ }
+
+ ///
+ /// Register Push Service ...
+ ///
+ ///
+ ///
+ private static void AddStringService(
+ IServiceCollection services,
+ ServiceLifetime lifeTime
+ )
+ {
+ //
+ var exception = XException.InvalidArgs.ToException(); ;
+
+ //
+ // Services ...
+ var isServicesExists = !services.IsNull();
+ if (!isServicesExists)
+ {
+ //
+ Log("AddStringService failed, services not provided ...");
+ throw exception;
+ }
+
+ //
+ // Lifetime ...
+ var isLifetimeExists = !lifeTime.IsNull();
+ if (!isLifetimeExists)
+ {
+ //
+ Log("AddStringService failed, lifetime not provided ...");
+ throw exception;
+ }
+
+ //
+ services.Add(new ServiceDescriptor(typeof(IXStringProvider), typeof(XStringProvider), lifeTime));
+ Log("AddStringService Succeed ...");
+ }
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/DataHelper/Events/XStringEvents.cs b/DataHelper/Events/XStringEvents.cs
new file mode 100644
index 0000000..a56db2c
--- /dev/null
+++ b/DataHelper/Events/XStringEvents.cs
@@ -0,0 +1,9 @@
+using xDataService.Events;
+using xStringService.Interfaces.Entities;
+using xStringService.Models.Entities;
+
+namespace xStringService.DataHelper.Events
+{
+ public class XStringEvents : XBaseRepositoryEvents, IXStringEvents
+ {}
+}
\ No newline at end of file
diff --git a/DataHelper/GraphQL/XStringGraphQLTypeHelper.cs b/DataHelper/GraphQL/XStringGraphQLTypeHelper.cs
new file mode 100644
index 0000000..3ede619
--- /dev/null
+++ b/DataHelper/GraphQL/XStringGraphQLTypeHelper.cs
@@ -0,0 +1,25 @@
+using xDataService.Configuration;
+using xDataService.GraphQL;
+using xStringService.Interfaces.Entities;
+using xStringService.Models.Entities;
+
+namespace xStringService.DataHelper.GraphQL
+{
+ public class XStringGraphQLTypeHelper : XBaseGraphQLTypeHelper, IXStringGraphQLTypeHelper
+ {
+ public XStringGraphQLTypeHelper(
+ XDataServiceConfiguration configuration
+ ) : base(configuration)
+ { }
+
+ public override string GetInQueryCollectionName()
+ {
+ return "strings";
+ }
+
+ public override string GetInQuerySingleName()
+ {
+ return "string";
+ }
+ }
+}
\ No newline at end of file
diff --git a/DataHelper/GraphQL/XStringGraphQuery.cs b/DataHelper/GraphQL/XStringGraphQuery.cs
new file mode 100644
index 0000000..fb6a1ba
--- /dev/null
+++ b/DataHelper/GraphQL/XStringGraphQuery.cs
@@ -0,0 +1,22 @@
+using GraphQL.Types;
+using xDataService.Configuration;
+using xDataService.GraphQL;
+using xStringService.Interfaces.Entities;
+using xStringService.Models.Entities;
+
+namespace xDataHelper.GraphQL
+{
+ public class XStringGraphQuery : XBaseGraphQLQuery
+ {
+ public XStringGraphQuery(
+ XDataServiceConfiguration configuration,
+ IXStringRepository repository,
+ IXStringGraphQLTypeHelper helper
+ ) : base(
+ configuration,
+ repository,
+ helper
+ )
+ { }
+ }
+}
\ No newline at end of file
diff --git a/DataHelper/GraphQL/XStringGraphSchema.cs b/DataHelper/GraphQL/XStringGraphSchema.cs
new file mode 100644
index 0000000..f28d89e
--- /dev/null
+++ b/DataHelper/GraphQL/XStringGraphSchema.cs
@@ -0,0 +1,13 @@
+using System;
+using GraphQL.Types;
+
+namespace xDataHelper.GraphQL
+{
+ public class XStringGraphSchema : Schema
+ {
+ public XStringGraphSchema(IServiceProvider services) : base(services)
+ {
+ Query = (XStringGraphQuery)services.GetService(typeof(XStringGraphQuery));
+ }
+ }
+}
\ No newline at end of file
diff --git a/DataHelper/GraphQL/XStringGraphType.cs b/DataHelper/GraphQL/XStringGraphType.cs
new file mode 100644
index 0000000..54e9bbc
--- /dev/null
+++ b/DataHelper/GraphQL/XStringGraphType.cs
@@ -0,0 +1,15 @@
+using xDataService.GraphQL;
+using xStringService.Models.Entities;
+
+namespace xDataHelper.GraphQL
+{
+ public class XStringGraphType : XBaseGraphObjectType
+ {
+ public XStringGraphType() : base()
+ {
+ Field(x => x.Language);
+ Field(x => x.ResourceTitle);
+ Field(x => x.TranslatedValue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Extensions/XModelExtensions.cs b/Extensions/XModelExtensions.cs
new file mode 100644
index 0000000..9198007
--- /dev/null
+++ b/Extensions/XModelExtensions.cs
@@ -0,0 +1,118 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using xCommons.Extensions;
+using xModels.Dtos;
+using xStringService.Models.Dtos;
+using xStringService.Models.Entities;
+
+namespace xStringService.Extensions
+{
+ public static class XModelExtensions
+ {
+ ///
+ /// Converts an Entity to Dto Representation ...
+ ///
+ ///
+ ///
+ public static XStringDto ToXStringDto(this XString source)
+ {
+ //
+ XStringDto result = new XStringDto();
+
+ //
+ result.Id = source.Id;
+ result.Language = source.Language;
+ result.ResourceTitle = source.ResourceTitle;
+ result.TranslatedValue = source.TranslatedValue;
+
+ //
+ return result;
+ }
+
+ ///
+ /// Converts a Collection of Entities to Dto ...
+ ///
+ ///
+ ///
+ public static IEnumerable ToXStringDtos(this IEnumerable source)
+ {
+ //
+ var list = new List();
+
+ //
+ // Validate ...
+ bool isValid = source.HasChild();
+ if (!isValid)
+ {
+ return list.AsEnumerable();
+ }
+
+ //
+ var result = source.Select(e => ToXStringDto(e));
+
+ //
+ return result;
+ }
+
+ ///
+ /// Converts an Entity to LocaleResource Dto ...
+ ///
+ ///
+ ///
+ public static XLocaleResourceDto ToXLocaleResourceDto(this XString source)
+ {
+ //
+ var result = new XLocaleResourceDto
+ {
+ Language = source.IsNull() ? "" : source.Language,
+ Value = source.IsNull() ? "" : source.TranslatedValue,
+ };
+
+ //
+ return result;
+ }
+
+ ///
+ /// Converts an Dto to LocaleResource Dto ...
+ ///
+ ///
+ ///
+ public static XLocaleResourceDto ToXLocaleResourceDto(this XStringDto source)
+ {
+ //
+ var result = new XLocaleResourceDto
+ {
+ Language = source.IsNull() ? "" : source.Language,
+ Value = source.IsNull() ? "" : source.TranslatedValue,
+ };
+
+ //
+ return result;
+ }
+
+ ///
+ /// Converts a Collection of Entities to Locale Resource Presentation ...
+ ///
+ ///
+ ///
+ public static IEnumerable ToXLocaleResourceDtos(this IEnumerable source)
+ {
+ //
+ var result = source.Select(e => ToXLocaleResourceDto(e));
+ return result;
+ }
+
+ ///
+ /// Converts a Collection of Dtos to Locale Resource Presentation ...
+ ///
+ ///
+ ///
+ public static IEnumerable ToXLocaleResourceDtos(this IEnumerable source)
+ {
+ //
+ var result = source.Select(e => ToXLocaleResourceDto(e));
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Interfaces/Entities/IXStringEvents.cs b/Interfaces/Entities/IXStringEvents.cs
new file mode 100644
index 0000000..4f6b4da
--- /dev/null
+++ b/Interfaces/Entities/IXStringEvents.cs
@@ -0,0 +1,8 @@
+using xDataService.Interfaces;
+using xStringService.Models.Entities;
+
+namespace xStringService.Interfaces.Entities
+{
+ public interface IXStringEvents : IXBaseRepositoryEvents
+ { }
+}
\ No newline at end of file
diff --git a/Interfaces/Entities/IXStringGraphQLTypeHelper.cs b/Interfaces/Entities/IXStringGraphQLTypeHelper.cs
new file mode 100644
index 0000000..8d10308
--- /dev/null
+++ b/Interfaces/Entities/IXStringGraphQLTypeHelper.cs
@@ -0,0 +1,8 @@
+using xDataService.Interfaces;
+using xStringService.Models.Entities;
+
+namespace xStringService.Interfaces.Entities
+{
+ public interface IXStringGraphQLTypeHelper : IXBaseGraphQLTypeHelper
+ { }
+}
\ No newline at end of file
diff --git a/Interfaces/Entities/IXStringRepository.cs b/Interfaces/Entities/IXStringRepository.cs
new file mode 100644
index 0000000..01b921e
--- /dev/null
+++ b/Interfaces/Entities/IXStringRepository.cs
@@ -0,0 +1,8 @@
+using xDataService.Interfaces;
+using xStringService.Models.Entities;
+
+namespace xStringService.Interfaces.Entities
+{
+ public interface IXStringRepository : IXBaseRepository
+ { }
+}
\ No newline at end of file
diff --git a/Interfaces/IXStringProvider.cs b/Interfaces/IXStringProvider.cs
new file mode 100644
index 0000000..32d3cc8
--- /dev/null
+++ b/Interfaces/IXStringProvider.cs
@@ -0,0 +1,251 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using xCommons.Configurations;
+using xDataService.Configuration;
+using xModels.Dtos;
+using xStringService.Interfaces.Entities;
+using xStringService.Models.Dtos;
+using xStringService.Models.Entities;
+
+namespace xStringService.Interfaces
+{
+ public interface IXStringProvider
+ {
+ //
+ #region Props ...
+ IXStringRepository Repository { get; }
+ XAppConfiguration AppConfiguration { get; }
+ XDataServiceConfiguration DataConfiguration { get; }
+ #endregion
+
+ //
+ #region Retrievers ...
+ ///
+ /// Retrieve all Exists Languages ...
+ ///
+ ///
+ Task> GetLanguages();
+
+ ///
+ /// Check Specified Resource Exists or not ...
+ ///
+ ///
+ ///
+ ///
+ Task IsResourceExists(
+ string resource,
+ string language = null
+ );
+
+ ///
+ /// Retrieve Specified Translation of Specified Resource ...
+ ///
+ ///
+ ///
+ ///
+ Task GetResourceValue(
+ string resource,
+ string language = null
+ );
+
+ ///
+ /// Retrieve an Specified Resource Items ...
+ ///
+ ///
+ ///
+ Task> GetResources(string resource);
+
+ ///
+ /// Retrieve Specified Resource Items as XResourceDto Presentation ...
+ ///
+ ///
+ ///
+ Task GetResource(string resource);
+ #endregion
+
+ //
+ #region Query ...
+ ///
+ /// Query Resource IDs ...
+ ///
+ ///
+ ///
+ Task> QueryResourceIds(XQuery query);
+
+ ///
+ /// Query Specified Language Resources ...
+ ///
+ ///
+ ///
+ ///
+ Task> QueryLanguageResources(
+ XQuery query,
+ string language = null //
+ );
+
+ ///
+ /// Query Locale Resources ...
+ ///
+ ///
+ ///
+ ///
+ Task> QueryLocaleResources(
+ XQuery query,
+ string language = null //
+ );
+
+ ///
+ /// Conditional Query Resources ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> ConditionalQueryResources(
+ XQuery query,
+ Expression> condition,
+ string language = null
+ );
+ #endregion
+
+ //
+ #region Add/Update Actions ...
+ ///
+ /// Add Specified Resource ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task Add(
+ string resource,
+ string value,
+ string language = null
+ );
+
+ ///
+ /// Update Resource ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task Update(
+ string resource,
+ string value,
+ string language = null
+ );
+
+ ///
+ /// Add Or Update Resource ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task AddOrUpdate(
+ string resource,
+ string value,
+ string language = null
+ );
+
+ ///
+ /// Add Specified Resource ...
+ ///
+ ///
+ ///
+ Task AddEntity(XStringDto item);
+
+ ///
+ /// Update Specified Entity ...
+ ///
+ ///
+ ///
+ Task UpdateEntity(XStringDto item);
+
+ ///
+ /// Add Or Update Specified Entitiy ...
+ ///
+ ///
+ ///
+ Task AddOrUpdateEntity(XStringDto item);
+
+ ///
+ /// Add Specified Locale Resource ...
+ ///
+ ///
+ ///
+ ///
+ Task AddByLocaleResource(
+ XLocaleResourceDto item,
+ string resource
+ );
+
+ ///
+ /// Update Specified Locale Resource ...
+ ///
+ ///
+ ///
+ ///
+ Task UpdateByLocaleResource(
+ XLocaleResourceDto item,
+ string resource
+ );
+
+ ///
+ /// Add Or Update Resource By Locale ...
+ ///
+ ///
+ ///
+ ///
+ Task AddOrUpdateByLocaleResource(
+ XLocaleResourceDto item,
+ string resource
+ );
+
+ ///
+ /// Add Or Update all XResourceDto(s) Locales ...
+ ///
+ ///
+ ///
+ Task> AddByResource(XResourceDto item);
+ #endregion
+
+ //
+ #region Remove Actions ...
+ ///
+ /// Remove all Specified Language's Resources ...
+ ///
+ ///
+ ///
+ Task RemoveLanguageResources(string language);
+
+ ///
+ /// Remove all Specified Resource Ids instances ...
+ ///
+ ///
+ ///
+ Task> RemoveResource(string resource);
+
+ ///
+ /// Remove Specified Resource ...
+ ///
+ ///
+ ///
+ ///
+ Task Remove(
+ string resource,
+ string language = null
+ );
+
+ ///
+ /// Remove all Resource of Specified XResourceDto ...
+ ///
+ ///
+ ///
+ Task RemoveByResource(XResourceDto item);
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Models/Dtos/XStringDto.cs b/Models/Dtos/XStringDto.cs
new file mode 100644
index 0000000..65bbb1f
--- /dev/null
+++ b/Models/Dtos/XStringDto.cs
@@ -0,0 +1,12 @@
+using xModels.Base;
+
+namespace xStringService.Models.Dtos
+{
+ public class XStringDto : XBaseDto
+ {
+ public int Id { get; set; }
+ public string Language { get; set; }
+ public string ResourceTitle { get; set; }
+ public string TranslatedValue { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Models/Entities/XString.cs b/Models/Entities/XString.cs
new file mode 100644
index 0000000..99b95b0
--- /dev/null
+++ b/Models/Entities/XString.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using xModels.Base;
+
+namespace xStringService.Models.Entities
+{
+ public class XString : XBaseIntIDEntity
+ {
+ [Required]
+ [StringLength (10)]
+ public string Language { get; set; }
+
+ [Required]
+ [StringLength (255)]
+ public string ResourceTitle { get; set; }
+
+ [Required]
+ public string TranslatedValue { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Providers/XStringProvider.cs b/Providers/XStringProvider.cs
new file mode 100644
index 0000000..1cb5399
--- /dev/null
+++ b/Providers/XStringProvider.cs
@@ -0,0 +1,1183 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reactive.Concurrency;
+using System.Threading.Tasks;
+using xCommons.Configurations;
+using xCommons.Extensions;
+using xDataService.Configuration;
+using xDataService.Extensions;
+using xExceptions.Constants;
+using xModels.Dtos;
+using xStringService.Extensions;
+using xStringService.Interfaces;
+using xStringService.Interfaces.Entities;
+using xStringService.Models.Dtos;
+using xStringService.Models.Entities;
+
+namespace xStringService.Providers
+{
+ public class XStringProvider : IXStringProvider
+ {
+ //
+ #region Props ...
+ public IXStringRepository Repository { get; }
+ public XAppConfiguration AppConfiguration { get; }
+ public XDataServiceConfiguration DataConfiguration { get; }
+ #endregion
+
+ //
+ #region Constructor ...
+ public XStringProvider(
+ IXStringRepository repository,
+ XAppConfiguration appConfiguration,
+ XDataServiceConfiguration dataConfiguration
+ )
+ {
+ //
+ Repository = repository;
+ AppConfiguration = appConfiguration;
+ DataConfiguration = dataConfiguration;
+ }
+ #endregion
+
+ //
+ #region Retrievers ...
+ ///
+ /// Retrieve all Exists Languages ...
+ ///
+ ///
+ public async Task> GetLanguages()
+ {
+ //
+ var result = (await Repository.GetAllAsync())
+ .AsQueryable()
+ .Select(e => e.Language)
+ .Distinct()
+ .ToList();
+
+ //
+ // Check Configuration Default Language Exists ...
+ var hasDefaultLanguage = !AppConfiguration.DefaultLanguage.IsNullOrEmpty();
+ if (hasDefaultLanguage)
+ {
+ //
+ // Find Default Language on Result ...
+ hasDefaultLanguage = result.Any(e => e.ToNormalString() == AppConfiguration.DefaultLanguage.ToNormalString());
+ if (!hasDefaultLanguage)
+ {
+ result.Add(AppConfiguration.DefaultLanguage);
+ }
+ }
+
+ //
+ result = result
+ .Distinct()
+ .ToList();
+
+ //
+ return result;
+ }
+
+ ///
+ /// Check Specified Resource Exists or not ...
+ ///
+ ///
+ ///
+ ///
+ public async Task IsResourceExists(
+ string resource,
+ string language = null
+ )
+ {
+ //
+ var result = false;
+
+ //
+ // Validate ...
+ result = !resource.IsNullOrEmpty();
+ if (!result)
+ {
+ return result;
+ }
+
+ //
+ XStringDto entity = null;
+ if (language.IsNullOrEmpty())
+ {
+ //
+ entity = await Repository
+ .FindOneAsync(e => e.ResourceTitle == resource)
+ .ToDynamicObject();
+ }
+ else
+ {
+ //
+ entity = await Repository
+ .FindOneAsync(e => e.ResourceTitle == resource &&
+ e.Language.ToNormalString() == language.ToNormalString()
+ )
+ .ToDynamicObject();
+ }
+ result = !entity.IsNullOrDefault();
+
+ //
+ return result;
+ }
+
+ ///
+ /// Retrieve Specified Translation of Specified Resource ...
+ ///
+ ///
+ ///
+ ///
+ public async Task GetResourceValue(
+ string resource,
+ string language = null
+ )
+ {
+ //
+ var result = "";
+
+ //
+ // Normalize ...
+ if (language.IsNullOrEmpty())
+ {
+ language = AppConfiguration.DefaultLanguage;
+ }
+
+ //
+ // Validate ...
+ var isValid = !resource.IsNullOrEmpty() &&
+ !language.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Check Langauage Exists ...
+ var languages = await GetLanguages();
+ isValid = languages.Any(l => l.ToNormalString() == language.ToNormalString());
+ if (!isValid)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Check Resource Exists ...
+ isValid = await IsResourceExists(resource);
+ if (!isValid)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ var entity = await Repository.FindOneAsync(e =>
+ e.ResourceTitle == resource &&
+ e.Language.ToNormalString() == language.ToNormalString()
+ );
+ isValid = !entity.IsNullOrDefault();
+ if (!isValid)
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ result = entity.TranslatedValue;
+
+ //
+ return result;
+ }
+
+ ///
+ /// Retrieve an Specified Resource Items ...
+ ///
+ ///
+ ///
+ public async Task> GetResources(string resource)
+ {
+ //
+ // Validate ...
+ var isValid = await IsResourceExists(resource);
+ if (!isValid)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ var result = (await Repository
+ .FindManyAsync(e => e.ResourceTitle == resource))
+ .ToXStringDtos();
+
+ //
+ return result;
+ }
+
+ ///
+ /// Retrieve Specified Resource Items as XResourceDto Presentation ...
+ ///
+ ///
+ ///
+ public async Task GetResource(string resource)
+ {
+ //
+ // Validate ...
+ bool isExists = await IsResourceExists(resource);
+ if (!isExists)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Retrieve String Dto (s) ...
+ var resources = await GetResources(resource);
+ if (!resource.HasChild())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ var result = new XResourceDto
+ {
+ Resource = resource,
+ Locales = resources.ToXLocaleResourceDtos()
+ };
+
+ return result;
+ }
+ #endregion
+
+ //
+ #region Query ...
+ ///
+ /// Query Resource IDs ...
+ ///
+ ///
+ ///
+ public async Task> QueryResourceIds(XQuery query)
+ {
+ //
+ // Normalize ...
+ query = query.NormalizeQuery(DataConfiguration);
+
+ //
+ // Read Resource IDs ...
+ var items = Repository
+ .AsQueryable()
+ .Select(e => e.ResourceTitle)
+ .Distinct();
+
+ //
+ var totalItemsCount = items.Count();
+
+ //
+ // Apply Filter ...
+ if (totalItemsCount > 0 &&
+ !query.Filter.IsNullOrEmpty())
+ {
+ //
+ items = items
+ .Where(e => e.ToNormalString().Contains(query.Filter.ToNormalString()));
+ }
+
+ //
+ var filteredItemsCount = items.Count();
+ var totalPagesCount = query.CountPages(totalItemsCount);
+ var filteredPagesCount = query.CountPages(filteredItemsCount);
+
+ //
+ // Apply Paging / Sorting ...
+ if (totalItemsCount > 0 &&
+ filteredItemsCount > 0)
+ {
+ //
+ items = items.ApplyPaging(
+ query.Page,
+ query.PageSize
+ );
+ }
+
+ //
+ // Prepare result ...
+ var result = new XQueryResult
+ {
+ Page = query.Page,
+ PageSize = query.PageSize,
+ TotalPages = totalPagesCount,
+ TotalItems = totalItemsCount,
+ TotalFilteredPages = filteredPagesCount,
+ TotalFilteredItems = filteredItemsCount
+ };
+
+ //
+ return result;
+ }
+
+ ///
+ /// Query Specified Language Resources ...
+ ///
+ ///
+ ///
+ ///
+ public async Task> QueryLanguageResources(
+ XQuery query,
+ string language = null //
+ )
+ {
+ //
+ // Normalize ...
+ query = query.NormalizeQuery(DataConfiguration);
+
+ //
+ // Validate ...
+ if (query.IsNull())
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ XQueryResult result = null;
+ if (language.IsNullOrEmpty())
+ {
+ //
+ result = (await Repository.QueryAsync(query))
+ .ToDynamicObject();
+ }
+ else
+ {
+ //
+ result = (await Repository.ConditionalQueryAsync(
+ e => e.Language.ToNormalString() == language.ToNormalString(),
+ query
+ ))
+ .ToDynamicObject();
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// Query Locale Resources ...
+ ///
+ ///
+ ///
+ ///
+ public async Task> QueryLocaleResources(
+ XQuery query,
+ string language = null //
+ )
+ {
+ //
+ // Normalize ...
+ query.NormalizeQuery(DataConfiguration);
+
+ //
+ // Validate ...
+ if (query.IsNull())
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ IEnumerable items = null;
+ if (!language.IsNullOrEmpty())
+ {
+ items = (await Repository
+ .FindManyAsync(e => e.Language.ToNormalString() == language.ToNormalString()))
+ .ToXLocaleResourceDtos();
+ }
+ else
+ {
+ items = (await Repository.GetAllAsync())
+ .ToXLocaleResourceDtos();
+ }
+
+ //
+ var totalItemsCount = items.Count();
+
+ //
+ // Apply Filter ...
+ if (totalItemsCount > 0 &&
+ !query.Filter.IsNullOrEmpty())
+ {
+ //
+ items = items.ApplyFilter(query.Filter);
+ }
+
+ //
+ var filteredItemsCount = items.Count();
+ var totalPagesCount = query.CountPages(totalItemsCount);
+ var filteredPagesCount = query.CountPages(filteredItemsCount);
+
+ //
+ // Apply Paging/Sorting ...
+ if (totalItemsCount > 0 &&
+ filteredItemsCount > 0)
+ {
+ //
+ // Apply Paging ...
+ items = items.ApplyPaging(
+ query.Page,
+ query.PageSize
+ );
+
+ //
+ // Apply Sorting ...
+ items = items.ApplySorting(
+ query.SortBy,
+ query.IsAscending
+ );
+ }
+
+ //
+ // Prepare Result ...
+ var result = new XQueryResult
+ {
+ Page = query.Page,
+ PageSize = query.PageSize,
+ TotalPages = totalPagesCount,
+ TotalItems = totalItemsCount,
+ TotalFilteredPages = filteredPagesCount,
+ TotalFilteredItems = filteredItemsCount
+ };
+
+ //
+ return result;
+ }
+
+ ///
+ /// Conditional Query Resources ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task> ConditionalQueryResources(
+ XQuery query,
+ Expression> condition,
+ string language = null
+ )
+ {
+ //
+ // Normalize ...
+ query = query.NormalizeQuery(DataConfiguration);
+
+ //
+ if (!language.IsNullOrEmpty())
+ {
+ //
+ // Renew and Update Condition by Language Checking ...
+ var compiledCondition = condition.Compile();
+ condition =
+ e => compiledCondition(e) &&
+ e.Language.ToNormalString() == language.ToNormalString();
+ }
+
+ //
+ var result = (await Repository.ConditionalQueryAsync(condition, query))
+ .ToDynamicObject();
+
+ //
+ return result;
+ }
+ #endregion
+
+ //
+ #region Add/Update Actions ...
+ ///
+ /// Add Specified Resource ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task Add(
+ string resource,
+ string value,
+ string language = null
+ )
+ {
+ //
+ bool result = false;
+
+ //
+ // Normalize ...
+ if (language.IsNullOrEmpty())
+ {
+ language = AppConfiguration.DefaultLanguage;
+ }
+
+ //
+ // Validate ...
+ result =
+ !value.IsNullOrEmpty() &&
+ !resource.IsNullOrEmpty() &&
+ !language.IsNullOrEmpty();
+ if (!result)
+ {
+ return result;
+ }
+
+ //
+ // Check Exists ...
+ bool isExists = await IsResourceExists(resource, language);
+ result = !isExists;
+ if (!result)
+ {
+ XException.Duplicate.Throw();
+ }
+
+ //
+ // Prepare Entity to Add ...
+ XString entity = new XString
+ {
+ Language = language,
+ TranslatedValue = value,
+ ResourceTitle = resource,
+ };
+ var added = await Repository.AddAsync(entity);
+ result = !added.IsNullOrDefault();
+
+ //
+ return result;
+ }
+
+ ///
+ /// Update Resource ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task Update(
+ string resource,
+ string value,
+ string language = null
+ )
+ {
+ //
+ bool result = false;
+
+ //
+ // Normalize ...
+ if (language.IsNullOrEmpty())
+ {
+ language = AppConfiguration.DefaultLanguage;
+ }
+
+ //
+ // Validate ...
+ result =
+ !value.IsNullOrEmpty() &&
+ !language.IsNullOrEmpty() &&
+ !resource.IsNullOrEmpty();
+ if (!result)
+ {
+ return result;
+ }
+
+ //
+ // Check Value Must Exists ...
+ result = await IsResourceExists(
+ resource: resource,
+ language: language
+ );
+ if (!result)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ var entity = await Repository.FindOneAsync(e =>
+ e.ResourceTitle == resource &&
+ e.Language.ToNormalString() == language.ToNormalString()
+ );
+ if (entity.IsNullOrDefault())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Update Entity ...
+ entity.TranslatedValue = value;
+ entity = await Repository.UpdateAsync(entity.Id, entity);
+ result = !entity.IsNullOrDefault();
+
+ //
+ return result;
+ }
+
+ ///
+ /// Add Or Update Resource ...
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task AddOrUpdate(
+ string resource,
+ string value,
+ string language = null
+ )
+ {
+ //
+ var result = false;
+
+ //
+ // Normalize ...
+ if (language.IsNullOrEmpty())
+ {
+ language = AppConfiguration.DefaultLanguage;
+ }
+
+ //
+ // Check Existsance ...
+ bool isExists = await IsResourceExists(
+ resource: resource,
+ language: language
+ );
+
+ //
+ // Act Based on Existance ...
+ if (isExists)
+ {
+ //
+ result = await Update(
+ value: value,
+ resource: resource,
+ language: language
+ );
+ }
+ else
+ {
+ //
+ result = await Add(
+ value: value,
+ resource: resource,
+ language: language
+ );
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// Add Specified Resource ...
+ ///
+ ///
+ ///
+ public async Task AddEntity(XStringDto item)
+ {
+ //
+ // Validate ...
+ bool isValid = !item.IsNull() &&
+ !item.ResourceTitle.IsNullOrEmpty() &&
+ !item.TranslatedValue.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Normalize ...
+ if (item.Language.IsNullOrEmpty())
+ {
+ item.Language = AppConfiguration.DefaultLanguage;
+ }
+ isValid = !item.Language.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Check Resource Doesn't Exists ...
+ isValid = await IsResourceExists(
+ resource: item.ResourceTitle,
+ language: item.Language
+ );
+ if (isValid)
+ {
+ XException.Duplicate.Throw();
+ }
+
+ //
+ var result = new XString
+ {
+ Language = item.Language,
+ ResourceTitle = item.ResourceTitle,
+ TranslatedValue = item.TranslatedValue
+ };
+ result = await Repository.AddAsync(result);
+ if (result.IsNullOrDefault())
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ return result.ToDynamicObject();
+ }
+
+ ///
+ /// Update Specified Entity ...
+ ///
+ ///
+ ///
+ public async Task UpdateEntity(XStringDto item)
+ {
+ //
+ // Validate ...
+ bool isValid = !item.IsNull() &&
+ !item.ResourceTitle.IsNullOrEmpty() &&
+ !item.TranslatedValue.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Normalize ...
+ if (item.Language.IsNullOrEmpty())
+ {
+ item.Language = AppConfiguration.DefaultLanguage;
+ }
+ isValid = !item.Language.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Check Resource Exists ...
+ isValid = await IsResourceExists(
+ resource: item.ResourceTitle,
+ language: item.Language
+ );
+ if (!isValid)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ var entity = await Repository.FindOneAsync(e =>
+ e.ResourceTitle == item.ResourceTitle &&
+ e.Language.ToNormalString() == item.Language.ToNormalString()
+ );
+ if (entity.IsNullOrDefault())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Update Entity ...
+ entity.TranslatedValue = item.TranslatedValue;
+ entity = await Repository.UpdateAsync(entity.Id, entity);
+ if (entity.IsNullOrDefault())
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ XStringDto result = entity.ToDynamicObject();
+
+ //
+ return result;
+ }
+
+ ///
+ /// Add Or Update Specified Entitiy ...
+ ///
+ ///
+ ///
+ public async Task AddOrUpdateEntity(XStringDto item)
+ {
+ //
+ // Validate ...
+ bool isValid = !item.IsNull() &&
+ !item.ResourceTitle.IsNullOrEmpty() &&
+ !item.TranslatedValue.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Normalize ...
+ if (item.Language.IsNullOrEmpty())
+ {
+ item.Language = AppConfiguration.DefaultLanguage;
+ }
+ isValid = !item.Language.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Check Resource Exists ...
+ var isExists = await IsResourceExists(
+ resource: item.ResourceTitle,
+ language: item.Language
+ );
+
+ //
+ XStringDto result = null;
+ if (!isExists)
+ {
+ result = await AddEntity(item);
+ }
+ else
+ {
+ result = await UpdateEntity(item);
+ }
+ if (result.IsNullOrDefault())
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// Add Specified Locale Resource ...
+ ///
+ ///
+ ///
+ ///
+ public async Task AddByLocaleResource(
+ XLocaleResourceDto item,
+ string resource
+ )
+ {
+ //
+ // Validate ...
+ bool isValid =
+ !item.IsNull() &&
+ !resource.IsNullOrEmpty() &&
+ !item.Value.IsNullOrEmpty() &&
+ !item.Language.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Check Specified Resource / Language Exists ...
+ isValid = await IsResourceExists(
+ resource: resource,
+ language: item.Language
+ );
+ if (isValid)
+ {
+ XException.Duplicate.Throw();
+ }
+
+ //
+ // Prepare Item to Add ...
+ var result = new XStringDto
+ {
+ Language = item.Language,
+ ResourceTitle = resource,
+ TranslatedValue = item.Value
+ };
+ result = await AddEntity(result);
+
+ //
+ return result;
+ }
+
+ ///
+ /// Update Specified Locale Resource ...
+ ///
+ ///
+ ///
+ ///
+ public async Task UpdateByLocaleResource(
+ XLocaleResourceDto item,
+ string resource
+ )
+ {
+ //
+ // Validate ...
+ bool isValid =
+ !item.IsNull() &&
+ !resource.IsNullOrEmpty() &&
+ !item.Value.IsNullOrEmpty() &&
+ !item.Language.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Check Specified Resource / Language Exists ...
+ isValid = await IsResourceExists(
+ resource: resource,
+ language: item.Language
+ );
+ if (!isValid)
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ var entity = await Repository.FindOneAsync(e =>
+ e.ResourceTitle == resource &&
+ e.Language.ToNormalString() == item.Language.ToNormalString()
+ );
+ if (entity.IsNullOrDefault())
+ {
+ XException.NotFound.Throw();
+ }
+
+ //
+ // Update ...
+ entity.TranslatedValue = item.Value;
+ entity = await Repository.UpdateAsync(entity.Id, entity);
+ if (entity.IsNullOrDefault())
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ XStringDto result = entity.ToDynamicObject();
+ return result;
+ }
+
+ ///
+ /// Add Or Update Resource By Locale ...
+ ///
+ ///
+ ///
+ ///
+ public async Task AddOrUpdateByLocaleResource(
+ XLocaleResourceDto item,
+ string resource
+ )
+ {
+ //
+ // Validate ...
+ bool isValid =
+ !item.IsNull() &&
+ !resource.IsNullOrEmpty() &&
+ !item.Value.IsNullOrEmpty() &&
+ !item.Language.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ // Check Specified Resource / Language Exists ...
+ isValid = await IsResourceExists(
+ resource: resource,
+ language: item.Language
+ );
+
+ //
+ XStringDto result = null;
+ if (!isValid)
+ {
+ //
+ result = await AddByLocaleResource(
+ item: item,
+ resource: resource
+ );
+ }
+ else
+ {
+ //
+ result = await UpdateByLocaleResource(
+ item: item,
+ resource: resource
+ );
+ }
+ if (result.IsNullOrDefault())
+ {
+ XException.ActionFailed.Throw();
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// Add Or Update all XResourceDto(s) Locales ...
+ ///
+ ///
+ ///
+ public async Task> AddByResource(XResourceDto item)
+ {
+ //
+ // Validate ...
+ bool isValid =
+ !item.IsNull() &&
+ item.Locales.HasChild() &&
+ !item.Resource.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ var result = await Task
+ .WhenAll(item.Locales
+ .Select(async e => await AddOrUpdateByLocaleResource(e, item.Resource)));
+
+ //
+ return result;
+ }
+ #endregion
+
+ //
+ #region Remove Actions ...
+ ///
+ /// Remove all Specified Language's Resources ...
+ ///
+ ///
+ ///
+ public async Task RemoveLanguageResources(string language)
+ {
+ //
+ // Validate ...
+ bool isValid = !language.IsNullOrEmpty();
+ if (!isValid)
+ {
+ return;
+ }
+
+ //
+ var entities = await Repository
+ .FindManyAsync(e => e.Language.ToNormalString() == language.ToNormalString());
+ await Repository.RemoveRangeAsync(entities);
+ }
+
+ ///
+ /// Remove all Specified Resource Ids instances ...
+ ///
+ ///
+ ///
+ public async Task> RemoveResource(string resource)
+ {
+ //
+ // Validate ...
+ if (resource.IsNullOrEmpty())
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ var result = new List();
+ var entities = await Repository.FindManyAsync(e => e.ResourceTitle == resource);
+ foreach (var entity in entities)
+ {
+ //
+ var removed = await Repository.RemoveAsync(entity);
+ if (!removed.IsNullOrDefault())
+ {
+ result.Add(removed.ToXStringDto());
+ }
+ }
+
+ //
+ return result;
+ }
+
+ ///
+ /// Remove Specified Resource ...
+ ///
+ ///
+ ///
+ ///
+ public async Task Remove(
+ string resource,
+ string language = null
+ )
+ {
+ //
+ bool result = false;
+
+ //
+ // Normalize ...
+ if (language.IsNullOrEmpty())
+ {
+ language = AppConfiguration.DefaultLanguage;
+ }
+
+ //
+ // Validate ...
+ result =
+ !language.IsNullOrEmpty() &&
+ !resource.IsNullOrEmpty();
+ if (!result)
+ {
+ return result;
+ }
+
+ //
+ // Check Resource Exists ...
+ result = await IsResourceExists(
+ language: language,
+ resource: resource
+ );
+ if (!result)
+ {
+ return result;
+ }
+
+ //
+ // Retrieve Entity ...
+ var entity = await Repository.FindOneAsync(e =>
+ e.ResourceTitle == resource &&
+ e.Language.ToNormalString() == language.ToNormalString()
+ );
+ result = !entity.IsNullOrDefault();
+ if (!result)
+ {
+ return result;
+ }
+
+ //
+ // Delete ...
+ entity = await Repository.RemoveAsync(entity.Id);
+ result = !entity.IsNullOrDefault();
+
+ //
+ return result;
+ }
+
+ ///
+ /// Remove all Resource of Specified XResourceDto ...
+ ///
+ ///
+ ///
+ public async Task RemoveByResource(XResourceDto item)
+ {
+ //
+ bool isValid =
+ !item.IsNullOrDefault() &&
+ item.Locales.HasChild() &&
+ !item.Resource.IsNullOrEmpty();
+ if (!isValid)
+ {
+ XException.InvalidArgs.Throw();
+ }
+
+ //
+ foreach (var locale in item.Locales)
+ {
+ //
+ await Remove(
+ resource: item.Resource,
+ language: locale.Language
+ );
+ }
+ }
+ #endregion
+ }
+}
\ No newline at end of file