Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class CreateFileProfileRequest

public string OperatorName { get; set; }

public string LineTerminator { get; set; }
public LineTerminatorType? LineTerminator { get; set; }

public string FileFormatHandler { get; set; }
}
14 changes: 14 additions & 0 deletions FileProcessor.DataTransferObjects/Requests/LineTerminatorType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Text.Json.Serialization;

namespace FileProcessor.DataTransferObjects.Requests;

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum LineTerminatorType
{
LineFeed = 1,

CarriageReturnLineFeed = 2,

CarriageReturn = 3
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class UpdateFileProfileRequest

public string OperatorName { get; set; }

public string LineTerminator { get; set; }
public LineTerminatorType? LineTerminator { get; set; }

public string FileFormatHandler { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void FileProfileAggregate_CreateUpdateAndUniquenessFlow_WorksAsExpected()
TestData.SafaricomListeningDirectory,
TestData.SafaricomRequestType,
TestData.SafaricomOperatorIdentifier,
TestData.SafaricomLineTerminator,
LineTerminatorType.LineFeed,
TestData.SafaricomFileFormatHandler));

Result secondCreate = aggregate.CreateProfile(this.CreateProfile(
Expand All @@ -33,7 +33,7 @@ public void FileProfileAggregate_CreateUpdateAndUniquenessFlow_WorksAsExpected()
TestData.VoucherListeningDirectory,
TestData.VoucherRequestType,
TestData.VoucherOperatorIdentifier,
TestData.VoucherLineTerminator,
LineTerminatorType.LineFeed,
TestData.VoucherFileFormatHandler));

Result updateName = aggregate.UpdateProfile(TestData.FileProfileId, new UpdateFileProfileRequest
Expand All @@ -58,7 +58,7 @@ public void FileProfileAggregate_CreateUpdateAndUniquenessFlow_WorksAsExpected()

Result updateLineTerminator = aggregate.UpdateProfile(TestData.FileProfileId, new UpdateFileProfileRequest
{
LineTerminator = "\r\n"
LineTerminator = LineTerminatorType.CarriageReturnLineFeed
});

Result updateFileFormatHandler = aggregate.UpdateProfile(TestData.FileProfileId, new UpdateFileProfileRequest
Expand All @@ -72,7 +72,7 @@ public void FileProfileAggregate_CreateUpdateAndUniquenessFlow_WorksAsExpected()
"/home/txnproc/bulkfiles/duplicate-name",
"GammaRequest",
"Gamma Operator",
"\n",
LineTerminatorType.LineFeed,
"GammaHandler"));

Result duplicateRequestTypeCreate = aggregate.CreateProfile(this.CreateProfile(
Expand All @@ -81,7 +81,7 @@ public void FileProfileAggregate_CreateUpdateAndUniquenessFlow_WorksAsExpected()
"/home/txnproc/bulkfiles/duplicate-request",
TestData.VoucherRequestType,
"Gamma Operator",
"\n",
LineTerminatorType.LineFeed,
"GammaHandler"));

List<FileProcessor.Models.FileProfile> fileProfiles = aggregate.GetAllProfiles();
Expand Down Expand Up @@ -128,7 +128,7 @@ public void FileProfileAggregate_Update_WithNoEffectiveChanges_DoesNotChangeAppl
TestData.SafaricomListeningDirectory,
TestData.SafaricomRequestType,
TestData.SafaricomOperatorIdentifier,
TestData.SafaricomLineTerminator,
LineTerminatorType.LineFeed,
TestData.SafaricomFileFormatHandler));

Result updateResult = aggregate.UpdateProfile(TestData.FileProfileId, new UpdateFileProfileRequest
Expand All @@ -137,7 +137,7 @@ public void FileProfileAggregate_Update_WithNoEffectiveChanges_DoesNotChangeAppl
RequestType = TestData.SafaricomRequestType,
ListeningDirectory = TestData.SafaricomListeningDirectory,
OperatorName = TestData.SafaricomOperatorIdentifier,
LineTerminator = TestData.SafaricomLineTerminator,
LineTerminator = LineTerminatorType.LineFeed,
FileFormatHandler = TestData.SafaricomFileFormatHandler
});

