refactor: remove PdfMetadata/PdfAMetadata, use result DTOs directly

PdfMetadata and PdfAMetadata were redundant intermediate classes that
mirrored PdfValidationResult and PdfAValidationResult exactly.

Changes:
- Delete PdfMetadata.cs and PdfAMetadata.cs
- IPdfProcessor.ValidateAsync now returns PdfValidationResult directly
- IPdfProcessor.ValidatePdfAAsync now returns PdfAValidationResult directly
- ValidatePdfQueryHandler: remove IMapper dependency, return result directly
- ValidatePdfAQueryHandler: remove IMapper dependency, return result directly
- MappingProfile: remove the two now-obsolete CreateMap calls
- PdfValidationResult: add IsEncrypted parameter (was missing)
This commit is contained in:
2026-08-28 11:45:33 +02:00
parent 9cb964379f
commit ef78fb5cdd
7 changed files with 9 additions and 88 deletions

View File

@@ -1,34 +0,0 @@
namespace DocumentService.Application.Common.DTOs;
/// <summary>
/// PDF/A validation metadata including conformance level and validation errors/warnings
/// </summary>
public sealed class PdfAMetadata(
bool isValid,
string pdfVersion,
int pageCount,
long fileSizeBytes,
bool encrypted,
string? pdfaVersion,
bool pdfaCompliant,
IReadOnlyList<string> errors,
IReadOnlyList<string> warnings)
{
public bool IsValid { get; } = isValid;
public string PdfVersion { get; } = pdfVersion;
public int PageCount { get; } = pageCount;
public long FileSizeBytes { get; } = fileSizeBytes;
public bool Encrypted { get; } = encrypted;
public string? PdfAVersion { get; } = pdfaVersion;
public bool PdfACompliant { get; } = pdfaCompliant;
public IReadOnlyList<string> Errors { get; } = errors;
public IReadOnlyList<string> Warnings { get; } = warnings;
// Computed property
public double FileSizeMB => FileSizeBytes / 1024.0 / 1024.0;
public override string ToString()
{
return $"PDF/A: {PdfAVersion ?? "None"}, {PageCount} pages, {FileSizeMB:F2} MB, Compliant: {PdfACompliant}";
}
}

View File

@@ -1,23 +0,0 @@
namespace DocumentService.Application.Common.DTOs;
public sealed class PdfMetadata(
int pageCount,
long fileSizeBytes,
string pdfVersion,
bool hasAttachments,
int attachmentCount)
{
public int PageCount { get; } = pageCount;
public long FileSizeBytes { get; } = fileSizeBytes;
public string PdfVersion { get; } = pdfVersion;
public bool HasAttachments { get; } = hasAttachments;
public int AttachmentCount { get; } = attachmentCount;
// Computed Property (berechnet aus FileSizeBytes)
public double FileSizeMB => FileSizeBytes / 1024.0 / 1024.0;
public override string ToString()
{
return $"PDF: {PageCount} pages, {FileSizeMB:F2} MB, Version {PdfVersion}, Attachments: {AttachmentCount}";
}
}

View File

@@ -9,10 +9,12 @@ namespace DocumentService.Application.Common.DTOs;
/// <param name="PdfVersion">PDF-Version (z.B. "1.4")</param>
/// <param name="HasAttachments">Hat das PDF Anhänge?</param>
/// <param name="AttachmentCount">Anzahl der Anhänge</param>
/// <param name="IsEncrypted">Ist das PDF passwortgeschützt/verschlüsselt?</param>
public record PdfValidationResult(
int PageCount,
long FileSizeBytes,
double FileSizeMB,
string PdfVersion,
bool HasAttachments,
int AttachmentCount);
int AttachmentCount,
bool IsEncrypted);

View File

