From 5dc2e3850752d2b53b727e5ff5a3125210dfbcfa Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 20 Jul 2026 16:31:31 +0200 Subject: [PATCH] refactor(application): update processor interfaces for Stream API - IPdfProcessor: ValidateAsync, ValidatePdfAAsync, CheckAttachmentsAsync now accept Stream - ISwissQrCodeProcessor: ExtractSwissQrCodeAsync now accepts Stream - Update XML documentation: Position=0 requirement, non-seekable stream support - Exception documentation: BadRequestException for validation errors (stream empty/invalid/wrong position) --- .../Common/Interfaces/IPdfProcessor.cs | 21 +++++++++++++------ .../Interfaces/ISwissQrCodeProcessor.cs | 13 +++++++----- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/DocumentOperator.Application/Common/Interfaces/IPdfProcessor.cs b/DocumentOperator.Application/Common/Interfaces/IPdfProcessor.cs index 9c7795c..87b4a78 100644 --- a/DocumentOperator.Application/Common/Interfaces/IPdfProcessor.cs +++ b/DocumentOperator.Application/Common/Interfaces/IPdfProcessor.cs @@ -7,30 +7,39 @@ public interface IPdfProcessor /// /// Validates a PDF and extracts metadata. /// - /// PDF content as stream (caller is responsible for disposal) + /// + /// PDF document stream. Must be readable and positioned at the beginning (Position = 0). + /// Non-seekable streams are supported. Caller is responsible for disposal. + /// /// PDF metadata (page count, size, version, attachments) /// - /// Thrown when stream is empty or invalid + /// Thrown when stream is empty, invalid, or not positioned at the beginning /// Task ValidateAsync(Stream pdfStream); /// /// Validates a PDF/A document and checks conformance level. /// - /// PDF content as stream (caller is responsible for disposal) + /// + /// PDF document stream. Must be readable and positioned at the beginning (Position = 0). + /// Non-seekable streams are supported. Caller is responsible for disposal. + /// /// PDF/A metadata including conformance level and validation errors/warnings /// - /// Thrown when stream is empty or invalid + /// Thrown when stream is empty, invalid, or not positioned at the beginning /// Task ValidatePdfAAsync(Stream pdfStream); /// /// Checks for embedded files (attachments) in a PDF document and returns detailed metadata. /// - /// PDF content as stream (caller is responsible for disposal) + /// + /// PDF document stream. Must be readable and positioned at the beginning (Position = 0). + /// Non-seekable streams are supported. Caller is responsible for disposal. + /// /// Attachment information (count, file names, MIME types, sizes) /// - /// Thrown when stream is empty or invalid + /// Thrown when stream is empty, invalid, or not positioned at the beginning /// Task CheckAttachmentsAsync(Stream pdfStream); } \ No newline at end of file diff --git a/DocumentOperator.Application/Common/Interfaces/ISwissQrCodeProcessor.cs b/DocumentOperator.Application/Common/Interfaces/ISwissQrCodeProcessor.cs index baa746a..3d95887 100644 --- a/DocumentOperator.Application/Common/Interfaces/ISwissQrCodeProcessor.cs +++ b/DocumentOperator.Application/Common/Interfaces/ISwissQrCodeProcessor.cs @@ -12,18 +12,21 @@ public interface ISwissQrCodeProcessor /// Extracts and parses Swiss QR Code from a PDF document. /// Returns both parsed Bill object and raw QR text lines. /// - /// PDF document as byte array + /// + /// PDF document stream. Must be readable and positioned at the beginning (Position = 0). + /// Non-seekable streams are supported. Caller is responsible for disposal. + /// /// Optional: Specific page numbers to scan (1-indexed). If null, scans all pages starting with last page. /// Cancellation token /// Tuple: (Parsed Codecrete Bill, Raw QR lines as string array) - /// + /// /// Thrown when no Swiss QR Code is found in the specified pages /// - /// - /// Thrown when PDF processing fails + /// + /// Thrown when stream is empty or (for seekable streams) not positioned at the beginning /// Task<(Bill Bill, string[] RawLines)> ExtractSwissQrCodeAsync( - byte[] pdfBytes, + Stream pdfStream, int[]? pageNumbers = null, CancellationToken cancellationToken = default); }