Expand All @@ -154,7 +154,7 @@ public void FileProfileAggregate_Update_ListeningDirectoryUpdatesDerivedDirector
TestData.SafaricomListeningDirectory,
TestData.SafaricomRequestType,
TestData.SafaricomOperatorIdentifier,
TestData.SafaricomLineTerminator,
LineTerminatorType.LineFeed,
TestData.SafaricomFileFormatHandler));

Result updateResult = aggregate.UpdateProfile(TestData.FileProfileId, new UpdateFileProfileRequest
Expand Down Expand Up @@ -182,7 +182,7 @@ public void FileProfileAggregate_Create_WithDuplicateName_IsRejected()
TestData.SafaricomListeningDirectory,
TestData.SafaricomRequestType,
TestData.SafaricomOperatorIdentifier,
TestData.SafaricomLineTerminator,
LineTerminatorType.LineFeed,
TestData.SafaricomFileFormatHandler));

Result duplicateCreate = aggregate.CreateProfile(this.CreateProfile(
Expand All @@ -191,14 +191,51 @@ public void FileProfileAggregate_Create_WithDuplicateName_IsRejected()
"/tmp/other",
"DifferentRequest",
"Other",
TestData.SafaricomLineTerminator,
LineTerminatorType.LineFeed,
"OtherHandler"));

firstCreate.IsSuccess.ShouldBeTrue();
duplicateCreate.IsFailed.ShouldBeTrue();
duplicateCreate.Status.ShouldBe(ResultStatus.Invalid);
}

[Theory]
[InlineData(null)]
public void FileProfileAggregate_Create_WithInvalidTerminator_IsRejected(LineTerminatorType? lineTerminator)
{
FileProfileAggregateRoot aggregate = FileProfileAggregateRoot.Create();

Result firstCreate = aggregate.CreateProfile(this.CreateProfile(
TestData.FileProfileId,
TestData.SafaricomProfileName,
TestData.SafaricomListeningDirectory,
TestData.SafaricomRequestType,
TestData.SafaricomOperatorIdentifier,
lineTerminator,
TestData.SafaricomFileFormatHandler));

firstCreate.IsFailed.ShouldBeTrue();
firstCreate.Status.ShouldBe(ResultStatus.Invalid);
}

[Fact]
public void FileProfileAggregate_Create_WithUnknownTerminator_IsRejected()
{
FileProfileAggregateRoot aggregate = FileProfileAggregateRoot.Create();

Result firstCreate = aggregate.CreateProfile(this.CreateProfile(
TestData.FileProfileId,
TestData.SafaricomProfileName,
TestData.SafaricomListeningDirectory,
TestData.SafaricomRequestType,
TestData.SafaricomOperatorIdentifier,
(LineTerminatorType?)99,
TestData.SafaricomFileFormatHandler));

firstCreate.IsFailed.ShouldBeTrue();
firstCreate.Status.ShouldBe(ResultStatus.Invalid);
}

[Fact]
public void FileProfileAggregate_Create_WithDuplicateRequestType_IsRejected()
{
Expand All @@ -210,7 +247,7 @@ public void FileProfileAggregate_Create_WithDuplicateRequestType_IsRejected()
TestData.SafaricomListeningDirectory,
TestData.SafaricomRequestType,
TestData.SafaricomOperatorIdentifier,
TestData.SafaricomLineTerminator,
LineTerminatorType.LineFeed,
TestData.SafaricomFileFormatHandler));

