diff --git a/source/ArchivedMessages.Application/Mapping/ArchivedMessageMapper.cs b/source/ArchivedMessages.Application/Mapping/ArchivedMessageMapper.cs index b53674cbc6..9c387323dc 100644 --- a/source/ArchivedMessages.Application/Mapping/ArchivedMessageMapper.cs +++ b/source/ArchivedMessages.Application/Mapping/ArchivedMessageMapper.cs @@ -12,8 +12,10 @@ // 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; @@ -21,7 +23,9 @@ internal static class ArchivedMessageMapper { internal static ArchivedMessage Map(ArchivedMessageDto dto) { - return new ArchivedMessage( + return !EnumCompatibilityChecker.AreEnumsCompatible() + ? 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, diff --git a/source/ArchivedMessages.Application/Mapping/GetMessagesQueryMapper.cs b/source/ArchivedMessages.Application/Mapping/GetMessagesQueryMapper.cs index 55866a9c2b..c260fbd04c 100644 --- a/source/ArchivedMessages.Application/Mapping/GetMessagesQueryMapper.cs +++ b/source/ArchivedMessages.Application/Mapping/GetMessagesQueryMapper.cs @@ -41,7 +41,7 @@ private static SortedCursorBasedPagination SetSortedCursorBasedPagination(Sorted pageSize: dto.PageSize, navigationForward: dto.NavigationForward, fieldToSortBy: SetFieldToSortBy(dto.FieldToSortBy), - sortByDirection: SetDirectionToSortBy(dto.DirectionToSortBy)); + directionToSortBy: SetDirectionToSortBy(dto.DirectionToSortBy)); } private static MessageCreationPeriod? SetMessageCreationPeriod(MessageCreationPeriodDto? messageCreationPeriod) diff --git a/source/ArchivedMessages.Domain/Exceptions/InvalidEnumMappingException.cs b/source/ArchivedMessages.Domain/Exceptions/InvalidEnumMappingException.cs new file mode 100644 index 0000000000..840e5ca608 --- /dev/null +++ b/source/ArchivedMessages.Domain/Exceptions/InvalidEnumMappingException.cs @@ -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) + { + } +} diff --git a/source/ArchivedMessages.Domain/Models/SortedCursorBasedPagination.cs b/source/ArchivedMessages.Domain/Models/SortedCursorBasedPagination.cs index fab0211c51..71a84d5211 100644 --- a/source/ArchivedMessages.Domain/Models/SortedCursorBasedPagination.cs +++ b/source/ArchivedMessages.Domain/Models/SortedCursorBasedPagination.cs @@ -23,7 +23,7 @@ public class SortedCursorBasedPagination( int pageSize = 100, bool navigationForward = true, FieldToSortBy? fieldToSortBy = null, - DirectionToSortBy? sortByDirection = null) + DirectionToSortBy? directionToSortBy = null) { /// /// The current position in the dataset. @@ -43,12 +43,12 @@ public class SortedCursorBasedPagination( /// /// The field to sort by. /// - public FieldToSortBy SortBy { get; } = fieldToSortBy ?? FieldToSortBy.CreatedAt; + public FieldToSortBy FieldToSortBy { get; } = fieldToSortBy ?? FieldToSortBy.CreatedAt; /// /// The direction to sort by. /// - public DirectionToSortBy SortByDirection { get; } = sortByDirection ?? DirectionToSortBy.Descending; + public DirectionToSortBy DirectionToSortBy { get; } = directionToSortBy ?? DirectionToSortBy.Descending; } /// diff --git a/source/ArchivedMessages.Infrastructure/QueryBuilder.cs b/source/ArchivedMessages.Infrastructure/QueryBuilder.cs index f3b93a2aaa..594e612ba5 100644 --- a/source/ArchivedMessages.Infrastructure/QueryBuilder.cs +++ b/source/ArchivedMessages.Infrastructure/QueryBuilder.cs @@ -122,7 +122,7 @@ public QueryInput BuildFrom(GetMessagesQuery query) return new QueryInput(BuildStatement(query), BuildTotalCountStatement(query), _queryParameters); } - private static string WherePaginationPosition(FieldToSortBy fieldToSortBy, DirectionToSortBy sortByDirection, SortingCursor cursor, bool isForward) + private static string WherePaginationPosition(FieldToSortBy fieldToSortBy, DirectionToSortBy directionToSortBy, SortingCursor cursor, bool isForward) { if (cursor.SortedFieldValue is null) { @@ -131,8 +131,8 @@ private static string WherePaginationPosition(FieldToSortBy fieldToSortBy, Direc } // Toggle the sort direction if navigating backwards, because sql use top to limit the result - var sortingDirection = isForward ? sortByDirection.Identifier == DirectionToSortBy.Descending.Identifier ? "<" : ">" - : sortByDirection.Identifier == DirectionToSortBy.Descending.Identifier ? ">" : "<"; + var sortingDirection = isForward ? directionToSortBy.Identifier == DirectionToSortBy.Descending.Identifier ? "<" : ">" + : directionToSortBy.Identifier == DirectionToSortBy.Descending.Identifier ? ">" : "<"; return isForward ? $""" (({fieldToSortBy.Identifier} = '{cursor.SortedFieldValue}' AND (RecordId < {cursor.RecordId} OR {cursor.RecordId} = 0)) @@ -156,7 +156,7 @@ private string BuildStatement(GetMessagesQuery query) { var whereClause = " WHERE "; whereClause += _statement.Count > 0 ? $"{string.Join(" AND ", _statement)} AND " : string.Empty; - whereClause += WherePaginationPosition(query.Pagination.SortBy, query.Pagination.SortByDirection, query.Pagination.Cursor, query.Pagination.NavigationForward); + whereClause += WherePaginationPosition(query.Pagination.FieldToSortBy, query.Pagination.DirectionToSortBy, query.Pagination.Cursor, query.Pagination.NavigationForward); string sqlStatement; if (query.IncludeRelatedMessages == true && query.MessageId is not null) @@ -183,7 +183,7 @@ private string BuildStatement(GetMessagesQuery query) sqlStatement = selectStatement + whereClause; } - sqlStatement += OrderBy(query.Pagination.SortBy, query.Pagination.SortByDirection, query.Pagination.NavigationForward); + sqlStatement += OrderBy(query.Pagination.FieldToSortBy, query.Pagination.DirectionToSortBy, query.Pagination.NavigationForward); return sqlStatement; } diff --git a/source/ArchivedMessages.IntegrationTests/ArchivedMessagesMappingTests.cs b/source/ArchivedMessages.IntegrationTests/ArchivedMessagesMappingTests.cs new file mode 100644 index 0000000000..a8135168c7 --- /dev/null +++ b/source/ArchivedMessages.IntegrationTests/ArchivedMessagesMappingTests.cs @@ -0,0 +1,50 @@ +// 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; +using Energinet.DataHub.EDI.BuildingBlocks.Domain.Validation; +using Xunit; + +namespace Energinet.DataHub.EDI.ArchivedMessages.IntegrationTests; + +public class ArchivedMessagesMappingTests +{ + private enum MismatchedEnum + { + A = 1, + B = 2, + D = 4, + } + + [Fact] + public void Given_EnumsAreLogicallyCompatible_When_Mapping_Then_ReturnTrueWhenEnumsMatch() + { + // Act + var result = EnumCompatibilityChecker.AreEnumsCompatible(); + + // Assert + Assert.True(result, "The enums should be logically compatible."); + } + + [Fact] + public void Given_EnumsAreNotLogicallyCompatible_When_Mapping_Then_ReturnFalseWhenEnumsDoNotMatch() + { + // Act + var result = EnumCompatibilityChecker.AreEnumsCompatible(); + + // Assert + Assert.False(result, "The enums should not be logically compatible."); + } +} diff --git a/source/ArchivedMessages.Interfaces/Models/SortedCursorBasedPaginationDto.cs b/source/ArchivedMessages.Interfaces/Models/SortedCursorBasedPaginationDto.cs index c08942b2ed..0f556630b9 100644 --- a/source/ArchivedMessages.Interfaces/Models/SortedCursorBasedPaginationDto.cs +++ b/source/ArchivedMessages.Interfaces/Models/SortedCursorBasedPaginationDto.cs @@ -39,12 +39,12 @@ public sealed record SortedCursorBasedPaginationDto( /// /// The field to sort by. /// - public FieldToSortByDto SortBy { get; } = FieldToSortBy ?? FieldToSortByDto.CreatedAt; + public FieldToSortByDto SortField { get; } = FieldToSortBy ?? FieldToSortByDto.CreatedAt; /// /// The direction to sort by. /// - public DirectionToSortByDto SortByDirection { get; } = DirectionToSortBy ?? DirectionToSortByDto.Descending; + public DirectionToSortByDto SortDirection { get; } = DirectionToSortBy ?? DirectionToSortByDto.Descending; } public sealed record SortingCursorDto(string? SortedFieldValue = null, long RecordId = 0); diff --git a/source/BuildingBlocks.Domain/BuildingBlocks.Domain.csproj b/source/BuildingBlocks.Domain/BuildingBlocks.Domain.csproj index f230cad237..12ff23a8d6 100644 --- a/source/BuildingBlocks.Domain/BuildingBlocks.Domain.csproj +++ b/source/BuildingBlocks.Domain/BuildingBlocks.Domain.csproj @@ -1,4 +1,4 @@ - + Energinet.DataHub.EDI.BuildingBlocks.Domain Energinet.DataHub.EDI.BuildingBlocks.Domain diff --git a/source/BuildingBlocks.Domain/Validation/EnumCompatibilityChecker.cs b/source/BuildingBlocks.Domain/Validation/EnumCompatibilityChecker.cs new file mode 100644 index 0000000000..8adab24b87 --- /dev/null +++ b/source/BuildingBlocks.Domain/Validation/EnumCompatibilityChecker.cs @@ -0,0 +1,28 @@ +// 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.BuildingBlocks.Domain.Validation; + +public static class EnumCompatibilityChecker +{ + public static bool AreEnumsCompatible() + where T1 : Enum + where T2 : Enum + { + var firstEnum = Enum.GetValues(typeof(T1)).Cast().ToDictionary(e => e.ToString(), Convert.ToInt32); + var secondEnum = Enum.GetValues(typeof(T2)).Cast().ToDictionary(e => e.ToString(), Convert.ToInt32); + + return firstEnum.All(e => secondEnum.ContainsKey(e.Key) && secondEnum[e.Key] == e.Value); + } +}