Skip to content

Commit

Permalink
refac: 1. refactor archived messages to clean architecture (#1358)
Browse files Browse the repository at this point in the history
* Refactor ArchivedMessages to clean architecture

---------

Co-authored-by: Ebbe Knudsen <[email protected]>
Co-authored-by: Mads Magnus Due <[email protected]>
  • Loading branch information
3 people authored Nov 15, 2024
1 parent 26e4ad3 commit 05a516c
Show file tree
Hide file tree
Showing 63 changed files with 942 additions and 286 deletions.
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>Energinet.DataHub.EDI.ArchivedMessages.Application</AssemblyName>
<RootNamespace>Energinet.DataHub.EDI.ArchivedMessages.Application</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.2" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.11.20">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ArchivedMessages.Infrastructure\ArchivedMessages.Infrastructure.csproj" />
<ProjectReference Include="..\ArchivedMessages.Domain\ArchivedMessages.Domain.csproj" />
<ProjectReference Include="..\ArchivedMessages.Interfaces\ArchivedMessages.Interfaces.csproj" />
<ProjectReference Include="..\BuildingBlocks.Application\BuildingBlocks.Application.csproj" />
<ProjectReference Include="..\DataAccess\DataAccess.csproj" />
</ItemGroup>
<ItemDefinitionGroup>
<ProjectReference>
Expand Down
40 changes: 24 additions & 16 deletions source/ArchivedMessages.Application/ArchivedMessagesClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,46 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using Energinet.DataHub.EDI.ArchivedMessages.Infrastructure;
using Energinet.DataHub.EDI.ArchivedMessages.Application.Mapping;
using Energinet.DataHub.EDI.ArchivedMessages.Domain.Models;
using Energinet.DataHub.EDI.ArchivedMessages.Interfaces;
using Energinet.DataHub.EDI.ArchivedMessages.Interfaces.Models;
using Energinet.DataHub.EDI.BuildingBlocks.Domain.Models;

namespace Energinet.DataHub.EDI.ArchivedMessages.Application;

public class ArchivedMessagesClient : IArchivedMessagesClient
public class ArchivedMessagesClient(IArchivedMessageRepository archivedMessageRepository) : IArchivedMessagesClient
{
private readonly IArchivedMessageRepository _archivedMessageRepository;
private readonly IArchivedMessageRepository _archivedMessageRepository = archivedMessageRepository;

public ArchivedMessagesClient(IArchivedMessageRepository archivedMessageRepository)
{
_archivedMessageRepository = archivedMessageRepository;
}

public async Task<IArchivedFile> CreateAsync(ArchivedMessage message, CancellationToken cancellationToken)
public async Task<IArchivedFile> CreateAsync(ArchivedMessageDto message, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(message);
await _archivedMessageRepository.AddAsync(message, cancellationToken).ConfigureAwait(false);

return new ArchivedFile(message.FileStorageReference, message.ArchivedMessageStream);
var mappedArchivedMessage = ArchivedMessageMapper.Map(message);

await _archivedMessageRepository.AddAsync(mappedArchivedMessage, cancellationToken).ConfigureAwait(false);

return new ArchivedFile(mappedArchivedMessage.FileStorageReference, mappedArchivedMessage.ArchivedMessageStream);
}

public async Task<ArchivedMessageStream?> GetAsync(ArchivedMessageId id, CancellationToken cancellationToken)
public async Task<ArchivedMessageStreamDto?> GetAsync(ArchivedMessageIdDto id, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(id);
return await _archivedMessageRepository.GetAsync(id, cancellationToken).ConfigureAwait(false);

var archivedMessageId = new ArchivedMessageId(id.Value);

var result = await _archivedMessageRepository.GetAsync(archivedMessageId, cancellationToken).ConfigureAwait(false);

return result != null ? new ArchivedMessageStreamDto(result.Stream) : null;
}

public Task<MessageSearchResult> SearchAsync(GetMessagesQuery queryInput, CancellationToken cancellationToken)
public async Task<MessageSearchResultDto> SearchAsync(GetMessagesQueryDto queryInputDto, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(queryInput);
return _archivedMessageRepository.SearchAsync(queryInput, cancellationToken);
ArgumentNullException.ThrowIfNull(queryInputDto);

var result = await _archivedMessageRepository.SearchAsync(GetMessagesQueryMapper.Map(queryInputDto), cancellationToken).ConfigureAwait(false);

return MessagesSearchResultMapper.Map(result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2020 Energinet DataHub A/S
//
// Licensed under the Apache License, Version 2.0 (the "License2");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Energinet.DataHub.EDI.ArchivedMessages.Domain.Exceptions;
using Energinet.DataHub.EDI.ArchivedMessages.Domain.Models;
using Energinet.DataHub.EDI.ArchivedMessages.Interfaces.Models;
using Energinet.DataHub.EDI.BuildingBlocks.Domain.Validation;

namespace Energinet.DataHub.EDI.ArchivedMessages.Application.Mapping;

public static class ArchivedMessageMapper
{
public static ArchivedMessage Map(ArchivedMessageDto dto)
{
return !EnumCompatibilityChecker.AreEnumsCompatible<ArchivedMessageType, ArchivedMessageTypeDto>()
? throw new InvalidEnumMappingException($"Enum of type {nameof(ArchivedMessageType)} cannot be mapped to type {nameof(ArchivedMessageTypeDto)}.")
: new ArchivedMessage(
id: new ArchivedMessageId(dto.Id.Value),
messageId: dto.MessageId,
eventIds: dto.EventIds,
documentType: dto.DocumentType,
senderNumber: dto.SenderNumber,
senderRole: dto.SenderRole,
receiverNumber: dto.ReceiverNumber,
receiverRole: dto.ReceiverRole,
createdAt: dto.CreatedAt,
businessReason: dto.BusinessReason,
archivedMessageType: (ArchivedMessageType)dto.ArchivedMessageType,
archivedMessageStream: new ArchivedMessageStream(dto.ArchivedMessageStream.Stream),
relatedToMessageId: dto.RelatedToMessageId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2020 Energinet DataHub A/S
//
// Licensed under the Apache License, Version 2.0 (the "License2");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Energinet.DataHub.EDI.ArchivedMessages.Domain.Models;
using Energinet.DataHub.EDI.ArchivedMessages.Interfaces.Models;

namespace Energinet.DataHub.EDI.ArchivedMessages.Application.Mapping;

internal static class GetMessagesQueryMapper
{
internal static GetMessagesQuery Map(GetMessagesQueryDto dto)
{
return new GetMessagesQuery(
Pagination: SetSortedCursorBasedPagination(dto.Pagination),
CreationPeriod: SetMessageCreationPeriod(dto.CreationPeriod),
MessageId: dto.MessageId,
SenderNumber: dto.SenderNumber,
SenderRoleCode: dto.SenderRoleCode,
ReceiverNumber: dto.ReceiverNumber,
ReceiverRoleCode: dto.ReceiverRoleCode,
DocumentTypes: dto.DocumentTypes,
BusinessReasons: dto.BusinessReasons,
IncludeRelatedMessages: dto.IncludeRelatedMessages);
}

private static SortedCursorBasedPagination SetSortedCursorBasedPagination(SortedCursorBasedPaginationDto dto)
{
return new SortedCursorBasedPagination(
cursor: SetSortingCursor(dto.Cursor),
pageSize: dto.PageSize,
navigationForward: dto.NavigationForward,
fieldToSortBy: SetFieldToSortBy(dto.FieldToSortBy),
directionToSortBy: SetDirectionToSortBy(dto.DirectionToSortBy));
}

private static MessageCreationPeriod? SetMessageCreationPeriod(MessageCreationPeriodDto? messageCreationPeriod)
{
return messageCreationPeriod is not null
? new MessageCreationPeriod(messageCreationPeriod.DateToSearchFrom, messageCreationPeriod.DateToSearchTo)
: null;
}

private static SortingCursor? SetSortingCursor(SortingCursorDto? sortingCursor)
{
return sortingCursor is not null
? new SortingCursor(sortingCursor.SortedFieldValue, sortingCursor.RecordId)
: null;
}

private static FieldToSortBy? SetFieldToSortBy(FieldToSortByDto? fieldToSortBy)
{
return fieldToSortBy is not null
? new FieldToSortBy(fieldToSortBy.Value.Identifier)
: null;
}

private static DirectionToSortBy? SetDirectionToSortBy(DirectionToSortByDto? directionToSortBy)
{
return directionToSortBy is not null
? new DirectionToSortBy(directionToSortBy.Value.Identifier)
: null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2020 Energinet DataHub A/S
//
// Licensed under the Apache License, Version 2.0 (the "License2");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Collections.ObjectModel;
using Energinet.DataHub.EDI.ArchivedMessages.Domain.Models;
using Energinet.DataHub.EDI.ArchivedMessages.Interfaces.Models;

namespace Energinet.DataHub.EDI.ArchivedMessages.Application.Mapping;

internal static class MessagesSearchResultMapper
{
internal static MessageSearchResultDto Map(MessageSearchResult messageSearchResult)
{
return new MessageSearchResultDto(SetMessageInfoCollection(messageSearchResult.Messages), messageSearchResult.TotalAmountOfMessages);
}

private static ReadOnlyCollection<MessageInfoDto> SetMessageInfoCollection(IReadOnlyCollection<MessageInfo> collection)
{
return collection.Select(mi => new MessageInfoDto(
RecordId: mi.RecordId,
Id: mi.Id,
MessageId: mi.MessageId,
DocumentType: mi.DocumentType,
SenderNumber: mi.SenderNumber,
SenderRoleCode: mi.SenderRoleCode,
ReceiverNumber: mi.ReceiverNumber,
ReceiverRoleCode: mi.ReceiverRoleCode,
CreatedAt: mi.CreatedAt,
BusinessReason: mi.BusinessReason))
.ToList()
.AsReadOnly();
}
}
15 changes: 15 additions & 0 deletions source/ArchivedMessages.Domain/ArchivedMessages.Domain.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>Energinet.DataHub.EDI.ArchivedMessages.Domain</AssemblyName>
<RootNamespace>Energinet.DataHub.EDI.ArchivedMessages.Domain</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.11.20">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BuildingBlocks.Domain\BuildingBlocks.Domain.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2020 Energinet DataHub A/S
//
// Licensed under the Apache License, Version 2.0 (the "License2");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Energinet.DataHub.EDI.ArchivedMessages.Domain.Exceptions;

public class InvalidEnumMappingException : Exception
{
public InvalidEnumMappingException()
{
}

public InvalidEnumMappingException(string message)
: base(message)
{
}

public InvalidEnumMappingException(string message, Exception innerException)
: base(message, innerException)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using Energinet.DataHub.EDI.ArchivedMessages.Interfaces;
using Energinet.DataHub.EDI.ArchivedMessages.Domain.Models;

namespace Energinet.DataHub.EDI.ArchivedMessages.Infrastructure;
namespace Energinet.DataHub.EDI.ArchivedMessages.Interfaces;

/// <summary>
/// Responsible for archiving messages.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,47 +15,14 @@
using Energinet.DataHub.EDI.BuildingBlocks.Domain.Models;
using NodaTime;

namespace Energinet.DataHub.EDI.ArchivedMessages.Interfaces;
namespace Energinet.DataHub.EDI.ArchivedMessages.Domain.Models;

public class ArchivedMessage
{
public static readonly FileStorageCategory FileStorageCategory = ArchivedFile.FileStorageCategory;

/// <summary>
/// Created an ArchivedMessage from a market document (typically from a outgoing message)
/// </summary>
public ArchivedMessage(
string? messageId,
IReadOnlyList<EventId> eventIds,
string documentType,
ActorNumber senderNumber,
ActorRole senderRole,
ActorNumber receiverNumber,
ActorRole receiverRole,
Instant createdAt,
string? businessReason,
ArchivedMessageType archivedMessageType,
IMarketDocumentStream marketDocumentStream,
MessageId? relatedToMessageId = null)
: this(messageId, eventIds, documentType, senderNumber, senderRole, receiverNumber, receiverRole, createdAt, businessReason, archivedMessageType, new ArchivedMessageStream(marketDocumentStream), relatedToMessageId) { }

/// <summary>
/// Creates an ArchivedMessage for an incoming message
/// </summary>
public ArchivedMessage(
string? messageId,
string documentType,
ActorNumber senderNumber,
ActorRole senderRole,
ActorNumber receiverNumber,
ActorRole receiverRole,
Instant createdAt,
string? businessReason,
ArchivedMessageType archivedMessageType,
IIncomingMarketMessageStream incomingMarketMessageStream)
: this(messageId, Array.Empty<EventId>(), documentType, senderNumber, senderRole, receiverNumber, receiverRole, createdAt, businessReason, archivedMessageType, new ArchivedMessageStream(incomingMarketMessageStream)) { }

internal ArchivedMessage(
ArchivedMessageId id,
string? messageId,
IReadOnlyList<EventId> eventIds,
string documentType,
Expand All @@ -69,7 +36,7 @@ internal ArchivedMessage(
ArchivedMessageStream archivedMessageStream,
MessageId? relatedToMessageId = null)
{
Id = ArchivedMessageId.Create();
Id = id;
MessageId = messageId;
EventIds = eventIds;
DocumentType = documentType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Energinet.DataHub.EDI.ArchivedMessages.Interfaces;
namespace Energinet.DataHub.EDI.ArchivedMessages.Domain.Models;

public record ArchivedMessageId(Guid Value)
{
Expand Down
Loading

0 comments on commit 05a516c

Please sign in to comment.