1
0

Nachbearbeitung: Meilensteinbezüge aus Produktiv-JavaDoc und

package-info entfernt
This commit is contained in:
2026-04-04 11:24:06 +02:00
parent 62f9542e50
commit 9ba29aaba5
52 changed files with 105 additions and 176 deletions

View File

@@ -5,7 +5,6 @@ import java.nio.file.Path;
/**
* Typed immutable configuration model for PDF Umbenenner startup parameters.
* AP-005: Represents all M1-relevant configuration properties with strong typing.
*/
public record StartConfiguration(
Path sourceFolder,

View File

@@ -15,7 +15,7 @@ import java.util.List;
* and basic path existence checks. Throws {@link InvalidStartConfigurationException}
* if any validation rule fails.
* <p>
* M3/AP-007: Supports injected source folder validation for testability
* Supports injected source folder validation for testability
* (allows mocking of platform-dependent filesystem checks).
*/
public class StartConfigurationValidator {
@@ -246,7 +246,7 @@ public class StartConfigurationValidator {
* <p>
* Uses {@code java.nio.file.Files} static methods to check existence, type, and readability.
* <p>
* M3/AP-007: This separation allows unit tests to inject alternative implementations
* This separation allows unit tests to inject alternative implementations
* that control the outcome of readability checks without relying on actual filesystem
* permissions (which are platform-dependent).
*/

View File

@@ -10,15 +10,13 @@ package de.gecheckt.pdf.umbenenner.application.port.in;
* The outcome is independent of individual document processing results;
* it represents the batch operation itself (lock acquired, no critical startup failure, etc.).
* <p>
* Design Note: This contract is defined in AP-002 to enable AP-007 (exit code handling)
* to derive exit codes systematically without requiring additional knowledge about
* the batch run. Each outcome maps cleanly to an exit code semantic.
* Design Note: This contract enables exit code handling to derive exit codes systematically
* without requiring additional knowledge about the batch run. Each outcome maps cleanly
* to an exit code semantic.
* <p>
* AP-007: Three distinct outcomes are now defined to make the difference between a
* technically successful run, a controlled early termination due to start protection,
* and a hard bootstrap failure explicit in both code and logs.
*
* @since M2-AP-002
* Three distinct outcomes are defined to make the difference between a technically successful run,
* a controlled early termination due to start protection, and a hard bootstrap failure
* explicit in both code and logs.
*/
public enum BatchRunOutcome {
@@ -42,7 +40,6 @@ public enum BatchRunOutcome {
* <p>
* Maps to exit code 1.
*
* @since M2-AP-007
*/
LOCK_UNAVAILABLE("Another instance is already running; this run terminates immediately"),
@@ -98,7 +95,6 @@ public enum BatchRunOutcome {
* the run lock being held by another instance.
*
* @return true if outcome is {@link #LOCK_UNAVAILABLE}, false otherwise
* @since M2-AP-007
*/
public boolean isLockUnavailable() {
return this == LOCK_UNAVAILABLE;

View File

@@ -17,18 +17,13 @@ import de.gecheckt.pdf.umbenenner.domain.model.BatchRunContext;
* <p>
* The returned outcome is designed to be independent of individual document results,
* representing only the batch operation itself. Individual document successes/failures
* are tracked separately in persistence (future milestones).
* are tracked separately in persistence.
* <p>
* M2-AP-002 Implementation:
* Implementation details:
* <ul>
* <li>Port is defined with a structured return contract ({@link BatchRunOutcome})</li>
* <li>Return model allows Bootstrap/CLI to systematically derive exit codes (AP-007)</li>
* <li>No implementation of the use case itself yet (that is AP-004)</li>
* </ul>
* <p>
* M2-AP-003 Update:
* <ul>
* <li>execute() now accepts a {@link BatchRunContext} containing the run ID and timing</li>
* <li>Return model allows Bootstrap/CLI to systematically derive exit codes</li>
* <li>execute() accepts a {@link BatchRunContext} containing the run ID and timing</li>
* <li>The context flows through the entire batch cycle for correlation and logging</li>
* </ul>
*/

View File

@@ -13,13 +13,11 @@
* Return models:
* <ul>
* <li>{@link de.gecheckt.pdf.umbenenner.application.port.in.BatchRunOutcome}
* — Structured result of a batch run, designed for exit code mapping (AP-007)</li>
* — Structured result of a batch run, designed for exit code mapping</li>
* </ul>
* <p>
* Architecture Rule: Inbound ports are independent of implementation and contain no business logic.
* They define "what can be done to the application". All dependencies point inward;
* adapters depend on ports, not vice versa.
*
* @since M2-AP-002
*/
package de.gecheckt.pdf.umbenenner.application.port.in;

View File

@@ -18,7 +18,6 @@ import java.time.Instant;
* This port is defined in M2 for use in later milestones where timestamps
* become relevant (e.g., run history, document date fallback).
*
* @since M2-AP-002
*/
public interface ClockPort {

View File

@@ -15,7 +15,6 @@ import java.util.Objects;
* without an additional lookup.
*
* @param record the current master record for this document; never null
* @since M4-AP-001
*/
public record DocumentKnownProcessable(DocumentRecord record) implements DocumentRecordLookupResult {

View File

@@ -23,7 +23,6 @@ package de.gecheckt.pdf.umbenenner.application.port.out;
* {@link DocumentRecordLookupResult} hierarchy to allow exhaustive pattern matching
* at the call site.
*
* @since M4-AP-001
*/
public class DocumentPersistenceException extends RuntimeException {

View File

@@ -49,7 +49,6 @@ import java.util.Objects;
* @param lastSuccessInstant timestamp of the successful processing, or {@code null}
* @param createdAt timestamp when this record was first created; never null
* @param updatedAt timestamp of the most recent update; never null
* @since M4-AP-001
*/
public record DocumentRecord(
DocumentFingerprint fingerprint,

View File

@@ -21,7 +21,6 @@ package de.gecheckt.pdf.umbenenner.application.port.out;
* <strong>Architecture boundary:</strong> No JDBC, SQLite, or filesystem types appear
* in this sealed hierarchy or in any of its implementations.
*
* @since M4-AP-001
*/
public sealed interface DocumentRecordLookupResult
permits DocumentUnknown,

View File

@@ -29,7 +29,6 @@ import de.gecheckt.pdf.umbenenner.domain.model.DocumentFingerprint;
* in this interface or in any type it references. Mapping to and from the persistence
* schema is the exclusive responsibility of the adapter implementation.
*
* @since M4-AP-001
*/
public interface DocumentRecordRepository {

View File

@@ -15,7 +15,6 @@ import java.util.Objects;
* current record for the skip attempt historisation without an additional lookup.
*
* @param record the current (finally failed) master record for this document; never null
* @since M4-AP-001
*/
public record DocumentTerminalFinalFailure(DocumentRecord record) implements DocumentRecordLookupResult {

View File

@@ -15,7 +15,6 @@ import java.util.Objects;
* current record for the skip attempt historisation without an additional lookup.
*
* @param record the current (successful) master record for this document; never null
* @since M4-AP-001
*/
public record DocumentTerminalSuccess(DocumentRecord record) implements DocumentRecordLookupResult {

View File

@@ -8,7 +8,6 @@ package de.gecheckt.pdf.umbenenner.application.port.out;
* <p>
* This variant carries no data because there is no existing record to return.
*
* @since M4-AP-001
*/
public record DocumentUnknown() implements DocumentRecordLookupResult {
}

View File

@@ -25,7 +25,6 @@ package de.gecheckt.pdf.umbenenner.application.port.out;
* must be &gt;= 0
* @param transientErrorCount number of transient technical errors recorded so far;
* must be &gt;= 0
* @since M4-AP-001
*/
public record FailureCounters(int contentErrorCount, int transientErrorCount) {

View File

@@ -22,7 +22,6 @@ import de.gecheckt.pdf.umbenenner.domain.model.SourceDocumentCandidate;
* and the candidate cannot be identified; consequently no SQLite attempt record is
* created for this candidate in M4.
*
* @since M4-AP-001
*/
public interface FingerprintPort {

View File

@@ -14,7 +14,6 @@ package de.gecheckt.pdf.umbenenner.application.port.out;
* the document cannot be identified and <em>no</em> SQLite attempt record is created.
* The failure is treated as a non-identifiable run event.
*
* @since M4-AP-001
*/
public sealed interface FingerprintResult permits FingerprintSuccess, FingerprintTechnicalError {
}

View File

@@ -12,7 +12,6 @@ import java.util.Objects;
* for all subsequent persistence operations in M4.
*
* @param fingerprint the successfully computed fingerprint; never null
* @since M4-AP-001
*/
public record FingerprintSuccess(DocumentFingerprint fingerprint) implements FingerprintResult {

View File

@@ -15,7 +15,6 @@ import java.util.Objects;
*
* @param errorMessage human-readable description of the failure; never null or blank
* @param cause the underlying throwable, or {@code null} if not available
* @since M4-AP-001
*/
public record FingerprintTechnicalError(String errorMessage, Throwable cause) implements FingerprintResult {

View File

@@ -35,7 +35,6 @@ import de.gecheckt.pdf.umbenenner.domain.model.SourceDocumentCandidate;
* <li>Persistence or caching of results</li>
* </ul>
*
* @since M3-AP-001
*/
public interface PdfTextExtractionPort {

View File

@@ -16,7 +16,6 @@ import java.util.Objects;
*
* @param errorMessage human-readable description of the persistence failure; never null or blank
* @param cause the underlying throwable, or {@code null} if not available
* @since M4-AP-001
*/
public record PersistenceLookupTechnicalFailure(String errorMessage, Throwable cause)
implements DocumentRecordLookupResult {

View File

@@ -23,7 +23,6 @@ package de.gecheckt.pdf.umbenenner.application.port.out;
* in this interface. All schema DDL and connection management are confined to the
* {@code adapter-out} implementation.
*
* @since M4-AP-001
*/
public interface PersistenceSchemaInitializationPort {

View File

@@ -55,7 +55,6 @@ import java.util.Objects;
* @param failureClass failure classification, or {@code null} for non-failure statuses
* @param failureMessage failure description, or {@code null} for non-failure statuses
* @param retryable whether this failure should be retried in a later run
* @since M4-AP-001
*/
public record ProcessingAttempt(
DocumentFingerprint fingerprint,

View File

@@ -26,7 +26,6 @@ import java.util.List;
* in this interface. Mapping to and from the persistence schema is the exclusive
* responsibility of the adapter implementation.
*
* @since M4-AP-001
*/
public interface ProcessingAttemptRepository {

View File

@@ -24,7 +24,6 @@ package de.gecheckt.pdf.umbenenner.application.port.out;
* This port is used by the batch use case (M2-AP-004) but not implemented in M2;
* implementation follows in M2-AP-006.
*
* @since M2-AP-002
*/
public interface RunLockPort {

View File

@@ -10,7 +10,6 @@ package de.gecheckt.pdf.umbenenner.application.port.out;
* This is a controlled failure mode, not a programming error. Applications should
* catch this exception and exit gracefully with the appropriate exit code.
*
* @since M2-AP-002
*/
public class RunLockUnavailableException extends RuntimeException {

View File

@@ -13,7 +13,6 @@ package de.gecheckt.pdf.umbenenner.application.port.out;
* This is a runtime exception, allowing adapters to propagate filesystem errors
* without forcing try/catch blocks in the application layer.
*
* @since M3-AP-001
*/
public final class SourceDocumentAccessException extends RuntimeException {
private static final long serialVersionUID = 1L;

View File

@@ -27,7 +27,6 @@ import java.util.List;
* <li>This enforces the hexagonal boundary and allows easy adapter swapping (e.g., cloud storage)</li>
* </ul>
*
* @since M3-AP-001
*/
public interface SourceDocumentCandidatesPort {

View File

@@ -10,7 +10,6 @@ import java.util.function.Consumer;
* Ensures that related persistence operations (such as saving a processing attempt
* and updating a document record) are executed atomically.
*
* @since M4-AP-006-fix
*/
public interface UnitOfWorkPort {

View File

@@ -4,17 +4,17 @@
* Outbound ports define the contracts for interacting with external systems and infrastructure.
* All calls flow FROM the application OUT TO infrastructure adapters through these ports.
* <p>
* M2-AP-002 ports:
* Configuration and runtime ports:
* <ul>
* <li>{@link de.gecheckt.pdf.umbenenner.application.port.out.ConfigurationPort}
* — Loading application startup configuration (already M1)</li>
* — Loading application startup configuration</li>
* <li>{@link de.gecheckt.pdf.umbenenner.application.port.out.RunLockPort}
* — Exclusive run lock for preventing concurrent batch instances</li>
* <li>{@link de.gecheckt.pdf.umbenenner.application.port.out.ClockPort}
* — System time access for timestamps and run context</li>
* </ul>
* <p>
* M3-AP-001 ports:
* Source document discovery and extraction ports:
* <ul>
* <li>{@link de.gecheckt.pdf.umbenenner.application.port.out.SourceDocumentCandidatesPort}
* — Load PDF document candidates from the source folder</li>
@@ -22,7 +22,7 @@
* — Extract text content and page count from a single PDF</li>
* </ul>
* <p>
* M4-AP-001 ports:
* Persistence and fingerprinting ports:
* <ul>
* <li>{@link de.gecheckt.pdf.umbenenner.application.port.out.FingerprintPort}
* — Compute the content-based SHA-256 fingerprint of a processing candidate</li>
@@ -34,7 +34,7 @@
* — Initialise the SQLite schema at program startup</li>
* </ul>
* <p>
* M4-AP-001 value types and result types:
* Value types and result types:
* <ul>
* <li>{@link de.gecheckt.pdf.umbenenner.application.port.out.FailureCounters}
* — Immutable snapshot of content-error and transient-error counters per document</li>
@@ -51,17 +51,15 @@
* Exception types:
* <ul>
* <li>{@link de.gecheckt.pdf.umbenenner.application.port.out.RunLockUnavailableException}
* — Thrown when run lock cannot be acquired (another instance running) (M2)</li>
* — Thrown when run lock cannot be acquired (another instance running)</li>
* <li>{@link de.gecheckt.pdf.umbenenner.application.port.out.SourceDocumentAccessException}
* — Thrown when source folder cannot be read or accessed (M3)</li>
* — Thrown when source folder cannot be read or accessed</li>
* <li>{@link de.gecheckt.pdf.umbenenner.application.port.out.DocumentPersistenceException}
* — Thrown when a persistence write operation or schema init fails (M4)</li>
* — Thrown when a persistence write operation or schema init fails</li>
* </ul>
* <p>
* Architecture Rule: Outbound ports are implementation-agnostic and contain no business logic.
* They define "what the application depends on externally". All dependencies point inward;
* the application depends on ports, adapters implement ports.
*
* @since M2-AP-002
*/
package de.gecheckt.pdf.umbenenner.application.port.out;

View File

@@ -33,7 +33,6 @@ import java.util.Objects;
* <p>
* This service is the single authoritative place for the decision rules:
* idempotency checks, status/counter mapping, and consistent two-level persistence.
* It is intentionally tightly scoped to AP-006 and contains no further logic.
*
* <h2>Processing order per candidate</h2>
* <ol>
@@ -76,8 +75,6 @@ import java.util.Objects;
* Failures that occur before a successful fingerprint is available are <em>not</em>
* historised in SQLite. They are handled by the caller and logged as non-identifiable
* run events.
*
* @since AP-006
*/
public class DocumentProcessingCoordinator {

View File

@@ -1,8 +1,8 @@
/**
* Application-level services for business logic evaluation and M4 orchestration.
* Application-level services for business logic evaluation and document processing orchestration.
* <p>
* This package contains stateless, pure-logic services that evaluate document content,
* apply business rules, and orchestrate the M4 per-document processing flow.
* apply business rules, and orchestrate the per-document processing flow.
* Services in this package:
* <ul>
* <li>Do not manage state or resources</li>
@@ -14,31 +14,31 @@
* <h2>Current services</h2>
* <ul>
* <li>{@link de.gecheckt.pdf.umbenenner.application.service.PreCheckEvaluator}
* — Pre-check evaluation (M3)</li>
* — Pre-check evaluation logic</li>
* <li>{@link de.gecheckt.pdf.umbenenner.application.service.DocumentProcessingService}
* — Complete M3 document processing pipeline orchestration</li>
* — Complete document processing pipeline orchestration</li>
* <li>{@link de.gecheckt.pdf.umbenenner.application.service.M4DocumentProcessor}
* — M4 per-document idempotency, status/counter mapping and consistent
* two-level persistence (AP-006)</li>
* — Per-document idempotency, status/counter mapping and consistent
* two-level persistence</li>
* </ul>
*
* <h2>M4 processing flow ({@code M4DocumentProcessor})</h2>
* <h2>Document processing flow ({@code M4DocumentProcessor})</h2>
* <p>
* The {@link de.gecheckt.pdf.umbenenner.application.service.M4DocumentProcessor}
* implements the verbindliche M4 processing order per candidate:
* implements the required processing order per candidate:
* <ol>
* <li>Load the document master record by fingerprint.</li>
* <li>If overall status is {@code SUCCESS} → persist a skip attempt with
* {@code SKIPPED_ALREADY_PROCESSED}; do not change counters.</li>
* <li>If overall status is {@code FAILED_FINAL} → persist a skip attempt with
* {@code SKIPPED_FINAL_FAILURE}; do not change counters.</li>
* <li>Otherwise map the M3 outcome into M4 status, counters and retryable flag
* using the M4 minimal rules.</li>
* <li>Otherwise map the extraction outcome into status, counters and retryable flag
* using the minimal rules.</li>
* <li>Persist exactly one historised processing attempt.</li>
* <li>Persist the updated document master record.</li>
* </ol>
*
* <h2>M4 minimal rules (status and counter semantics)</h2>
* <h2>Processing rules (status and counter semantics)</h2>
* <ul>
* <li>First deterministic content error → {@code FAILED_RETRYABLE},
* content error counter +1, {@code retryable=true}.</li>
@@ -54,7 +54,7 @@
* For every identified document, the processing attempt and the master record are
* written in sequence. If either write fails, the failure is caught and logged;
* the batch run continues with the next candidate. True transactionality across
* two separate repository calls is not available in the M4 scope; this is a known
* two separate repository calls is not available due to the two-level persistence design; this is a known
* and documented limitation.
*
* <h2>Pre-fingerprint failures</h2>

View File

@@ -76,7 +76,6 @@ import java.util.Objects;
* <li>No retry rules for KI or target copy failures.</li>
* </ul>
*
* @since AP-004 (extended in AP-006)
*/
public class DefaultBatchRunProcessingUseCase implements BatchRunProcessingUseCase {

View File

@@ -4,25 +4,23 @@
* Implementations:
* <ul>
* <li>{@link de.gecheckt.pdf.umbenenner.application.usecase.DefaultBatchRunProcessingUseCase}
* — Production implementation with run lock, M4 fingerprint-based idempotency,
* and consistent two-level persistence (extended in M4-AP-006)</li>
* — Production implementation with run lock, fingerprint-based idempotency,
* and consistent two-level persistence</li>
* </ul>
* <p>
* <h2>M4 processing order (AP-006)</h2>
* <h2>Processing order per candidate</h2>
* <p>
* For each candidate, {@link de.gecheckt.pdf.umbenenner.application.usecase.DefaultBatchRunProcessingUseCase}
* The {@link de.gecheckt.pdf.umbenenner.application.usecase.DefaultBatchRunProcessingUseCase}
* enforces this order:
* <ol>
* <li>Compute SHA-256 fingerprint of the candidate file content.</li>
* <li>If fingerprint computation fails: log as non-identifiable run event;
* do NOT write any SQLite record; continue with next candidate.</li>
* <li>Run the M3 pipeline (PDF extraction + pre-checks).</li>
* <li>Run the document extraction and pre-checks pipeline.</li>
* <li>Delegate to {@link de.gecheckt.pdf.umbenenner.application.service.M4DocumentProcessor}
* for idempotency check, status/counter mapping, and consistent persistence.</li>
* </ol>
* <p>
* All implementations are infrastructure-agnostic and interact only through ports.
*
* @since M2 (extended in M4-AP-006)
*/
package de.gecheckt.pdf.umbenenner.application.usecase;