Result duplicateCreate = aggregate.CreateProfile(this.CreateProfile(
Expand All @@ -219,7 +256,7 @@ public void FileProfileAggregate_Create_WithDuplicateRequestType_IsRejected()
"/tmp/other",
TestData.SafaricomRequestType,
"Other",
TestData.SafaricomLineTerminator,
LineTerminatorType.LineFeed,
"OtherHandler"));

firstCreate.IsSuccess.ShouldBeTrue();
Expand All @@ -232,7 +269,7 @@ private CreateFileProfileRequest CreateProfile(Guid fileProfileId,
string listeningDirectory,
string requestType,
string operatorName,
string lineTerminator,
LineTerminatorType? lineTerminator,
string fileFormatHandler)
{
return new CreateFileProfileRequest
Expand Down
86 changes: 74 additions & 12 deletions FileProcessor.FileProfileAggregate/FileProfileAggregate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Shared.DomainDrivenDesign.EventSourcing;
using Shared.EventStore.Aggregate;
using Shared.General;
using Shared.Results;
using SimpleResults;
using FileProfileModel = FileProcessor.Models.FileProfile;

Expand Down Expand Up @@ -93,13 +94,17 @@ public static Result CreateProfile(this FileProfileAggregate aggregate, CreateFi
return Result.Invalid($"File profile [{request.FileProfileId}] already exists");
}

var lineTerminatorResult = request.LineTerminator.Value.ToLineTerminator();
if (lineTerminatorResult.IsFailed)
return ResultHelpers.CreateFailure(lineTerminatorResult);

FileProfileCreatedEvent fileProfileCreatedEvent = new(aggregate.AggregateId,
request.FileProfileId,
request.Name.Trim(),
request.ListeningDirectory.Trim(),
request.RequestType.Trim(),
request.OperatorName.Trim(),
request.LineTerminator,
lineTerminatorResult.Data,
request.FileFormatHandler.Trim());

aggregate.ApplyAndAppend(fileProfileCreatedEvent);
Expand Down Expand Up @@ -135,12 +140,19 @@ public static Result UpdateProfile(this FileProfileAggregate aggregate, Guid fil
aggregate.ApplyAndAppend(new FileProfileOperatorNameUpdatedEvent(aggregate.AggregateId, fileProfileId, request.OperatorName));
}

if (IsDomainEventRequired(profile.FileFormatHandler, request.FileFormatHandler)) {
aggregate.ApplyAndAppend(new FileProfileFileFormatHandlerUpdatedEvent(aggregate.AggregateId, fileProfileId, request.FileFormatHandler));
if (request.LineTerminator.HasValue) {
Result<String> lineTerminatorResult = request.LineTerminator.Value.ToLineTerminator();
if (lineTerminatorResult.IsFailed) {
return ResultHelpers.CreateFailure(lineTerminatorResult);
}

if (IsDomainEventRequired(profile.LineTerminator, lineTerminatorResult.Data)) {
aggregate.ApplyAndAppend(new FileProfileLineTerminatorUpdatedEvent(aggregate.AggregateId, fileProfileId, lineTerminatorResult.Data));
}
}

if (IsDomainEventRequired(profile.LineTerminator, request.LineTerminator)) {
aggregate.ApplyAndAppend(new FileProfileLineTerminatorUpdatedEvent(aggregate.AggregateId, fileProfileId, request.LineTerminator));
if (IsDomainEventRequired(profile.FileFormatHandler, request.FileFormatHandler)) {
aggregate.ApplyAndAppend(new FileProfileFileFormatHandlerUpdatedEvent(aggregate.AggregateId, fileProfileId, request.FileFormatHandler));
}

return Result.Success();
Expand Down Expand Up @@ -270,18 +282,42 @@ private static Boolean IsSameProfile(this FileProfileAggregate aggregate, FilePr
Comparer.Equals(profile.ListeningDirectory, request.ListeningDirectory.Trim()) &&
Comparer.Equals(profile.RequestType, request.RequestType.Trim()) &&
Comparer.Equals(profile.OperatorName, request.OperatorName.Trim()) &&
Comparer.Equals(profile.LineTerminator, request.LineTerminator) &&
Comparer.Equals(profile.LineTerminator, request.LineTerminator.Value.ToLineTerminator()) &&
Comparer.Equals(profile.FileFormatHandler, request.FileFormatHandler.Trim()) &&
profile.IsArchived == false;
}

private static Result ValidateRequiredCreateFields(CreateFileProfileRequest request)
{
return ValidateStringField(request.ListeningDirectory, "No listening directory provided") ??
ValidateStringField(request.RequestType, "No request type provided") ??
ValidateStringField(request.OperatorName, "No operator name provided") ??
ValidateStringField(request.LineTerminator, "No line terminator provided") ??
ValidateStringField(request.FileFormatHandler, "No file format handler provided");
var errors = new List<string>();

AddIfInvalid(request.ListeningDirectory, "No listening directory provided", errors);
AddIfInvalid(request.RequestType, "No request type provided", errors);
AddIfInvalid(request.OperatorName, "No operator name provided", errors);
AddLineTerminatorIfInvalid(request.LineTerminator, "No line terminator provided", errors);
AddIfInvalid(request.FileFormatHandler, "No file format handler provided", errors);

return errors.Count == 0
? Result.Success()
: Result.Invalid(errors);
}

private static void AddIfInvalid(string? value, string errorMessage, ICollection<string> errors)
{
if (string.IsNullOrWhiteSpace(value))
{
errors.Add(errorMessage);
}
}

private static void AddLineTerminatorIfInvalid(LineTerminatorType? value,
string errorMessage,
ICollection<string> errors)
{
if (value.HasValue == false || Enum.IsDefined(typeof(LineTerminatorType), value.Value) == false)
{
errors.Add(errorMessage);
}
}

private static Result ValidateProposedUpdateValues(UpdateFileProfileRequest request)
Expand All @@ -290,10 +326,22 @@ private static Result ValidateProposedUpdateValues(UpdateFileProfileRequest requ
ValidateOptionalStringField(request.ListeningDirectory, "No listening directory provided") ??
ValidateOptionalStringField(request.RequestType, "No request type provided") ??
ValidateOptionalStringField(request.OperatorName, "No operator name provided") ??
ValidateOptionalStringField(request.LineTerminator, "No line terminator provided") ??
ValidateOptionalLineTerminatorField(request.LineTerminator, "No line terminator provided") ??
ValidateOptionalStringField(request.FileFormatHandler, "No file format handler provided");
}

private static Result ValidateOptionalLineTerminatorField(LineTerminatorType? value, string errorMessage)
{
if (value.HasValue == false)
{
return Result.Success();
}

return Enum.IsDefined(typeof(LineTerminatorType), value.Value)
? Result.Success()
: Result.Invalid(errorMessage);
}

private static Result ValidateCreateUniqueness(this FileProfileAggregate aggregate, CreateFileProfileRequest request)
{
String proposedName = request.Name.Trim();
Expand Down Expand Up @@ -395,6 +443,20 @@ private static FileProfileModel ToModel(this FileProfileState fileProfile)
}
}

public static class LineTerminatorTypeExtensions
{
public static Result<string> ToLineTerminator(this LineTerminatorType lineTerminator)
{
return lineTerminator switch
{
LineTerminatorType.LineFeed => Result.Success<string>("\n"),
LineTerminatorType.CarriageReturnLineFeed => Result.Success<string>("\r\n"),
LineTerminatorType.CarriageReturn => Result.Success<string>("\r"),
_ => Result.Invalid($"Invalid line terminator type {lineTerminator}")
};
}
}

public record FileProfileAggregate : Aggregate
{
public static readonly Guid FileProfileCollectionId = Guid.Parse("2E8EAF39-3F51-4C10-9B8B-0D9DE3F80110");
Expand Down
Loading
Loading