diff --git a/PG.Commons/PG.Commons/Repository/IRepository.cs b/PG.Commons/PG.Commons/Repository/IRepository.cs new file mode 100644 index 00000000..1a2d01d3 --- /dev/null +++ b/PG.Commons/PG.Commons/Repository/IRepository.cs @@ -0,0 +1,45 @@ +// Copyright (c) Alamo Engine Tools and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. + +using PG.Commons.Validation; + +namespace PG.Commons.Repository; + +/// +/// Base contract for a object storage repository. +/// +/// The key to access values. +/// The value. +public interface IRepository : IValidatable where TValue : IValidatable +{ + /// + /// Tries to insert an object into the repository. + /// + /// The object's key. + /// the object + /// True if the insert succeeded, false else. + bool TryCreate(TKey key, TValue value); + + /// + /// Tries to load the value for a given key. + /// + /// The key. + /// The object to load. + /// True if the read succeeded, false else. + bool TryRead(TKey key, out TValue? value); + + /// + /// Tries to update the value for a given key. + /// + /// The key. + /// The object to load. + /// True if the update succeeded, false else. + bool TryUpdate(TKey key, TValue value); + + /// + /// Tries to delete a given object from the repository. + /// + /// The key. + /// True if the delete succeeded, false else. + bool TryDelete(TKey key); +} \ No newline at end of file diff --git a/PG.Commons/PG.Commons/Repository/RepositoryBase.cs b/PG.Commons/PG.Commons/Repository/RepositoryBase.cs new file mode 100644 index 00000000..1706dd54 --- /dev/null +++ b/PG.Commons/PG.Commons/Repository/RepositoryBase.cs @@ -0,0 +1,127 @@ +// Copyright (c) Alamo Engine Tools and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. + +using System; +using System.Collections.Generic; +using System.Linq; +using FluentValidation.Results; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using PG.Commons.Validation; + +namespace PG.Commons.Repository; + +/// +public abstract class RepositoryBase : IRepository + where TKey : notnull + where TValue : + IValidatable +{ + /// + /// .ctor + /// + /// + protected RepositoryBase(IServiceProvider services) + { + Logger = services.GetService()?.CreateLogger(GetType()) ?? NullLogger.Instance; + } + + /// + /// The internal Dictionary. + /// + protected readonly Dictionary InternalRepository = new(); + + /// + protected readonly ILogger Logger; + + /// + public ValidationResult Validate() + { + var errors = new List(); + foreach (var validationFailures in InternalRepository.Values.Select(v => v.Validate().Errors)) + { + errors.AddRange(validationFailures); + } + + return new ValidationResult(errors); + } + + /// + public void ValidateAndThrow() + { + foreach (var v in InternalRepository.Values) + { + v.ValidateAndThrow(); + } + } + + /// + public bool TryCreate(TKey key, TValue value) + { + if (InternalRepository.ContainsKey(key)) + { + Logger.LogInformation( + "The repository already has a value set for the key={key}. The value could not be inserted.", key); + return false; + } + + var validationResult = value.Validate(); + if (!validationResult.IsValid) + { + Logger.LogWarning("The provided value {value} is invalid. Validation result: {validationResult}", value, + validationResult); + return false; + } + + InternalRepository.Add(key, value); + return true; + } + + /// + public bool TryRead(TKey key, out TValue? value) + { + if (!InternalRepository.ContainsKey(key)) + { + Logger.LogInformation("There is no object with key={key} in repository.", key); + value = default; + return false; + } + + value = InternalRepository[key]; + return true; + } + + /// + public bool TryUpdate(TKey key, TValue value) + { + if (!InternalRepository.ContainsKey(key)) + { + Logger.LogInformation("There is no object with key={key} in repository.", key); + return false; + } + + var validationResult = value.Validate(); + if (!validationResult.IsValid) + { + Logger.LogWarning("The provided value {value} is invalid. Validation result: {validationResult}", value, + validationResult); + return false; + } + + InternalRepository[key] = value; + return true; + } + + /// + public bool TryDelete(TKey key) + { + if (!InternalRepository.ContainsKey(key)) + { + Logger.LogInformation("There is no object with key={key} in repository.", key); + return false; + } + + return InternalRepository.Remove(key); + } +} \ No newline at end of file diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Attributes/DefaultLanguageAttribute.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Attributes/DefaultLanguageAttribute.cs index 0f7b6bd5..8c609657 100644 --- a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Attributes/DefaultLanguageAttribute.cs +++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Attributes/DefaultLanguageAttribute.cs @@ -10,7 +10,7 @@ namespace PG.StarWarsGame.Localisation.Attributes; /// that can be used to mark a as the default /// language. /// -public class DefaultLanguageAttribute : Attribute +public sealed class DefaultLanguageAttribute : Attribute { /// /// Is set to true, if the language is a default. diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/LocalisationDomain.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/LocalisationDomain.cs index e8276d93..d7ea4f8b 100644 --- a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/LocalisationDomain.cs +++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/LocalisationDomain.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for details. using Microsoft.Extensions.DependencyInjection; -using PG.StarWarsGame.Files.DAT; using PG.StarWarsGame.Localisation.Commons.Helper; namespace PG.StarWarsGame.Localisation; @@ -18,7 +17,7 @@ public static class LocalisationDomain /// The service collection to populate. public static void RegisterServices(IServiceCollection serviceCollection) { - DatDomain.RegisterServices(serviceCollection); + PG.StarWarsGame.Files.DAT.DatDomain.RegisterServices(serviceCollection); serviceCollection .AddSingleton(sp => new AlamoLanguageDefinitionHelper(sp)) ; diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation.csproj b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation.csproj index 611edd87..93f4c1c9 100644 --- a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation.csproj +++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation.csproj @@ -12,6 +12,10 @@ true true + + $(BaseIntermediateOutputPath)Generated + true + diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItem.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItem.cs new file mode 100644 index 00000000..18a7a24c --- /dev/null +++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItem.cs @@ -0,0 +1,22 @@ +// Copyright (c) Alamo Engine Tools and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. + +using PG.Commons.Validation; + +namespace PG.StarWarsGame.Localisation.Repository; + +/// +/// A simple translation item. +/// +public interface ITranslationItem : IValidatable +{ + /// + /// The item's key. + /// + string Key { get; } + + /// + /// The item's value. + /// + string Value { get; } +} \ No newline at end of file diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItemRepository.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItemRepository.cs new file mode 100644 index 00000000..6d5c1af3 --- /dev/null +++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationItemRepository.cs @@ -0,0 +1,14 @@ +// Copyright (c) Alamo Engine Tools and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. + +using PG.Commons.Repository; +using PG.StarWarsGame.Localisation.Languages; + +namespace PG.StarWarsGame.Localisation.Repository; + +/// +/// A repository to hold s. +/// +public interface ITranslationItemRepository : IRepository +{ +} \ No newline at end of file diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationRepository.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationRepository.cs new file mode 100644 index 00000000..5b340e96 --- /dev/null +++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/ITranslationRepository.cs @@ -0,0 +1,13 @@ +// Copyright (c) Alamo Engine Tools and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. + +using PG.Commons.Repository; + +namespace PG.StarWarsGame.Localisation.Repository; + +/// +/// Repository for sorted localisations. +/// +public interface ITranslationRepository : IRepository +{ +} \ No newline at end of file diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItem.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItem.cs new file mode 100644 index 00000000..4b4b8030 --- /dev/null +++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItem.cs @@ -0,0 +1,67 @@ +// Copyright (c) Alamo Engine Tools and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. + +using System; +using FluentValidation; +using FluentValidation.Results; + +namespace PG.StarWarsGame.Localisation.Repository; + +/// +public sealed class TranslationItem : ITranslationItem +{ + internal TranslationItem() + { + } + + /// + /// .ctor + /// + /// The string key. + /// The translated text. + /// + internal TranslationItem(string key, string value) + { + if (string.IsNullOrWhiteSpace(key)) + { + throw new ArgumentNullException(nameof(key)); + } + + if (string.IsNullOrWhiteSpace(value)) + { + throw new ArgumentNullException(nameof(value)); + } + + Key = key ?? throw new ArgumentNullException(nameof(key)); + Value = value ?? throw new ArgumentNullException(nameof(value)); + } + + + /// + public string Key { get; private set; } = null!; + + /// + public string Value { get; private set; } = null!; + + /// + public ValidationResult Validate() + { + return new TranslationItemValidator().Validate(this); + } + + /// + public void ValidateAndThrow() + { + new TranslationItemValidator().ValidateAndThrow(this); + } + + /// + private class TranslationItemValidator : AbstractValidator + { + internal TranslationItemValidator() + { + RuleFor(i => i.Key).NotNull().NotEmpty(); + RuleFor(i => i.Value).NotNull().NotEmpty(); + } + } +} \ No newline at end of file diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItemRepository.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItemRepository.cs new file mode 100644 index 00000000..b01ed9db --- /dev/null +++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationItemRepository.cs @@ -0,0 +1,18 @@ +// Copyright (c) Alamo Engine Tools and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. + +using System; +using PG.Commons.Repository; +using PG.StarWarsGame.Localisation.Languages; + +namespace PG.StarWarsGame.Localisation.Repository; + +/// +internal sealed class TranslationItemRepository : RepositoryBase, + ITranslationItemRepository +{ + /// + public TranslationItemRepository(IServiceProvider services) : base(services) + { + } +} \ No newline at end of file diff --git a/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationRepository.cs b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationRepository.cs new file mode 100644 index 00000000..0a1ca95e --- /dev/null +++ b/PG.StarWarsGame.Localisation/PG.StarWarsGame.Localisation/Repository/TranslationRepository.cs @@ -0,0 +1,15 @@ +// Copyright (c) Alamo Engine Tools and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for details. + +using System; +using PG.Commons.Repository; + +namespace PG.StarWarsGame.Localisation.Repository; + +internal sealed class TranslationRepository : RepositoryBase, ITranslationRepository +{ + /// + public TranslationRepository(IServiceProvider services) : base(services) + { + } +} \ No newline at end of file