diff --git a/Application/AnnotationOperations/Queries/FetchAnnotationFromEncyclopediaId/FetchAnnotationFromEncyclopediaIdQuery.cs b/Application/AnnotationOperations/Queries/FetchAnnotationFromEncyclopediaId/FetchAnnotationFromEncyclopediaIdQuery.cs new file mode 100644 index 0000000..9815d23 --- /dev/null +++ b/Application/AnnotationOperations/Queries/FetchAnnotationFromEncyclopediaId/FetchAnnotationFromEncyclopediaIdQuery.cs @@ -0,0 +1,6 @@ +using Application.Common.Abstractions.Messaging; +using Domain.Entities; + +namespace Application.AnnotationOperations.Queries.FetchAnnotationFromEncyclopediaId; + +public sealed record FetchAnnotationFromEncyclopediaIdQuery(int EncyclopediaId): IQuery; \ No newline at end of file diff --git a/Application/AnnotationOperations/Queries/FetchAnnotationFromEncyclopediaId/FetchAnnotationFromEncyclopediaIdQueryHandler.cs b/Application/AnnotationOperations/Queries/FetchAnnotationFromEncyclopediaId/FetchAnnotationFromEncyclopediaIdQueryHandler.cs new file mode 100644 index 0000000..3e66b60 --- /dev/null +++ b/Application/AnnotationOperations/Queries/FetchAnnotationFromEncyclopediaId/FetchAnnotationFromEncyclopediaIdQueryHandler.cs @@ -0,0 +1,18 @@ +using Application.Common.Abstractions.Messaging; +using Application.Common.Databases; +using Domain.Entities; +using Domain.Shared; +using Microsoft.Extensions.Logging; + +namespace Application.AnnotationOperations.Queries.FetchAnnotationFromEncyclopediaId; + +public sealed class FetchAnnotationFromEncyclopediaIdQueryHandler( + IAnnotationRepository annotationRepository, + IEncyclopediaRepository encyclopediaRepository, + ILogger logger) : IQueryHandler +{ + public async Task> Handle(FetchAnnotationFromEncyclopediaIdQuery request, CancellationToken cancellationToken) + { + return await annotationRepository.FetchAnnotationFromEncyclopedia(request.EncyclopediaId, cancellationToken); + } +} \ No newline at end of file diff --git a/Application/AnnotationOperations/Queries/FetchAnnotationFromId/FetchAnnotationFromIdQuery.cs b/Application/AnnotationOperations/Queries/FetchAnnotationFromId/FetchAnnotationFromIdQuery.cs new file mode 100644 index 0000000..2819d75 --- /dev/null +++ b/Application/AnnotationOperations/Queries/FetchAnnotationFromId/FetchAnnotationFromIdQuery.cs @@ -0,0 +1,6 @@ +using Application.Common.Abstractions.Messaging; +using Domain.Entities; + +namespace Application.AnnotationOperations.Queries.FetchAnnotationFromId; + +public sealed record FetchAnnotationFromIdQuery(int id): IQuery; \ No newline at end of file diff --git a/Application/AnnotationOperations/Queries/FetchAnnotationFromId/FetchAnnotationFromIdQueryHandler.cs b/Application/AnnotationOperations/Queries/FetchAnnotationFromId/FetchAnnotationFromIdQueryHandler.cs new file mode 100644 index 0000000..0ca86ba --- /dev/null +++ b/Application/AnnotationOperations/Queries/FetchAnnotationFromId/FetchAnnotationFromIdQueryHandler.cs @@ -0,0 +1,17 @@ +using Application.Common.Abstractions.Messaging; +using Application.Common.Databases; +using Domain.Entities; +using Domain.Shared; + +namespace Application.AnnotationOperations.Queries.FetchAnnotationFromId; + +public class FetchAnnotationFromIdQueryHandler( + IAnnotationRepository repository + ): IQueryHandler +{ + public async Task> Handle(FetchAnnotationFromIdQuery request, + CancellationToken cancellationToken) + { + return await repository.FetchAnnotationFromId(request.id, cancellationToken); + } +} \ No newline at end of file diff --git a/Application/Common/Databases/IAnnotationRepository.cs b/Application/Common/Databases/IAnnotationRepository.cs new file mode 100644 index 0000000..f0bc330 --- /dev/null +++ b/Application/Common/Databases/IAnnotationRepository.cs @@ -0,0 +1,10 @@ +using Domain.Entities; +using Domain.Shared; + +namespace Application.Common.Databases; + +public interface IAnnotationRepository +{ + Task> FetchAnnotationFromEncyclopedia(int encyclopediaId, CancellationToken cancellationToken); + Task> FetchAnnotationFromId(int id, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/Application/Common/Databases/IEncyclopediaRepository.cs b/Application/Common/Databases/IEncyclopediaRepository.cs new file mode 100644 index 0000000..397ce3b --- /dev/null +++ b/Application/Common/Databases/IEncyclopediaRepository.cs @@ -0,0 +1,9 @@ +using Domain.Entities; +using Domain.Shared; + +namespace Application.Common.Databases; + +public interface IEncyclopediaRepository +{ + Task> FetchEncyclopedia(CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/Application/Common/Databases/IThemeRepository.cs b/Application/Common/Databases/IThemeRepository.cs new file mode 100644 index 0000000..4f269b8 --- /dev/null +++ b/Application/Common/Databases/IThemeRepository.cs @@ -0,0 +1,6 @@ +namespace Application.Common.Databases; + +public class IThemeRepository +{ + +} \ No newline at end of file diff --git a/Application/Common/Mappers/AnnotationToDtoMapper.cs b/Application/Common/Mappers/AnnotationToDtoMapper.cs new file mode 100644 index 0000000..38b0282 --- /dev/null +++ b/Application/Common/Mappers/AnnotationToDtoMapper.cs @@ -0,0 +1,24 @@ +using Application.DTO; +using Domain.Entities; + +namespace Application.Common.Mappers; + +public class AnnotationToDtoMapper +{ + public AnnotationDto Map(Annotation annotation) + { + AnnotationDto annotationDto = new AnnotationDto( + annotation.Id, + annotation.Title, + annotation.StartPage, + annotation.EndPage, + annotation.ContentUrl, + annotation.Tags, + annotation.Date, + annotation.Theme.Id, + annotation.Encyclopedia.Id + ); + + return annotationDto; + } +} \ No newline at end of file diff --git a/Application/Common/Mappers/ContentTableToDtoMapper.cs b/Application/Common/Mappers/ContentTableToDtoMapper.cs new file mode 100644 index 0000000..e2daf63 --- /dev/null +++ b/Application/Common/Mappers/ContentTableToDtoMapper.cs @@ -0,0 +1,25 @@ +using Application.DTO; +using Domain.Entities; +using Domain.Shared; + +namespace Application.Common.Mappers; + +public class ContentTableToDtoMapper +{ + public List Map(ContentTable contentTable) + { + List contentTableDto = new List(); + + foreach (ContentTableEntry entry in contentTable.Entries) + { + List notesDto = new List(); + foreach (Annotation note in entry.Notes) + { + notesDto.Add(new NoteIdDto(note.Id, note.Title)); + } + contentTableDto.Add(new ContentTableEntryDto(entry.Id, entry.ThemeName, notesDto)); + } + + return contentTableDto; + } +} \ No newline at end of file diff --git a/Application/Common/Mappers/EncyclopediaListAnswerListDtoMapper.cs b/Application/Common/Mappers/EncyclopediaListAnswerListDtoMapper.cs new file mode 100644 index 0000000..9c02422 --- /dev/null +++ b/Application/Common/Mappers/EncyclopediaListAnswerListDtoMapper.cs @@ -0,0 +1,21 @@ +using Application.DTO; +using Domain.Entities; +using Domain.Shared; + +namespace Application.Common.Mappers; + +public class EncyclopediaListAnswerListDtoMapper +{ + public AnswerListDto Map(EncyclopediaList list) + { + List encyclopediaDtos = new List(); + EncyclopediaToDtoMapper mapper = new EncyclopediaToDtoMapper(); + + foreach (Encyclopedia encyclopedia in list.List) + { + encyclopediaDtos.Add(mapper.Map(encyclopedia)); + } + + return new AnswerListDto(true, encyclopediaDtos, Error.Empty()); + } +} \ No newline at end of file diff --git a/Application/Common/Mappers/EncyclopediaToDtoMapper.cs b/Application/Common/Mappers/EncyclopediaToDtoMapper.cs new file mode 100644 index 0000000..c29fa97 --- /dev/null +++ b/Application/Common/Mappers/EncyclopediaToDtoMapper.cs @@ -0,0 +1,19 @@ +using Application.DTO; +using Domain.Entities; + +namespace Application.Common.Mappers; + +public class EncyclopediaToDtoMapper +{ + public EncyclopediaDto Map(Encyclopedia encyclopedia) + { + EncyclopediaDto encyclopediaDto = new EncyclopediaDto( + encyclopedia.Id, + encyclopedia.Title, + encyclopedia.Scribe.Id, + encyclopedia.Scribe.Name + ); + + return encyclopediaDto; + } +} \ No newline at end of file diff --git a/Application/DTO/AnnotationDto.cs b/Application/DTO/AnnotationDto.cs index e2bbc38..e61a32a 100644 --- a/Application/DTO/AnnotationDto.cs +++ b/Application/DTO/AnnotationDto.cs @@ -1,13 +1,13 @@ namespace Application.DTO; public record AnnotationDto( - Guid Id, + int Id, string Title, int StartPage, int LastPage, string ContentUrl, string Tags, DateOnly Date, - Guid ThemeId, - Guid EncyclopediaId + int ThemeId, + int EncyclopediaId ): IDto; \ No newline at end of file diff --git a/Application/DTO/AnswerDto.cs b/Application/DTO/AnswerDto.cs new file mode 100644 index 0000000..0260a52 --- /dev/null +++ b/Application/DTO/AnswerDto.cs @@ -0,0 +1,5 @@ +using Domain.Shared; + +namespace Application.DTO; + +public record AnswerDto(bool Success, IDto Value, Error error); \ No newline at end of file diff --git a/Application/DTO/AnswerListDto.cs b/Application/DTO/AnswerListDto.cs new file mode 100644 index 0000000..c8106c6 --- /dev/null +++ b/Application/DTO/AnswerListDto.cs @@ -0,0 +1,5 @@ +using Domain.Shared; + +namespace Application.DTO; + +public record AnswerListDto(bool Success, List Value, Error error); \ No newline at end of file diff --git a/Application/DTO/ContentTableEntryDto.cs b/Application/DTO/ContentTableEntryDto.cs new file mode 100644 index 0000000..7a7980f --- /dev/null +++ b/Application/DTO/ContentTableEntryDto.cs @@ -0,0 +1,3 @@ +namespace Application.DTO; + +public sealed record ContentTableEntryDto(int Id, string ThemeName, List notes): IDto; \ No newline at end of file diff --git a/Application/DTO/EncyclopediaDto.cs b/Application/DTO/EncyclopediaDto.cs index 854cecd..d2d8c07 100644 --- a/Application/DTO/EncyclopediaDto.cs +++ b/Application/DTO/EncyclopediaDto.cs @@ -1,7 +1,8 @@ namespace Application.DTO; public record EncyclopediaDto( - Guid Id, + int Id, string Title, - Guid ScribeId + Guid ScribeId, + string ScribeName ): IDto; \ No newline at end of file diff --git a/Application/DTO/IDto.cs b/Application/DTO/IDto.cs index 4e9e1ea..4d78895 100644 --- a/Application/DTO/IDto.cs +++ b/Application/DTO/IDto.cs @@ -1,5 +1,10 @@ +using System.Text.Json.Serialization; + namespace Application.DTO; +[JsonDerivedType(typeof(EncyclopediaDto), typeDiscriminator: "encyclopedia")] +[JsonDerivedType(typeof(ContentTableEntryDto), typeDiscriminator: "contentTableEntry")] + public interface IDto { diff --git a/Application/DTO/NoteIdDto.cs b/Application/DTO/NoteIdDto.cs new file mode 100644 index 0000000..b7fdf93 --- /dev/null +++ b/Application/DTO/NoteIdDto.cs @@ -0,0 +1,3 @@ +namespace Application.DTO; + +public sealed record NoteIdDto(int Id, string Title): IDto; \ No newline at end of file diff --git a/Application/DTO/NoteInformationsDto.cs b/Application/DTO/NoteInformationsDto.cs new file mode 100644 index 0000000..faaa38e --- /dev/null +++ b/Application/DTO/NoteInformationsDto.cs @@ -0,0 +1,3 @@ +namespace Application.DTO; + +public sealed record NoteInformationsDto(int Id, string ContentUrl, int StartPage, int EndPage, string Tags, DateOnly Date): IDto; \ No newline at end of file diff --git a/Application/EncyclopediaOperations/Queries/FetchEncyclopedia/FetchEncyclopediaQuery.cs b/Application/EncyclopediaOperations/Queries/FetchEncyclopedia/FetchEncyclopediaQuery.cs new file mode 100644 index 0000000..d33de7c --- /dev/null +++ b/Application/EncyclopediaOperations/Queries/FetchEncyclopedia/FetchEncyclopediaQuery.cs @@ -0,0 +1,6 @@ +using Application.Common.Abstractions.Messaging; +using Domain.Entities; + +namespace Application.EncyclopediaOperations.Queries.FetchEncyclopedia; + +public sealed record FetchEncyclopediaQuery(): IQuery; \ No newline at end of file diff --git a/Application/EncyclopediaOperations/Queries/FetchEncyclopedia/FetchEncyclopediaQueryHandler.cs b/Application/EncyclopediaOperations/Queries/FetchEncyclopedia/FetchEncyclopediaQueryHandler.cs new file mode 100644 index 0000000..dad315b --- /dev/null +++ b/Application/EncyclopediaOperations/Queries/FetchEncyclopedia/FetchEncyclopediaQueryHandler.cs @@ -0,0 +1,19 @@ +using Application.Common.Abstractions.Messaging; +using Application.Common.Databases; +using Domain.Entities; +using Domain.Shared; +using Microsoft.Extensions.Logging; + +namespace Application.EncyclopediaOperations.Queries.FetchEncyclopedia; + +public sealed class FetchEncyclopediaQueryHandler( + IEncyclopediaRepository repository, + ILogger logger) : IQueryHandler +{ + public async Task> Handle(FetchEncyclopediaQuery request, CancellationToken cancellationToken) + { + Result result = await repository.FetchEncyclopedia(cancellationToken); + + return new Result(result.Value, result.Error, result.Succeeded); + } +} \ No newline at end of file diff --git a/Application/Services/AnnotationInformation/AnnotationInformationService.cs b/Application/Services/AnnotationInformation/AnnotationInformationService.cs new file mode 100644 index 0000000..a40f318 --- /dev/null +++ b/Application/Services/AnnotationInformation/AnnotationInformationService.cs @@ -0,0 +1,26 @@ +using Application.AnnotationOperations.Queries.FetchAnnotationFromId; +using Application.Common.Mappers; +using Application.DTO; +using Domain.Entities; +using Domain.Errors; +using Domain.Shared; +using MediatR; +using Microsoft.Extensions.Logging; + +namespace Application.Services.AnnotationInformation; + +public class AnnotationInformationService(ISender sender, ILogger logger): IAnnotationInformationService +{ + public async Task HandleAnnotationInformationAsync(int id, CancellationToken cancellationToken) + { + AnswerDto result; + AnnotationToDtoMapper mapper = new AnnotationToDtoMapper(); + AnnotationInformationServiceErrors errors = new AnnotationInformationServiceErrors(); + + Result annotation = await sender.Send(new FetchAnnotationFromIdQuery(id), cancellationToken); + + return annotation.Succeeded + ? new AnswerDto(true, mapper.Map(annotation.Value), Error.Empty()) + : new AnswerDto(false, mapper.Map(Annotation.Empty()), annotation.Error); + } +} \ No newline at end of file diff --git a/Application/Services/AnnotationInformation/IAnnotationInformationService.cs b/Application/Services/AnnotationInformation/IAnnotationInformationService.cs new file mode 100644 index 0000000..685d743 --- /dev/null +++ b/Application/Services/AnnotationInformation/IAnnotationInformationService.cs @@ -0,0 +1,8 @@ +using Application.DTO; + +namespace Application.Services.AnnotationInformation; + +public interface IAnnotationInformationService +{ + Task HandleAnnotationInformationAsync(int annotationId, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/Application/Services/ContentTableSearch/ContentTableService.cs b/Application/Services/ContentTableSearch/ContentTableService.cs new file mode 100644 index 0000000..d464b57 --- /dev/null +++ b/Application/Services/ContentTableSearch/ContentTableService.cs @@ -0,0 +1,62 @@ +using Application.AnnotationOperations.Queries.FetchAnnotationFromEncyclopediaId; +using Application.Common.Mappers; +using Application.DTO; +using Domain.Entities; +using Domain.Errors; +using Domain.Shared; +using MediatR; +using Microsoft.Extensions.Logging; + +namespace Application.Services.ContentTableSearch; + +public class ContentTableService (ISender sender, ILogger logger): IContentTableService +{ + private readonly ContentTableServiceErrors _errors = new(); + private readonly ContentTableToDtoMapper _mapper = new(); + + public async Task HandleContentTableAsync(int encyclopediaId, CancellationToken cancellationToken) + { + Result annotationsList = await sender.Send(new FetchAnnotationFromEncyclopediaIdQuery(encyclopediaId), cancellationToken); + + return annotationsList.Succeeded + ? BuildContentTable(annotationsList.Value) + : new AnswerListDto(false, new List(), annotationsList.Error); + } + + private AnswerListDto BuildContentTable(AnnotationList annotationsList) + { + List contentTableEntries = []; + List annotations = annotationsList.Annotations; + List themes = annotations + .Select(a => a.Theme) + .Distinct() + .ToList(); + + foreach (Annotation annotation in annotations) + { + Theme theme = annotation.Theme; + + List tmpNotes = annotations + .Where(a => a.Theme.Id == theme.Id) + .ToList(); + + Result tmpContentTableEntry = + ContentTableEntry.Create(theme.Id, theme.Name, tmpNotes); + + if (tmpContentTableEntry.Failed) + { + return new AnswerListDto(false, new List(), _errors.ContentTableEntryCreationError(tmpContentTableEntry.Error)); + } + + contentTableEntries.Add(tmpContentTableEntry.Value); + } + + Result tmpContentTable = ContentTable.Create(contentTableEntries); + + AnswerListDto result = tmpContentTable.Succeeded + ? new AnswerListDto(true, _mapper.Map(tmpContentTable.Value), Error.Empty()) + : new AnswerListDto(false, new List(), _errors.ContentTableCreationError(tmpContentTable.Error)); + + return result; + } +} \ No newline at end of file diff --git a/Application/Services/ContentTableSearch/IContentTableService.cs b/Application/Services/ContentTableSearch/IContentTableService.cs new file mode 100644 index 0000000..d609f5e --- /dev/null +++ b/Application/Services/ContentTableSearch/IContentTableService.cs @@ -0,0 +1,8 @@ +using Application.DTO; + +namespace Application.Services.ContentTableSearch; + +public interface IContentTableService +{ + Task HandleContentTableAsync(int encyclopediaId, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/Application/Services/EncyclopediaSearch/EncyclopediaSearchService.cs b/Application/Services/EncyclopediaSearch/EncyclopediaSearchService.cs new file mode 100644 index 0000000..b3167ae --- /dev/null +++ b/Application/Services/EncyclopediaSearch/EncyclopediaSearchService.cs @@ -0,0 +1,20 @@ +using Application.Common.Mappers; +using Application.DTO; +using Application.EncyclopediaOperations.Queries.FetchEncyclopedia; +using Domain.Entities; +using Domain.Shared; +using MediatR; +using Microsoft.Extensions.Logging; + +namespace Application.Services.EncyclopediaSearch; + +public class EncyclopediaSearchService(ISender sender, ILogger logger): IEncyclopediaSearchService +{ + public async Task HandleEncyclopediaSearchAsync(CancellationToken cancellationToken) + { + EncyclopediaListAnswerListDtoMapper mapper = new EncyclopediaListAnswerListDtoMapper(); + Result encyclopediaList = await sender.Send(new FetchEncyclopediaQuery(), cancellationToken); + + return mapper.Map(encyclopediaList.Value); + } +} \ No newline at end of file diff --git a/Application/Services/EncyclopediaSearch/IEncyclopediaSearchService.cs b/Application/Services/EncyclopediaSearch/IEncyclopediaSearchService.cs new file mode 100644 index 0000000..01f9512 --- /dev/null +++ b/Application/Services/EncyclopediaSearch/IEncyclopediaSearchService.cs @@ -0,0 +1,9 @@ +using Application.DTO; +using Domain.Shared; + +namespace Application.Services.EncyclopediaSearch; + +public interface IEncyclopediaSearchService +{ + Task HandleEncyclopediaSearchAsync(CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/Domain/Entities/Annotation.cs b/Domain/Entities/Annotation.cs index 1202486..b3e6963 100644 --- a/Domain/Entities/Annotation.cs +++ b/Domain/Entities/Annotation.cs @@ -5,22 +5,27 @@ namespace Domain.Entities; public class Annotation: IEntity { - private Guid Id { get; } - private string Title { get; } - private int StartPage { get; } - private int EndPage { get; } - private string ContentUrl { get; } - private DateOnly Date { get; } - private Theme Theme { get; } - private Encyclopedia Encyclopedia { get; } + public int Id { get; } + public string Title { get; } + public int StartPage { get; } + public int EndPage { get; } + public string ContentUrl { get; } + public string Tags { get; } + public DateOnly Date { get; } + public Theme Theme { get; } + public Encyclopedia Encyclopedia { get; } - public static Result Create(string title, int startPage, int endPage, string contentUrl, DateOnly date, + public static Result Create(int id, string title, int startPage, int endPage, string contentUrl, string tags, DateOnly date, Theme theme, Encyclopedia encyclopedia) { AnnotationErrors errors = new AnnotationErrors(); Result result; - if (String.IsNullOrEmpty(title)) + if (id <= 0) + { + result = new Result(Annotation.Empty(), errors.MissingId(), false); + } + else if (String.IsNullOrEmpty(title)) { result = new Result(Annotation.Empty(), errors.MissingTitle(), false); } @@ -50,13 +55,12 @@ public static Result Create(string title, int startPage, int endPage } else { - if (String.IsNullOrEmpty(contentUrl)) - { - contentUrl = Constants.NotImplementedContentUrl; - } + contentUrl = String.IsNullOrEmpty(contentUrl) + ? Constants.NotImplementedContentUrl + : contentUrl; result = new Result( - new Annotation(Guid.NewGuid(), title, startPage, endPage, contentUrl, date, theme, encyclopedia), + new Annotation(id, title, startPage, endPage, contentUrl, tags, date, theme, encyclopedia), Error.Empty(), true); } @@ -65,10 +69,10 @@ public static Result Create(string title, int startPage, int endPage public static Annotation Empty() { - return new Annotation(Guid.Empty, "", -1,-1, "", DateOnly.MinValue, Theme.Empty(), Encyclopedia.Empty()); + return new Annotation(-1, "", -1,-1, "", "", DateOnly.MinValue, Theme.Empty(), Encyclopedia.Empty()); } - private Annotation(Guid id, string title, int startPage, int endPage, string contentUrl, DateOnly date, Theme theme, + private Annotation(int id, string title, int startPage, int endPage, string contentUrl, string tags, DateOnly date, Theme theme, Encyclopedia encyclopedia) { Id = id; @@ -76,6 +80,7 @@ private Annotation(Guid id, string title, int startPage, int endPage, string con StartPage = startPage; EndPage = endPage; ContentUrl = contentUrl; + Tags = tags; Date = date; Theme = theme; Encyclopedia = encyclopedia; diff --git a/Domain/Entities/AnnotationList.cs b/Domain/Entities/AnnotationList.cs new file mode 100644 index 0000000..5480a60 --- /dev/null +++ b/Domain/Entities/AnnotationList.cs @@ -0,0 +1,25 @@ +using Domain.Shared; + +namespace Domain.Entities; + +public class AnnotationList: IEntity +{ + public Guid Id { get; } + public List Annotations { get; } + + public static Result Create(List annotations) + { + return new Result(new AnnotationList(Guid.NewGuid(), annotations), Error.Empty(), true); + } + + public static AnnotationList Empty() + { + return new AnnotationList(Guid.Empty, new List()); + } + + private AnnotationList(Guid id, List annotations) + { + Id = id; + Annotations = annotations; + } +} \ No newline at end of file diff --git a/Domain/Entities/ContentTable.cs b/Domain/Entities/ContentTable.cs new file mode 100644 index 0000000..4e7b8b3 --- /dev/null +++ b/Domain/Entities/ContentTable.cs @@ -0,0 +1,25 @@ +using Domain.Shared; + +namespace Domain.Entities; + +public class ContentTable : IEntity +{ + public Guid Id { get; } + public List Entries { get; } + + public static Result Create(List entries) + { + return new Result(new ContentTable(Guid.NewGuid(), entries), Error.Empty(), true); + } + + public static ContentTable Empty() + { + return new ContentTable(Guid.Empty, new List()); + } + + private ContentTable(Guid id, List entries) + { + Id = id; + Entries = entries; + } +} \ No newline at end of file diff --git a/Domain/Entities/ContentTableEntry.cs b/Domain/Entities/ContentTableEntry.cs new file mode 100644 index 0000000..7355e89 --- /dev/null +++ b/Domain/Entities/ContentTableEntry.cs @@ -0,0 +1,44 @@ +using Domain.Errors; +using Domain.Shared; + +namespace Domain.Entities; + +public class ContentTableEntry : IEntity +{ + public int Id { get; } + public string ThemeName { get; } + public List Notes { get; } + + public static Result Create(int id, string themeName, List notes) + { + ContentTableEntryErrors errors = new ContentTableEntryErrors(); + Result result; + + if (id <= 0) + { + result = new Result(ContentTableEntry.Empty(), errors.MissingId(), false); + } + else if (string.IsNullOrEmpty(themeName)) + { + result = new Result(ContentTableEntry.Empty(), errors.MissingThemeName(), false); + } + else + { + result = new Result(new ContentTableEntry(id, themeName, notes), Error.Empty(), true); + } + + return result; + } + + private ContentTableEntry(int id, string themeName, List notes) + { + Id = id; + ThemeName = themeName; + Notes = notes; + } + + public static ContentTableEntry Empty() + { + return new ContentTableEntry(-1, "", new List()); + } +} \ No newline at end of file diff --git a/Domain/Entities/Encyclopedia.cs b/Domain/Entities/Encyclopedia.cs index ca8665e..2930e3d 100644 --- a/Domain/Entities/Encyclopedia.cs +++ b/Domain/Entities/Encyclopedia.cs @@ -5,16 +5,20 @@ namespace Domain.Entities; public class Encyclopedia : IEntity { - private Guid Id { get; } - private string Title { get; } - private Scribe Scribe { get; } + public int Id { get; } + public string Title { get; } + public Scribe Scribe { get; } - public static Result Create(string title, Scribe scribe) + public static Result Create(int id, string title, Scribe scribe) { EncyclopediaErrors errors = new EncyclopediaErrors(); Result result; - - if (String.IsNullOrWhiteSpace(title)) + + if (id <= 0) + { + result = new Result(Encyclopedia.Empty(), errors.MissingId(), false); + } + else if (String.IsNullOrWhiteSpace(title)) { result = new Result(Encyclopedia.Empty(), errors.MissingTitle(), false); } @@ -22,7 +26,7 @@ public static Result Create(string title, Scribe scribe) { result = scribe.Equals(Scribe.Empty()) ? new Result(Encyclopedia.Empty(), errors.MissingScribe(), false) - : new Result(new Encyclopedia(Guid.NewGuid(), title, scribe), Error.Empty(), true); + : new Result(new Encyclopedia(id, title, scribe), Error.Empty(), true); } return result; @@ -30,10 +34,10 @@ public static Result Create(string title, Scribe scribe) public static Encyclopedia Empty() { - return new Encyclopedia(Guid.Empty, "", Scribe.Empty()); + return new Encyclopedia(-1, "", Scribe.Empty()); } - private Encyclopedia(Guid id, string title, Scribe scribe) + private Encyclopedia(int id, string title, Scribe scribe) { Id = id; Title = title; diff --git a/Domain/Entities/EncyclopediaList.cs b/Domain/Entities/EncyclopediaList.cs new file mode 100644 index 0000000..b2bde43 --- /dev/null +++ b/Domain/Entities/EncyclopediaList.cs @@ -0,0 +1,37 @@ +using Domain.Errors; +using Domain.Shared; + +namespace Domain.Entities; + +public class EncyclopediaList : IEntity +{ + public Guid Id { get; } + public List List { get; } + + public static Result Create(List encyclopedias) + { + Result result = new Result(new EncyclopediaList(Guid.NewGuid(), encyclopedias), Error.Empty(), true); + EncyclopediaListErrors errors = new EncyclopediaListErrors(); + + foreach (Encyclopedia encyclopedia in encyclopedias) + { + if (encyclopedia == Encyclopedia.Empty()) + { + result = new Result(EncyclopediaList.Empty(), errors.InvalidEncyclopedia(), false); + } + } + + return result; + } + + public static EncyclopediaList Empty() + { + return new EncyclopediaList(Guid.Empty, new List()); + } + + private EncyclopediaList(Guid id, List list) + { + Id = id; + List = list; + } +} \ No newline at end of file diff --git a/Domain/Entities/Scribe.cs b/Domain/Entities/Scribe.cs index c024f4b..a4b73ce 100644 --- a/Domain/Entities/Scribe.cs +++ b/Domain/Entities/Scribe.cs @@ -5,8 +5,8 @@ namespace Domain.Entities; public class Scribe : IEntity { - private Guid Id { get; } - private string Name { get; } + public Guid Id { get; } + public string Name { get; } public static Result Create(string name) { @@ -17,6 +17,17 @@ public static Result Create(string name) return result; } + + public static Result Create(Guid id, string name) + { + ScribeErrors errors = new ScribeErrors(); + + Result result = String.IsNullOrEmpty(name) + ? new Result(Scribe.Empty(), errors.MissingName(), false) + : new Result(new Scribe(id, name), Error.Empty(), true); + + return result; + } public static Scribe Empty() { diff --git a/Domain/Entities/Theme.cs b/Domain/Entities/Theme.cs index d6b647e..fafa403 100644 --- a/Domain/Entities/Theme.cs +++ b/Domain/Entities/Theme.cs @@ -5,43 +5,43 @@ namespace Domain.Entities; public class Theme : IEntity { - private Guid Id { get; } - private string Name { get; } - private string Folder { get; } + public int Id { get; } + public string Name { get; } + public string Folder { get; } - public static Result Create(string name, string folder) + public static Result Create(int id, string name, string folder) { ThemeErrors errors = new ThemeErrors(); Result result; - if (String.IsNullOrEmpty(name)) + if (id <= 0) + { + result = new Result(Theme.Empty(), errors.MissingId(), false); + } + else if (String.IsNullOrEmpty(name)) { result = new Result(Theme.Empty(), errors.MissingName(), false); } + else if (String.IsNullOrEmpty(folder)) + { + result = new Result(Theme.Empty(), errors.MissingFolder(), false); + } else { - if (String.IsNullOrEmpty(folder)) - { - result = new Result(new Theme(Guid.NewGuid(), name, folder), Error.Empty(), true); - - } - else - { - result = IncorrectFolder(folder) - ? new Result(Theme.Empty(), errors.InvalidFolder(), false) - : new Result(Theme.Empty(), errors.MissingFolder(), false); - } + result = IncorrectFolder(folder) + ? new Result(Theme.Empty(), errors.InvalidFolder(), false) + : new Result(new Theme(id, name, folder), Error.Empty(), true); } - + return result; } private static bool IncorrectFolder(string folder) { - return !folder.Any(Char.IsWhiteSpace); + return folder.Any(Char.IsWhiteSpace); } - private Theme(Guid id, string name, string folder) + private Theme(int id, string name, string folder) { Id = id; Name = name; @@ -50,6 +50,6 @@ private Theme(Guid id, string name, string folder) public static Theme Empty() { - return new Theme(Guid.Empty,"",""); + return new Theme(-1,"",""); } } \ No newline at end of file diff --git a/Domain/Errors/AnnotationErrors.cs b/Domain/Errors/AnnotationErrors.cs index 0570ee2..3e65c38 100644 --- a/Domain/Errors/AnnotationErrors.cs +++ b/Domain/Errors/AnnotationErrors.cs @@ -4,6 +4,11 @@ namespace Domain.Errors; public class AnnotationErrors { + public Error MissingId() + { + return new Error("Annotation.MissingId", "Annotation id must be greater than 0."); + } + public Error MissingTitle() { return new Error("Annotation.MissingTitle", "Annotation title is missing."); diff --git a/Domain/Errors/AnnotationInformationServiceErrors.cs b/Domain/Errors/AnnotationInformationServiceErrors.cs new file mode 100644 index 0000000..911f7c5 --- /dev/null +++ b/Domain/Errors/AnnotationInformationServiceErrors.cs @@ -0,0 +1,6 @@ +namespace Domain.Errors; + +public class AnnotationInformationServiceErrors +{ + +} \ No newline at end of file diff --git a/Domain/Errors/AnnotationRepositoryErrors.cs b/Domain/Errors/AnnotationRepositoryErrors.cs new file mode 100644 index 0000000..044169c --- /dev/null +++ b/Domain/Errors/AnnotationRepositoryErrors.cs @@ -0,0 +1,61 @@ +using Domain.Shared; + +namespace Domain.Errors; + +public class AnnotationRepositoryErrors +{ + public Error DatabaseConnectionError() + { + return new Error("AnnotationRepositoryErrors.DatabaseConnectionError()", "Can't connect to the database"); + } + + public Error AnnotationCreationError(int annotationId, Error error) + { + return new Error("AnnotationRepositoryErrors.AnnotationCreationError", $"Something went wrong while initiating the annotation '{annotationId}': {error.Message}"); + } + + public Error AnnotationListCreationError(Error error) + { + return new Error("AnnotationRepositoryErrors.AnnotationListCreationError", $"Something went wrong while initiating the annotation list: {error.Message}"); + } + + public Error EncyclopediaCreationError(int encyclopediaId, Error error) + { + return new Error("AnnotationRepositoryErrors.EncyclopediaCreationError", $"Something went wrong while initiating the encyclopedia '{encyclopediaId}': {error.Message}"); + } + + public Error ThemeCreationError(int annotationId, int themeId, Error error) + { + return new Error("AnnotationRepositoryErrors.ThemeCreationError", $"Something went wrong while initiating the theme '{themeId}' for the annotation '{annotationId}': {error.Message}"); + } + + public Error ScribeCreationError(string scribeId, Error error) + { + return new Error("AnnotationRepositoryErrors.ScribeCreationError", $"Something went wrong while initiating the scribe '{scribeId}': {error.Message}"); + } + + public Error AnnotationNotFound(int id) + { + return new Error("AnnotationRepositoryErrors.AnnotationNotFound", + $"No annotation found in the database for the id '{id}'."); + } + + public Error EncyclopediaNotFound(int encyclopediaId) + { + return new Error("AnnotationRepositoryErrors.EncyclopediaNotFound", + $"No encyclopedia found in the database for the id '{encyclopediaId}'."); + } + + public Error ThemeNotFound(int themeId) + { + return new Error("AnnotationRepositoryErrors.ThemeNotFound", + $"No theme found in the database for the id '{themeId}'."); + } + + public Error ScribeNotFound(string scribeId) + { + return new Error("AnnotationRepositoryErrors.ScribeNotFound", + $"No scribe found in the database for the id '{scribeId}'."); + } + +} \ No newline at end of file diff --git a/Domain/Errors/ContentTableEntryErrors.cs b/Domain/Errors/ContentTableEntryErrors.cs new file mode 100644 index 0000000..fc0561f --- /dev/null +++ b/Domain/Errors/ContentTableEntryErrors.cs @@ -0,0 +1,16 @@ +using Domain.Shared; + +namespace Domain.Errors; + +public class ContentTableEntryErrors +{ + public Error MissingId() + { + return new Error("ContentTableEntryErrors.MissingId", "The content table entry Id must be greater than 0."); + } + + public Error MissingThemeName() + { + return new Error("ContentTableEntryErrors.MissingThemeName", "The content table entry theme name is missing."); + } +} \ No newline at end of file diff --git a/Domain/Errors/ContentTableServiceErrors.cs b/Domain/Errors/ContentTableServiceErrors.cs new file mode 100644 index 0000000..1650128 --- /dev/null +++ b/Domain/Errors/ContentTableServiceErrors.cs @@ -0,0 +1,24 @@ +using Domain.Shared; + +namespace Domain.Errors; + +public class ContentTableServiceErrors +{ + public Error AnnotationListFetchingError(int encyclopediaId, Error annotationsListError) + { + return new Error("ContentTableServiceErrors.AnnotationListFetchingError", + $"An error occured while fetching the annotation list for the encyclopedia id {encyclopediaId} : {annotationsListError.Message}."); + } + + public Error ContentTableEntryCreationError(Error error) + { + return new Error("ContentTableServiceErrors.ContentTableEntryCreationError", + $"The following error occured while creating one ContentTableEntry : {error.Message}."); + } + + public Error ContentTableCreationError(Error error) + { + return new Error("ContentTableServiceErrors.ContentTableCreationError", + $"The following error occured while creating one ContentTable : {error.Message}."); + } +} \ No newline at end of file diff --git a/Domain/Errors/EncyclopediaErrors.cs b/Domain/Errors/EncyclopediaErrors.cs index 5b3575d..f35e707 100644 --- a/Domain/Errors/EncyclopediaErrors.cs +++ b/Domain/Errors/EncyclopediaErrors.cs @@ -4,6 +4,11 @@ namespace Domain.Errors; public class EncyclopediaErrors { + public Error MissingId() + { + return new Error("Encyclopedia.MissingId", "Encyclopedia Id must be greater than 0."); + } + public Error MissingTitle() { return new Error("Encyclopedia.MissingTitle", @@ -14,4 +19,5 @@ public Error MissingScribe() { return new Error("Encyclopedia.MissingScribe", "Encyclopedia Scribe can't be empty."); } + } \ No newline at end of file diff --git a/Domain/Errors/EncyclopediaListErrors.cs b/Domain/Errors/EncyclopediaListErrors.cs new file mode 100644 index 0000000..ee1a4f2 --- /dev/null +++ b/Domain/Errors/EncyclopediaListErrors.cs @@ -0,0 +1,11 @@ +using Domain.Shared; + +namespace Domain.Errors; + +public class EncyclopediaListErrors +{ + public Error InvalidEncyclopedia() + { + return new Error("EncyclopediaList.InvalidEncyclopedia", "There is an invalid Encyclopedia in the list."); + } +} \ No newline at end of file diff --git a/Domain/Errors/EncyclopediaRepositoryErrors.cs b/Domain/Errors/EncyclopediaRepositoryErrors.cs new file mode 100644 index 0000000..ebade8c --- /dev/null +++ b/Domain/Errors/EncyclopediaRepositoryErrors.cs @@ -0,0 +1,26 @@ +using Domain.Shared; + +namespace Domain.Errors; + +public class EncyclopediaRepositoryErrors +{ + public Error DatabaseConnectionError() + { + return new Error("EncyclopediaRepository.DatabaseConnectionError", "Can't connect to the database"); + } + + public Error InvalidData(int encyclopediaId, Error error) + { + return new Error("EncyclopediaRepository.InvalidData", $"Something went wrong with the fetched data for the encyclopediaId '{encyclopediaId}': {error.Message}"); + } + + public static Error EncyclopediaNotFound(int encyclopediaId) + { + return new Error("EncyclopediaRepository.NoEncyclopediaFound", $"No encyclopedia was found for the EncyclopediaId '{encyclopediaId}'."); + } + + public static Error NoScribeFound(Guid scribeId) + { + return new Error("EncyclopediaRepository.NoScribeFound", $"No scribe was found for the ScribeId '{scribeId}'."); + } +} \ No newline at end of file diff --git a/Domain/Errors/ThemeErrors.cs b/Domain/Errors/ThemeErrors.cs index 472fb2f..8f1afca 100644 --- a/Domain/Errors/ThemeErrors.cs +++ b/Domain/Errors/ThemeErrors.cs @@ -4,6 +4,11 @@ namespace Domain.Errors; public class ThemeErrors { + public Error MissingId() + { + return new Error("Theme.MissingId", "Theme id must be greater than 0."); + } + public Error MissingName() { return new Error("Theme.MissingName", "Theme name is missing."); diff --git a/Infrastructure/DependencyInjection.cs b/Infrastructure/DependencyInjection.cs index 8c45cc0..180b902 100644 --- a/Infrastructure/DependencyInjection.cs +++ b/Infrastructure/DependencyInjection.cs @@ -1,4 +1,6 @@ +using Application.Common.Databases; using Infrastructure.Context; +using Infrastructure.Repositories; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -12,6 +14,8 @@ public static IServiceCollection AddInfrastructure(this IServiceCollection servi string? serverConnectionString = configuration.GetConnectionString("ScriptoriumDatabase"); services.AddDbContext(options => options.UseMySql(serverConnectionString, ServerVersion.AutoDetect(serverConnectionString))); + services.AddScoped(); + services.AddScoped(); return services; } } \ No newline at end of file diff --git a/Infrastructure/Infrastructure.csproj b/Infrastructure/Infrastructure.csproj index a5475b4..c2c1b33 100644 --- a/Infrastructure/Infrastructure.csproj +++ b/Infrastructure/Infrastructure.csproj @@ -28,6 +28,5 @@ - diff --git a/Infrastructure/Repositories/AnnotationRepository.cs b/Infrastructure/Repositories/AnnotationRepository.cs new file mode 100644 index 0000000..fb515b1 --- /dev/null +++ b/Infrastructure/Repositories/AnnotationRepository.cs @@ -0,0 +1,191 @@ +using Application.Common.Databases; +using Domain.Entities; +using Domain.Shared; +using Domain.Errors; +using Infrastructure.Context; +using Infrastructure.Contexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Annotation = Infrastructure.Contexts.Annotation; +using Scribe = Infrastructure.Contexts.Scribe; +using Theme = Infrastructure.Contexts.Theme; + +namespace Infrastructure.Repositories; + +internal sealed class AnnotationRepository(ScriptoriumDbContext context, ILogger logger) : IAnnotationRepository +{ + private readonly AnnotationRepositoryErrors _errors = new(); + public async Task> FetchAnnotationFromEncyclopedia(int encyclopediaId, CancellationToken cancellationToken) + { + bool canConnect = await context.Database.CanConnectAsync(cancellationToken); + Result result; + + if (canConnect) + { + List queryAnnotations = await ( + from a in context.Annotations + where a.encyclopediaId == encyclopediaId + orderby a.id + select a + ).ToListAsync(cancellationToken: cancellationToken); + + List queryThemes = await ( + from t in context.Themes + orderby t.id + select t + ).ToListAsync(cancellationToken: cancellationToken); + + Result encyclopedia = await MatchingEncyclopedia(encyclopediaId); + + if (encyclopedia.Succeeded) + { + List annotations = new List(); + + foreach (Annotation annotation in queryAnnotations) + { + Result tmpAnnotation = await Map(annotation, queryThemes, encyclopedia.Value); + + if (tmpAnnotation.Succeeded) + { + annotations.Add(tmpAnnotation.Value); + } + else + { + return new Result(AnnotationList.Empty(), + _errors.AnnotationCreationError(annotation.id,tmpAnnotation.Error),false); + } + } + + Result annotationList = AnnotationList.Create(annotations); + + result = annotationList.Succeeded + ? annotationList + : new Result(AnnotationList.Empty(), _errors.AnnotationListCreationError(annotationList.Error), false); + + } + else + { + result = new Result(AnnotationList.Empty(), + encyclopedia.Error, false); + } + } + else + { + result = new Result(AnnotationList.Empty(), _errors.DatabaseConnectionError(), false); + } + + return result; + } + + public async Task> FetchAnnotationFromId(int id, CancellationToken cancellationToken) + { + Annotation? queryAnnotation = await context.Annotations.FindAsync(id, cancellationToken); + + if (queryAnnotation is not { } annotation) + { + return new Result( + Domain.Entities.Annotation.Empty(), + _errors.AnnotationNotFound(id), + false); + } + + Result result; + + List queryThemes = await ( + from t in context.Themes + orderby t.id + select t + ).ToListAsync(cancellationToken: cancellationToken); + + Result theme = await MatchingTheme(annotation.themeId); + + if (theme.Failed) + { + result = new Result(Domain.Entities.Annotation.Empty(), _errors.ThemeCreationError(annotation.id, annotation.themeId, theme.Error), false); + } + else + { + Result encyclopedia = await MatchingEncyclopedia(annotation.encyclopediaId); + + result = encyclopedia.Succeeded + ? Domain.Entities.Annotation.Create( + annotation.id, + annotation.title, + annotation.startPage, + annotation.endPage, + annotation.contentUrl, + annotation.tags, + annotation.date, + theme.Value, + encyclopedia.Value + ) + : new Result(Domain.Entities.Annotation.Empty(), _errors.EncyclopediaCreationError(annotation.encyclopediaId, theme.Error), false); + } + + return result; + } + + private async Task> MatchingTheme(int annotationThemeId) + { + Theme? queryTheme = await context.Themes.FindAsync(annotationThemeId); + + return queryTheme is not { } theme + ? new Result( + Domain.Entities.Theme.Empty(), + _errors.ThemeNotFound(annotationThemeId), + false) + : Domain.Entities.Theme.Create(theme.id, theme.name, theme.folder); + } + + private async Task> MatchingEncyclopedia(int annotationEncyclopediaId) + { + Result result; + Encyclopedium? queryEncyclopedia = await context.Encyclopedia.FindAsync(annotationEncyclopediaId); + + if (queryEncyclopedia is not { } encyclopedia) + { + return new Result(Encyclopedia.Empty(), + _errors.EncyclopediaNotFound(annotationEncyclopediaId), false); + } + + Result scribe = await MatchingScribe(queryEncyclopedia.scribeId); + + return scribe.Succeeded + ? Encyclopedia.Create(queryEncyclopedia.id, queryEncyclopedia.title, scribe.Value) + : new Result(Encyclopedia.Empty(), scribe.Error, + false); + + } + + private async Task> MatchingScribe(string scribeId) + { + Scribe? queryScribe = await context.Scribes.FindAsync(scribeId); + + return queryScribe is not { } scribe + ? new Result( + Domain.Entities.Scribe.Empty(), + _errors.ScribeNotFound(scribeId), + false) + : Domain.Entities.Scribe.Create(new Guid(scribe.id), scribe.username); + } + + private async Task> Map(Annotation queryAnnotation, List queryThemes, Encyclopedia encyclopedia) + { + Result theme = await MatchingTheme(queryAnnotation.themeId); + + return theme.Succeeded + ? Domain.Entities.Annotation.Create( + queryAnnotation.id, + queryAnnotation.title, + queryAnnotation.startPage, + queryAnnotation.endPage, + queryAnnotation.contentUrl, + queryAnnotation.tags, + queryAnnotation.date, + theme.Value, + encyclopedia + ) + : new Result(Domain.Entities.Annotation.Empty(), + _errors.ThemeCreationError(queryAnnotation.id, queryAnnotation.themeId, theme.Error), false); + } +} \ No newline at end of file diff --git a/Infrastructure/Repositories/EncyclopediaRepository.cs b/Infrastructure/Repositories/EncyclopediaRepository.cs new file mode 100644 index 0000000..227d5f9 --- /dev/null +++ b/Infrastructure/Repositories/EncyclopediaRepository.cs @@ -0,0 +1,87 @@ +using Application.Common.Databases; +using Domain.Entities; +using Domain.Errors; +using Domain.Shared; +using Infrastructure.Context; +using Infrastructure.Contexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Scribe = Infrastructure.Contexts.Scribe; + +namespace Infrastructure.Repositories; + +internal sealed class EncyclopediaRepository(ScriptoriumDbContext context, ILogger logger) : IEncyclopediaRepository +{ + public async Task> FetchEncyclopedia(CancellationToken cancellationToken) + { + EncyclopediaRepositoryErrors errors = new EncyclopediaRepositoryErrors(); + bool canConnect = await context.Database.CanConnectAsync(cancellationToken); + Result result; + + if (canConnect) + { + List queryEncyclopedias = await ( + from e in context.Encyclopedia + orderby e.id + select e + ).ToListAsync(cancellationToken: cancellationToken); + + List queryScribes = await ( + from s in context.Scribes + orderby s.id + select s + ).ToListAsync(cancellationToken: cancellationToken); + + List encyclopedias = new List(); + + foreach (Encyclopedium encyclopedia in queryEncyclopedias) + { + Result tmpEncyclopedia = Map(encyclopedia, queryScribes); + + if (tmpEncyclopedia.Failed) + { + return new Result(EncyclopediaList.Empty(), + errors.InvalidData(encyclopedia.id, tmpEncyclopedia.Error), false); + } + + encyclopedias.Add(tmpEncyclopedia.Value); + } + + result = EncyclopediaList.Create(encyclopedias); + } + else + { + result = new Result(EncyclopediaList.Empty(), errors.DatabaseConnectionError(), false); + } + + return result; + } + + private Result Map(Encyclopedium encyclopedia, List queryScribes) + { + Result matchingScribe = MatchingScribe(queryScribes, new Guid(encyclopedia.scribeId)); + if (matchingScribe.Failed) + { + return new Result(Encyclopedia.Empty(), + matchingScribe.Error, false); + } + + return Encyclopedia.Create(encyclopedia.id, encyclopedia.title, matchingScribe.Value); + } + + private Result MatchingScribe(List queryScribes, Guid scribeId) + { + Result result = new Result(Domain.Entities.Scribe.Empty(), EncyclopediaRepositoryErrors.NoScribeFound(scribeId), false); + + foreach (Scribe scribe in queryScribes) + { + Guid queryScribeId = new Guid(scribe.id); + if (queryScribeId == scribeId) + { + result = Domain.Entities.Scribe.Create(queryScribeId, scribe.username); + } + } + + return result; + } +} \ No newline at end of file diff --git a/WebApi/Controllers/AnnotationController.cs b/WebApi/Controllers/AnnotationController.cs new file mode 100644 index 0000000..60ec983 --- /dev/null +++ b/WebApi/Controllers/AnnotationController.cs @@ -0,0 +1,40 @@ +using Application.DTO; +using Application.Services.AnnotationInformation; +using Domain.Errors; +using Domain.Shared; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using WebApi.Abstraction; + +namespace WebApi.Controllers; + +[Route("api/v1/annotation")] +public class AnnotationController( + ISender sender, + IAnnotationInformationService annotationInformationService +): ApiController(sender) +{ + [HttpGet("{id}")] + public async Task Get(int id, CancellationToken cancellationToken) + { + AnswerDto result = await annotationInformationService.HandleAnnotationInformationAsync(id, cancellationToken); + IActionResult response; + + Error notFoundError = new AnnotationRepositoryErrors().AnnotationNotFound(id); + + if (result.Success) + { + response = Ok(result.Value); + } + else if(result.error.Equals(notFoundError)) + { + response = NotFound(); + } + else + { + response = BadRequest(result.error); + } + + return response; + } +} \ No newline at end of file diff --git a/WebApi/Controllers/EncyclopediaController.cs b/WebApi/Controllers/EncyclopediaController.cs new file mode 100644 index 0000000..1b38334 --- /dev/null +++ b/WebApi/Controllers/EncyclopediaController.cs @@ -0,0 +1,53 @@ +using Application.DTO; +using Application.Services.ContentTableSearch; +using Application.Services.EncyclopediaSearch; +using Domain.Errors; +using Domain.Shared; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using WebApi.Abstraction; + +namespace WebApi.Controllers; + +[Route("api/v1/encyclopedia")] +public class EncyclopediaController( + ISender sender, + IEncyclopediaSearchService encyclopediaSearchService, + IContentTableService contentTableService +): ApiController(sender) +{ + [HttpGet("filters")] + public async Task Get(CancellationToken cancellationToken) + { + AnswerListDto result = await encyclopediaSearchService.HandleEncyclopediaSearchAsync(cancellationToken); + + return result.Success + ? Ok(result.Value) + : BadRequest(result.error); + } + + [HttpGet("content-table/{encyclopediaId}")] + public async Task GetContentTable(int encyclopediaId, CancellationToken cancellationToken) + { + AnswerListDto result = await contentTableService.HandleContentTableAsync(encyclopediaId, cancellationToken); + IActionResult response; + + Error notFoundError = new AnnotationRepositoryErrors() + .EncyclopediaNotFound(encyclopediaId); + + if (result.Success) + { + response = Ok(result.Value); + } + else if (result.error.Equals(notFoundError)) + { + response = NotFound(); + } + else + { + response = BadRequest(result.error); + } + + return response; + } +} \ No newline at end of file diff --git a/WebApi/Program.cs b/WebApi/Program.cs index 19c0091..624959b 100644 --- a/WebApi/Program.cs +++ b/WebApi/Program.cs @@ -1,4 +1,7 @@ using Application; +using Application.Services.AnnotationInformation; +using Application.Services.ContentTableSearch; +using Application.Services.EncyclopediaSearch; using Infrastructure; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; @@ -10,7 +13,7 @@ builder.Host.UseSerilog((context, configuration) => { configuration - .Enrich.WithProperty("ApplicationName", "Exemple") + .Enrich.WithProperty("ApplicationName", "Scriptorium") .WriteTo.Console() .WriteTo.DurableHttpUsingFileSizeRolledBuffers( requestUri: "http://localhost://", @@ -32,9 +35,12 @@ }); builder.Services.AddEndpointsApiExplorer(); - builder.Services.AddSwaggerGen(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + builder.Services .AddApplication(builder.Configuration) .AddInfrastructure(builder.Configuration) diff --git a/WebApi/WebApi.csproj b/WebApi/WebApi.csproj index e096ff5..683a9ca 100644 --- a/WebApi/WebApi.csproj +++ b/WebApi/WebApi.csproj @@ -28,8 +28,4 @@ - - - -