@@ -15,7 +15,7 @@ public interface IPdfProcessor
/// <exception cref="Domain.Common.Exceptions.BadRequestException">
/// Thrown when stream is empty, invalid, or not positioned at the beginning
/// </exception>
Task<PdfMetadata> ValidateAsync(Stream pdfStream);
Task<PdfValidationResult> ValidateAsync(Stream pdfStream);
/// <summary>
/// Validates a PDF/A document and checks conformance level.
@@ -28,7 +28,7 @@ public interface IPdfProcessor
/// <exception cref="Domain.Common.Exceptions.BadRequestException">
/// Thrown when stream is empty, invalid, or not positioned at the beginning
/// </exception>
Task<PdfAMetadata> ValidatePdfAAsync(Stream pdfStream);
Task<PdfAValidationResult> ValidatePdfAAsync(Stream pdfStream);
/// <summary>
/// Checks for embedded files (attachments) in a PDF document and returns detailed metadata.

View File

@@ -13,12 +13,6 @@ public class MappingProfile : Profile
{
public MappingProfile()
{
// PdfMetadata -> PdfValidationResult
CreateMap<PdfMetadata, PdfValidationResult>();
// PdfAMetadata -> PdfAValidationResult
CreateMap<PdfAMetadata, PdfAValidationResult>()
.ForMember(dest => dest.FileSize, opt => opt.MapFrom(src => src.FileSizeBytes));
// Codecrete Bill -> SwissQrBillDto
CreateMap<Bill, SwissQrBillDto>()

View File

@@ -1,4 +1,3 @@
using AutoMapper;
using DocumentService.Application.Common.DTOs;
using DocumentService.Application.Common.Interfaces;
using MediatR;
@@ -18,20 +17,12 @@ public record ValidatePdfQuery : IRequest<PdfValidationResult>
/// <summary>
/// Handler for ValidatePdfQuery
/// Orchestrates PDF validation using IPdfProcessor and AutoMapper
/// </summary>
public class ValidatePdfQueryHandler(IPdfProcessor PdfProcessor, IMapper Mapper)
public class ValidatePdfQueryHandler(IPdfProcessor pdfProcessor)
: IRequestHandler<ValidatePdfQuery, PdfValidationResult>
{
/// <summary>
/// Validates PDF and returns metadata
/// </summary>
public async Task<PdfValidationResult> Handle(ValidatePdfQuery request, CancellationToken cancellationToken)
{
// Call DevExpress service directly with stream (exceptions propagate naturally)
var metadata = await PdfProcessor.ValidateAsync(request.PdfStream);
// Map DTO to response DTO using AutoMapper
return Mapper.Map<PdfValidationResult>(metadata);
return await pdfProcessor.ValidateAsync(request.PdfStream);
}
}

View File

@@ -1,4 +1,3 @@
using AutoMapper;
using DocumentService.Application.Common.DTOs;
using DocumentService.Application.Common.Interfaces;
using MediatR;
@@ -18,20 +17,12 @@ public record ValidatePdfAQuery : IRequest<PdfAValidationResult>
/// <summary>
/// Handler for ValidatePdfAQuery
/// Orchestrates PDF/A validation using IPdfProcessor and AutoMapper
/// </summary>
public class ValidatePdfAQueryHandler(IPdfProcessor PdfProcessor, IMapper Mapper)
public class ValidatePdfAQueryHandler(IPdfProcessor pdfProcessor)
: IRequestHandler<ValidatePdfAQuery, PdfAValidationResult>
{
/// <summary>
/// Validates PDF/A and returns metadata with conformance level
/// </summary>
public async Task<PdfAValidationResult> Handle(ValidatePdfAQuery request, CancellationToken cancellationToken)
{
// Call DevExpress service directly with stream (exceptions propagate naturally)
var metadata = await PdfProcessor.ValidatePdfAAsync(request.PdfStream);
// Map DTO to response DTO using AutoMapper
return Mapper.Map<PdfAValidationResult>(metadata);
return await pdfProcessor.ValidatePdfAAsync(request.PdfStream);
}
}