Skip to content

Commit

Permalink
[#316] CSV Export Draft
Browse files Browse the repository at this point in the history
  • Loading branch information
gruenwaldlk committed Sep 5, 2023
1 parent 55ba984 commit 611bb0f
Show file tree
Hide file tree
Showing 18 changed files with 705 additions and 4 deletions.
20 changes: 19 additions & 1 deletion PG.Commons/PG.Commons/Repository/IRepository.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
// 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.Collections.Generic;
using PG.Commons.Validation;

namespace PG.Commons.Repository;

/// <summary>
/// Base contract for a object storage repository.
/// </summary>
public interface IRepository
{
}

/// <summary>
/// Base contract for a object storage repository.
/// </summary>
/// <typeparam name="TKey">The key to access values.</typeparam>
/// <typeparam name="TValue">The value.</typeparam>
public interface IRepository<in TKey, TValue> : IValidatable where TValue : IValidatable
public interface IRepository<TKey, TValue> : IRepository, IValidatable where TValue : IValidatable
{
/// <summary>
/// Gets a collection containing the keys in the repository.
/// </summary>
IReadOnlyCollection<TKey> Keys { get; }

/// <summary>
/// Gets a collection containing the values in the repository.
/// </summary>
IReadOnlyCollection<TValue> Values { get; }

/// <summary>
/// Tries to insert an object into the repository.
/// </summary>
Expand Down
8 changes: 8 additions & 0 deletions PG.Commons/PG.Commons/Repository/RepositoryBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ protected RepositoryBase(IServiceProvider services)
Logger = services.GetService<ILoggerFactory>()?.CreateLogger(GetType()) ?? NullLogger.Instance;
}


/// <inheritdoc />
public IReadOnlyCollection<TKey> Keys => InternalRepository.Keys;


/// <inheritdoc />
public IReadOnlyCollection<TValue> Values => InternalRepository.Values;

/// <summary>
/// The internal Dictionary.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -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.Files;
using PG.Commons.Validation;

namespace PG.Commons.Services.Processing;

/// <summary>
/// Contract for processing instruction parameters.
/// </summary>
public interface IProcessingInstructionsParam : IParam, IValidatable
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// 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.Diagnostics;
using System.IO.Abstractions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PG.StarWarsGame.Components.Localisation.IO.Formats.Builtin.Csv;
using PG.StarWarsGame.Components.Localisation.IO.Formats.Builtin.Csv.Translation;
using PG.StarWarsGame.Components.Localisation.Languages.Builtin;
using PG.StarWarsGame.Components.Localisation.Repository;
using PG.StarWarsGame.Components.Localisation.Repository.Translation;
using PG.Testing;

namespace PG.StarWarsGame.Components.Localisation.Test.IO.Formats.Builtin.Csv.Translation;

[TestClass]
public class TranslationCsvFormatterTest
{
private readonly string _directoryPath =
$"/tst/{nameof(TranslationCsvFormatterTest)}/{DateTimeOffset.Now.ToUnixTimeSeconds()}/";

private TranslationCsvFormatter? Formatter { get; set; }
private TranslationCsvFormatDescriptor? Descriptor { get; set; }

private IDirectoryInfo? Directory { get; set; }

[TestInitialize]
public void TestInitialize()
{
Descriptor = new TranslationCsvFormatDescriptor(TestConstants.Services);
Formatter = new TranslationCsvFormatter(Descriptor, TestConstants.Services);
var fs = TestConstants.Services.GetService<IFileSystem>();
Debug.Assert(fs != null, nameof(fs) + " != null");
Directory = fs.Directory.CreateDirectory(_directoryPath);
Debug.Assert(Directory != null, nameof(Directory) + " != null");
Assert.IsTrue(fs.Directory.Exists(Directory.FullName));
}

[TestCleanup]
public void TestCleanup()
{
Descriptor = null;
Formatter = null;
Directory = null;
}

private static ITranslationRepository CreateRepository()
{
var en = new EnglishAlamoLanguageDefinition();
var de = new GermanAlamoLanguageDefinition();

var repository = new TranslationRepository(TestConstants.Services);

var itemRepository0 = new TranslationItemRepository(TestConstants.Services);
var itemRepository1 = new TranslationItemRepository(TestConstants.Services);
var itemRepository2 = new TranslationItemRepository(TestConstants.Services);
var itemRepository3 = new TranslationItemRepository(TestConstants.Services);

itemRepository0.TryCreate(en, new TranslationItem("KEY_00", "VALUE_00 - ENGLISH"));
itemRepository0.TryCreate(de, new TranslationItem("KEY_00", "VALUE_00 - GERMAN"));

itemRepository1.TryCreate(en, new TranslationItem("KEY_01", "VALUE_01 - ENGLISH"));
itemRepository1.TryCreate(de, new TranslationItem("KEY_01", "VALUE_01 - GERMAN"));

itemRepository2.TryCreate(en, new TranslationItem("KEY_02", "VALUE_02 - ENGLISH"));
// itemRepository2.TryCreate(german, new TranslationItem("KEY_02", "VALUE_02 - GERMAN"));

// itemRepository3.TryCreate(english, new TranslationItem("KEY_03", "VALUE_03 - ENGLISH"));
itemRepository3.TryCreate(de, new TranslationItem("KEY_03", "VALUE_03 - GERMAN"));

repository.TryCreate("KEY_00", itemRepository0);
repository.TryCreate("KEY_01", itemRepository1);
repository.TryCreate("KEY_02", itemRepository2);
repository.TryCreate("KEY_03", itemRepository3);

return repository;
}

[TestMethod]
public void Test_CreateCsvFiles__ValidOutput()
{
Debug.Assert(Directory != null, nameof(Directory) + " != null");
var param = CreateCsvFormatterProcessingInstructionsParam.WithDirectory(Directory.FullName)
.WithFileName("testfile").WithCsvExtension().WithSeparator('=').withoutKeyWrapper().withoutValueWrapper()
.AlphabetizeKeys();
Debug.Assert(Formatter != null, nameof(Formatter) + " != null");
Formatter.WithProcessingInstructions(param);
Formatter.ValidateAndThrow();
var repository = CreateRepository();
Formatter.Export(repository);

var fs = TestConstants.Services.GetService<IFileSystem>();
Debug.Assert(fs != null, nameof(fs) + " != null");

var fileEn = Directory.FullName + fs.Path.DirectorySeparatorChar +
"testfile.en.csv"; // Workaround for IPath.Join shenanigans.
var fileDe = Directory.FullName + fs.Path.DirectorySeparatorChar +
"testfile.de.csv"; // Workaround for IPath.Join shenanigans.
Assert.IsTrue(fs.File.Exists(fileEn));
Assert.IsTrue(fs.File.Exists(fileDe));

var enContent = fs.File.ReadLines(fileEn);
var deContent = fs.File.ReadLines(fileEn);

Assert.IsNotNull(enContent);
Assert.IsNotNull(deContent);

Assert.AreNotEqual(enContent, deContent);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) Alamo Engine Tools and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.

namespace PG.StarWarsGame.Components.Localisation.IO.Formats.Builtin.Csv.Credits;

public class CreditsCsvFormatDescriptor
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) Alamo Engine Tools and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.

namespace PG.StarWarsGame.Components.Localisation.IO.Formats.Builtin.Csv.Credits;

public class CreditsCsvFormatter
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// 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.Components.Localisation.IO.Formats.Builtin.Csv;

/// <inheritdoc cref="ILocalisationFormatter{TProcessingInstructions,TData}" />
public abstract class
CsvFormatterBase<TRepository> : FormatterBase<CsvFormatterProcessingInstructionsParam, TRepository>
where TRepository : IRepository
{
/// <inheritdoc />
protected CsvFormatterBase(
ILocalisationFormatDescriptor<CsvFormatterProcessingInstructionsParam, TRepository> descriptor,
IServiceProvider services) : base(descriptor, services)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 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 FluentValidation;
using FluentValidation.Results;
using M31.FluentApi.Attributes;

namespace PG.StarWarsGame.Components.Localisation.IO.Formats.Builtin.Csv;

/// <inheritdoc />
[FluentApi]
public record CsvFormatterProcessingInstructionsParam : ILocalisationFormatterProcessingInstructionsParam
{
/// <inheritdoc />
[FluentMember(0)]
public string? Directory { get; init; }

/// <inheritdoc />
[FluentMember(1)]
public string? FileName { get; init; }

/// <inheritdoc />
[FluentMember(2)]
[FluentDefault("WithCsvExtension")]
public string? FileExtension { get; init; } = "csv";

/// <summary>
/// The separator used in the CSV file
/// </summary>
[FluentMember(3)]
[FluentDefault("WithCommaSeparator")]
public char? Separator { get; init; } = ',';

/// <summary>
/// The character used wo wrap a key, eg. "MY_KEY"
/// </summary>
[FluentMember(4)]
[FluentDefault("withoutKeyWrapper")]
public char? KeyWrapper { get; init; } = null;

/// <summary>
/// The character used wo wrap a value, eg. "My new value!"
/// </summary>
[FluentMember(5)]
[FluentDefault("withoutValueWrapper")]
public char? ValueWrapper { get; init; } = null;

/// <summary>
/// Determines whether the output is alphabetized by key.
/// </summary>
[FluentMember(6)]
[FluentDefault("AlphabetizeKeys")]
public bool? AlphabetizeKeys { get; init; } = true;

/// <inheritdoc />
public ValidationResult Validate()
{
return new CsvFormatterProcessingInstructionsParamValidator().Validate(this);
}

/// <inheritdoc />
public void ValidateAndThrow()
{
new CsvFormatterProcessingInstructionsParamValidator().ValidateAndThrow(this);
}

private class CsvFormatterProcessingInstructionsParamValidator :
AbstractValidator<CsvFormatterProcessingInstructionsParam>
{
internal CsvFormatterProcessingInstructionsParamValidator()
{
RuleFor(param => param.Directory)
.NotNull()
.NotEmpty();
RuleFor(param => param.FileName)
.NotNull()
.NotEmpty();
RuleFor(param => param.AlphabetizeKeys)
.NotNull();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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.StarWarsGame.Components.Localisation.Languages;
using PG.StarWarsGame.Components.Localisation.Repository.Translation;

namespace PG.StarWarsGame.Components.Localisation.IO.Formats.Builtin.Csv.Translation;

/// <inheritdoc />
public class TranslationCsvFormatDescriptor : FormatDescriptorBase<CsvFormatterProcessingInstructionsParam,
ITranslationRepository>
{
private static string FallbackFileExtension => "csv";

/// <inheritdoc />
public TranslationCsvFormatDescriptor(IServiceProvider services) : base(services)
{
}

/// <inheritdoc />
public override string ToFileName(
ILocalisationFormatter<CsvFormatterProcessingInstructionsParam, ITranslationRepository> formatter,
IAlamoLanguageDefinition definition)
{
var fileNameBase = formatter.Param.FileName ?? FallbackFileNameBase;
var fileExtension = formatter.Param.FileExtension ?? FallbackFileExtension;
return $"{fileNameBase}.{definition.Culture.TwoLetterISOLanguageName.ToLower()}.{fileExtension}";
}

/// <inheritdoc />
public override ILocalisationFormatter<CsvFormatterProcessingInstructionsParam, ITranslationRepository>
CreateFormatter(CsvFormatterProcessingInstructionsParam param)
{
return new TranslationCsvFormatter(this, Services)
.WithProcessingInstructions(param);
}
}
Loading

0 comments on commit 611bb0f

Please sign in to comment.