Introduced a new `WorkflowsClient` to orchestrate multi-step operations, combining `IPdfValidationClient` and `ISwissQrCodeClient`. Added methods to validate PDFs and extract Swiss QR Codes in a single call, with overloads for byte arrays, streams, and file paths. Registered `WorkflowsClient` as a scoped service in `ServiceCollectionExtensions`. Updated `PdfValidationResult` with an `IsValid` property to simplify PDF validity checks. Added `IWorkflowsClient` interface to define the contract for the new client, with detailed XML documentation for its methods.
85 lines
3.6 KiB
C#
85 lines
3.6 KiB
C#
using DocumentService.Application.Common.DTOs;
|
||
using DocumentService.Client.Interfaces;
|
||
|
||
namespace DocumentService.Client.Clients;
|
||
|
||
/// <summary>
|
||
/// Orchestrated multi-step workflows that compose multiple DocumentService clients
|
||
/// into single, higher-level operations.
|
||
/// </summary>
|
||
public class WorkflowsClient(IPdfValidationClient validation, ISwissQrCodeClient swissQrCode) : IWorkflowsClient
|
||
{
|
||
/// <inheritdoc />
|
||
public async Task<SwissQrCodeExtractionResult?> ExtractSwissQrCodeValidatedAsync(
|
||
byte[] pdfBytes,
|
||
bool raw = false,
|
||
bool throwIfInvalid = true,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
var validationResult = await validation.ValidatePdfAsync(pdfBytes, cancellationToken);
|
||
|
||
if (!validationResult.IsValid)
|
||
return throwIfInvalid
|
||
? throw new InvalidOperationException(
|
||
$"PDF validation failed (IsEncrypted={validationResult.IsEncrypted}, " +
|
||
$"PageCount={validationResult.PageCount}, FileSize={validationResult.FileSizeBytes}).")
|
||
: (SwissQrCodeExtractionResult?)null;
|
||
|
||
return await swissQrCode.ExtractSwissQrCodeAsync(pdfBytes, raw, cancellationToken);
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<SwissQrCodeExtractionResult?> ExtractSwissQrCodeValidatedAsync(
|
||
Stream pdfStream,
|
||
bool raw = false,
|
||
bool throwIfInvalid = true,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
var validationResult = await validation.ValidatePdfAsync(pdfStream, cancellationToken);
|
||
|
||
if (!validationResult.IsValid)
|
||
return throwIfInvalid
|
||
? throw new InvalidOperationException(
|
||
$"PDF validation failed (IsEncrypted={validationResult.IsEncrypted}, " +
|
||
$"PageCount={validationResult.PageCount}, FileSize={validationResult.FileSizeBytes}).")
|
||
: (SwissQrCodeExtractionResult?)null;
|
||
|
||
// Stream was consumed by validation – reset if possible, otherwise re-open is caller's responsibility.
|
||
// Since callers typically pass a FileStream or MemoryStream, Position reset covers the common case.
|
||
if (pdfStream.CanSeek)
|
||
pdfStream.Position = 0;
|
||
|
||
return await swissQrCode.ExtractSwissQrCodeAsync(pdfStream, raw, cancellationToken);
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<SwissQrCodeExtractionResult?> ExtractSwissQrCodeValidatedAsync(
|
||
string filePath,
|
||
bool raw = false,
|
||
bool throwIfInvalid = true,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
#if NETFRAMEWORK
|
||
using var stream = File.OpenRead(filePath);
|
||
var validationResult = await validation.ValidatePdfAsync(stream, cancellationToken);
|
||
#else
|
||
var pdfBytes = await File.ReadAllBytesAsync(filePath, cancellationToken);
|
||
var validationResult = await validation.ValidatePdfAsync(pdfBytes, cancellationToken);
|
||
#endif
|
||
|
||
if (!validationResult.IsValid)
|
||
return throwIfInvalid
|
||
? throw new InvalidOperationException(
|
||
$"PDF validation failed (IsEncrypted={validationResult.IsEncrypted}, " +
|
||
$"PageCount={validationResult.PageCount}, FileSize={validationResult.FileSizeBytes}).")
|
||
: (SwissQrCodeExtractionResult?)null;
|
||
|
||
#if NETFRAMEWORK
|
||
using var extractStream = File.OpenRead(filePath);
|
||
return await swissQrCode.ExtractSwissQrCodeAsync(extractStream, raw, cancellationToken);
|
||
#else
|
||
return await swissQrCode.ExtractSwissQrCodeAsync(pdfBytes, raw, cancellationToken);
|
||
#endif
|
||
}
|
||
}
|