SonarQube: fix alle BLOCKER- und CRITICAL-Issues (S3252, S2479, S1186, S1192, S2699, S5783, S3776)

- S3252: GuiStatusRefreshTimeline nutzt Animation.INDEFINITE statt Timeline.INDEFINITE
- S2479: Narrow-No-Break-Space (U+202F) in GuiTooltipTexts durch normales Leerzeichen ersetzt
- S1186: 134 leere Stub-Methoden in 18 Test- und Produktionsdateien kommentiert
- S1192: ~49 duplizierte String-Literale in ~25 Klassen als Konstanten extrahiert
- S2699: fehlende Assertions in SqliteSchemaInitializationAdapterTest und FilesystemTargetFolderAdapterTest ergaenzt
- S5783: Lambda-geprufte Ausnahme in SqliteSchemaInitializationAdapterTest in private Hilfsmethode extrahiert
- S3776: kognitive Komplexitaet in 8 Methoden durch Methodenextraktion auf unter 15 gesenkt
  (EarlyLogDirectoryInitializer, CliArgumentParser, GuiConfigurationEditorWorkspace,
   GuiHistoryTab x2, GuiBatchRunTab x2, DefaultManualFileCopyUseCase)
- Kompilierungsfehler behoben: private-Modifier in CorrectionOutcome-Interface entfernt,
  selbstreferenzielle Konstante in ModelCatalogResult korrigiert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-06 21:27:59 +02:00
parent 14da7ee789
commit b7f9184344
49 changed files with 974 additions and 511 deletions
@@ -18,6 +18,8 @@ public sealed interface PromptSaveResult
PromptSaveResult.WriteFailed,
PromptSaveResult.TargetDirectoryMissing,
PromptSaveResult.AtomicMoveFailed {
String MESSAGE_NOT_NULL = "message must not be null";
/**
* Die Prompt-Datei wurde erfolgreich gespeichert.
@@ -53,7 +55,7 @@ public sealed interface PromptSaveResult
* @throws NullPointerException wenn {@code message} null ist
*/
public WriteFailed {
java.util.Objects.requireNonNull(message, "message must not be null");
java.util.Objects.requireNonNull(message, MESSAGE_NOT_NULL);
}
}
@@ -71,7 +73,7 @@ public sealed interface PromptSaveResult
* @throws NullPointerException wenn {@code message} null ist
*/
public TargetDirectoryMissing {
java.util.Objects.requireNonNull(message, "message must not be null");
java.util.Objects.requireNonNull(message, MESSAGE_NOT_NULL);
}
}
@@ -90,7 +92,7 @@ public sealed interface PromptSaveResult
* @throws NullPointerException wenn {@code message} null ist
*/
public AtomicMoveFailed {
java.util.Objects.requireNonNull(message, "message must not be null");
java.util.Objects.requireNonNull(message, MESSAGE_NOT_NULL);
}
}
}
@@ -29,6 +29,8 @@ public sealed interface ModelCatalogResult
ModelCatalogResult.EmptyList,
ModelCatalogResult.IncompleteConfiguration,
ModelCatalogResult.TechnicalFailure {
String PROVIDER_ID_NOT_NULL = "providerIdentifier must not be null";
/**
* The provider returned a non-empty list of available model identifiers.
@@ -55,7 +57,7 @@ public sealed interface ModelCatalogResult
* @throws IllegalArgumentException if {@code models} is empty
*/
public Success {
Objects.requireNonNull(providerIdentifier, "providerIdentifier must not be null");
Objects.requireNonNull(providerIdentifier, PROVIDER_ID_NOT_NULL);
Objects.requireNonNull(models, "models must not be null");
Objects.requireNonNull(loadedAt, "loadedAt must not be null");
if (models.isEmpty()) {
@@ -88,7 +90,7 @@ public sealed interface ModelCatalogResult
* @throws NullPointerException if any parameter is {@code null}
*/
public EmptyList {
Objects.requireNonNull(providerIdentifier, "providerIdentifier must not be null");
Objects.requireNonNull(providerIdentifier, PROVIDER_ID_NOT_NULL);
Objects.requireNonNull(loadedAt, "loadedAt must not be null");
}
}
@@ -118,7 +120,7 @@ public sealed interface ModelCatalogResult
* @throws NullPointerException if any parameter is {@code null}
*/
public IncompleteConfiguration {
Objects.requireNonNull(providerIdentifier, "providerIdentifier must not be null");
Objects.requireNonNull(providerIdentifier, PROVIDER_ID_NOT_NULL);
Objects.requireNonNull(missingReason, "missingReason must not be null");
}
}
@@ -153,7 +155,7 @@ public sealed interface ModelCatalogResult
* @throws NullPointerException if any parameter is {@code null}
*/
public TechnicalFailure {
Objects.requireNonNull(providerIdentifier, "providerIdentifier must not be null");
Objects.requireNonNull(providerIdentifier, PROVIDER_ID_NOT_NULL);
Objects.requireNonNull(errorCategory, "errorCategory must not be null");
Objects.requireNonNull(errorDetail, "errorDetail must not be null");
}
@@ -38,6 +38,10 @@ import de.gecheckt.pdf.umbenenner.domain.model.ParsedAiResponse;
* of {@link AiResponseValidator}.
*/
public final class AiResponseParser {
private static final String JSON_KEY_TITLE = "title";
private static final String JSON_KEY_REASONING = "reasoning";
private AiResponseParser() {
// Static utility no instances
@@ -81,19 +85,19 @@ public final class AiResponseParser {
}
// Validate mandatory field: title
if (!json.has("title") || json.isNull("title")) {
if (!json.has(JSON_KEY_TITLE) || json.isNull(JSON_KEY_TITLE)) {
return new AiResponseParsingFailure("MISSING_TITLE", "AI response missing mandatory field 'title'");
}
String title = json.getString("title");
String title = json.getString(JSON_KEY_TITLE);
if (title.isBlank()) {
return new AiResponseParsingFailure("BLANK_TITLE", "AI response field 'title' is blank");
}
// Validate mandatory field: reasoning
if (!json.has("reasoning") || json.isNull("reasoning")) {
if (!json.has(JSON_KEY_REASONING) || json.isNull(JSON_KEY_REASONING)) {
return new AiResponseParsingFailure("MISSING_REASONING", "AI response missing mandatory field 'reasoning'");
}
String reasoning = json.getString("reasoning");
String reasoning = json.getString(JSON_KEY_REASONING);
// Optional field: date
String dateString = null;
@@ -70,6 +70,17 @@ public class DefaultManualFileCopyUseCase implements ManualFileCopyUseCase {
private final ClockPort clock;
private final ProcessingLogger logger;
/** Ergebnis der Dokument-Stammsatz-Auflösung: entweder ein Record oder ein Fehler. */
private record RecordLookupOutcome(DocumentRecord record, ManualFileCopyResult failure) {
boolean hasFailed() { return failure != null; }
}
/** Ergebnis der Zieldateinamen-Auflösung: entweder Name + No-Op-Flag oder ein Fehler. */
private record FilenameLookupOutcome(String appliedFileName, boolean noOpIdentical,
ManualFileCopyResult failure) {
boolean hasFailed() { return failure != null; }
}
/**
* Erstellt den Use-Case mit allen erforderlichen Ports.
*
@@ -127,86 +138,144 @@ public class DefaultManualFileCopyUseCase implements ManualFileCopyUseCase {
logger.info("Manuelle Dateikopie angefordert: Fingerprint={}, Zielname={}",
fingerprint.sha256Hex(), desiredFullName);
// Schritt 1: Dokument-Stammsatz laden und Zustand prüfen
RecordLookupOutcome recordOutcome = loadAndValidateRecord(fingerprint);
if (recordOutcome.hasFailed()) {
return recordOutcome.failure();
}
DocumentRecord record = recordOutcome.record();
FilenameLookupOutcome filenameOutcome = resolveTargetFilename(fingerprint, desiredFullName);
if (filenameOutcome.hasFailed()) {
return filenameOutcome.failure();
}
String appliedFileName = filenameOutcome.appliedFileName();
boolean noOpIdentical = filenameOutcome.noOpIdentical();
if (!noOpIdentical) {
ManualFileCopyResult copyFailure = performFileCopy(fingerprint, record, appliedFileName);
if (copyFailure != null) {
return copyFailure;
}
}
return persistAndBuildResult(fingerprint, record, appliedFileName, noOpIdentical, desiredFullName);
}
/**
* Lädt den Dokument-Stammsatz und prüft, ob der aktuelle Status eine manuelle
* Kopie erlaubt.
*
* @param fingerprint der Fingerprint des Dokuments
* @return Outcome mit geladenem Record oder mit einem Fehler-Ergebnis
*/
private RecordLookupOutcome loadAndValidateRecord(DocumentFingerprint fingerprint) {
DocumentRecordLookupResult lookupResult = repository.findByFingerprint(fingerprint);
DocumentRecord record;
if (lookupResult instanceof DocumentTerminalFinalFailure terminalFailure) {
record = terminalFailure.record();
return new RecordLookupOutcome(terminalFailure.record(), null);
} else if (lookupResult instanceof DocumentKnownProcessable known) {
record = known.record();
ProcessingStatus status = record.overallStatus();
if (status == ProcessingStatus.SUCCESS) {
// Defensiv: SUCCESS sollte über DocumentTerminalSuccess auflösen, nicht hier.
DocumentRecord record = known.record();
if (record.overallStatus() == ProcessingStatus.SUCCESS) {
logger.warn("Manuelle Dateikopie verweigert: Dokument bereits SUCCESS. Fingerprint={}",
fingerprint.sha256Hex());
return new ManualFileCopyInvalidState(
return new RecordLookupOutcome(null, new ManualFileCopyInvalidState(
"Dokument ist bereits erfolgreich verarbeitet. Bitte die Umbenennung der "
+ "Zieldatei verwenden.");
+ "Zieldatei verwenden."));
}
return new RecordLookupOutcome(record, null);
} else if (lookupResult instanceof DocumentTerminalSuccess) {
logger.warn("Manuelle Dateikopie verweigert: Dokument bereits SUCCESS. Fingerprint={}",
fingerprint.sha256Hex());
return new ManualFileCopyInvalidState(
return new RecordLookupOutcome(null, new ManualFileCopyInvalidState(
"Dokument ist bereits erfolgreich verarbeitet. Bitte die Umbenennung der "
+ "Zieldatei verwenden.");
+ "Zieldatei verwenden."));
} else if (lookupResult instanceof DocumentUnknown) {
logger.warn("Manuelle Dateikopie verweigert: Dokument unbekannt. Fingerprint={}",
fingerprint.sha256Hex());
return new ManualFileCopyDocumentNotFound(
"Kein Dokument mit dem angegebenen Fingerprint gefunden.");
return new RecordLookupOutcome(null, new ManualFileCopyDocumentNotFound(
"Kein Dokument mit dem angegebenen Fingerprint gefunden."));
} else if (lookupResult instanceof PersistenceLookupTechnicalFailure failure) {
logger.warn("Manuelle Dateikopie fehlgeschlagen: Lookup-Fehler. Fingerprint={}, Ursache={}",
fingerprint.sha256Hex(), failure.errorMessage());
return new ManualFileCopyPersistenceFailure(
"Persistenzfehler beim Laden des Dokumentstammsatzes: " + failure.errorMessage());
} else {
// Defensiv: nicht erreichbar dank sealed type, aber erforderlich für die Compiler-
// Vollständigkeitsprüfung in älteren Werkzeugen.
return new ManualFileCopyDocumentNotFound(
"Unbekanntes Lookup-Ergebnis: " + lookupResult.getClass().getSimpleName());
return new RecordLookupOutcome(null, new ManualFileCopyPersistenceFailure(
"Persistenzfehler beim Laden des Dokumentstammsatzes: " + failure.errorMessage()));
}
// Defensiv: nicht erreichbar dank sealed type, aber erforderlich für die Compiler-
// Vollständigkeitsprüfung in älteren Werkzeugen.
return new RecordLookupOutcome(null, new ManualFileCopyDocumentNotFound(
"Unbekanntes Lookup-Ergebnis: " + lookupResult.getClass().getSimpleName()));
}
// Schritt 2: Eindeutigen Zieldateinamen über TargetFolderPort auflösen
/**
* Löst über {@link TargetFolderPort} einen eindeutigen Zieldateinamen auf.
*
* @param fingerprint der Fingerprint des Dokuments
* @param desiredFullName der gewünschte vollständige Dateiname
* @return Outcome mit aufgelöstem Dateinamen und No-Op-Flag oder mit einem Fehler-Ergebnis
*/
private FilenameLookupOutcome resolveTargetFilename(DocumentFingerprint fingerprint,
String desiredFullName) {
TargetFilenameResolutionResult resolutionResult =
targetFolderPort.resolveUniqueFilename(desiredFullName, fingerprint);
boolean noOpIdentical = false;
String appliedFileName;
if (resolutionResult instanceof ExistingIdenticalTargetFile identical) {
noOpIdentical = true;
appliedFileName = identical.existingFilename();
logger.info("Manuelle Dateikopie: Identische Datei bereits im Zielordner vorhanden. Fingerprint={}",
fingerprint.sha256Hex());
return new FilenameLookupOutcome(identical.existingFilename(), true, null);
} else if (resolutionResult instanceof TargetFolderTechnicalFailure folderFailure) {
logger.warn("Manuelle Dateikopie fehlgeschlagen: Zielordnerzugriff. Fingerprint={}, Ursache={}",
fingerprint.sha256Hex(), folderFailure.errorMessage());
return new ManualFileCopyFileSystemFailure(
"Zielordner nicht zugänglich: " + folderFailure.errorMessage());
return new FilenameLookupOutcome(null, false, new ManualFileCopyFileSystemFailure(
"Zielordner nicht zugänglich: " + folderFailure.errorMessage()));
} else if (resolutionResult instanceof ResolvedTargetFilename resolved) {
appliedFileName = resolved.resolvedFilename();
} else {
return new FilenameLookupOutcome(resolved.resolvedFilename(), false, null);
}
return new FilenameLookupOutcome(null, false, new ManualFileCopyFileSystemFailure(
"Unbekanntes Auflösungsergebnis: " + resolutionResult.getClass().getSimpleName()));
}
/**
* Kopiert die Quelldatei physisch in den Zielordner.
*
* @param fingerprint der Fingerprint des Dokuments (für Logging)
* @param record der aktuelle Dokument-Stammsatz
* @param appliedFileName der aufgelöste Zieldateiname
* @return ein Fehler-Ergebnis bei Misserfolg, {@code null} bei Erfolg
*/
private ManualFileCopyResult performFileCopy(DocumentFingerprint fingerprint,
DocumentRecord record,
String appliedFileName) {
var copyResult = targetFileCopyPort.copyToTarget(
record.lastKnownSourceLocator(), appliedFileName);
if (copyResult instanceof TargetFileCopyTechnicalFailure technicalFailure) {
logger.warn("Manuelle Dateikopie fehlgeschlagen: Dateisystemfehler. Fingerprint={}, Ursache={}",
fingerprint.sha256Hex(), technicalFailure.errorMessage());
return new ManualFileCopyFileSystemFailure(technicalFailure.errorMessage());
}
if (!(copyResult instanceof TargetFileCopySuccess)) {
return new ManualFileCopyFileSystemFailure(
"Unbekanntes Auflösungsergebnis: " + resolutionResult.getClass().getSimpleName());
"Unbekanntes Kopier-Ergebnis: " + copyResult.getClass().getSimpleName());
}
return null;
}
// Schritt 3: Quelldatei kopieren nur wenn keine identische Zieldatei existiert
if (!noOpIdentical) {
var copyResult = targetFileCopyPort.copyToTarget(
record.lastKnownSourceLocator(), appliedFileName);
if (copyResult instanceof TargetFileCopyTechnicalFailure technicalFailure) {
logger.warn("Manuelle Dateikopie fehlgeschlagen: Dateisystemfehler. Fingerprint={}, Ursache={}",
fingerprint.sha256Hex(), technicalFailure.errorMessage());
return new ManualFileCopyFileSystemFailure(technicalFailure.errorMessage());
}
if (!(copyResult instanceof TargetFileCopySuccess)) {
return new ManualFileCopyFileSystemFailure(
"Unbekanntes Kopier-Ergebnis: " + copyResult.getClass().getSimpleName());
}
}
// Schritt 4: Dokument-Stammsatz aktualisieren
/**
* Aktualisiert den Dokument-Stammsatz in der Persistenz und gibt das finale
* Operationsergebnis zurück. Bei einem Persistenzfehler nach erfolgter Zielkopie
* wird ein Best-Effort-Rollback der neu geschriebenen Datei durchgeführt.
*
* @param fingerprint der Fingerprint des Dokuments
* @param record der bisher gültige Dokument-Stammsatz
* @param appliedFileName der tatsächlich verwendete Zieldateiname
* @param noOpIdentical true, wenn keine neue Kopie geschrieben wurde
* @param desiredFullName der ursprünglich gewünschte Zieldateiname
* @return das finale Operationsergebnis
*/
private ManualFileCopyResult persistAndBuildResult(DocumentFingerprint fingerprint,
DocumentRecord record,
String appliedFileName,
boolean noOpIdentical,
String desiredFullName) {
var now = clock.now();
DocumentRecord updatedRecord = new DocumentRecord(
record.fingerprint(),
@@ -248,17 +317,15 @@ public class DefaultManualFileCopyUseCase implements ManualFileCopyUseCase {
"Persistenzfehler nach Kopie: " + errorMessage);
}
boolean conflictSuffixApplied = !noOpIdentical && !appliedFileName.equals(desiredFullName);
if (noOpIdentical) {
logger.info("Manuelle Dateikopie abgeschlossen ohne Schreibvorgang: identische Zieldatei {}.",
appliedFileName);
return new ManualFileCopyNoOpIdenticalTarget(appliedFileName);
}
boolean conflictSuffixApplied = !appliedFileName.equals(desiredFullName);
logger.info("Manuelle Dateikopie erfolgreich: {} (Suffix angewendet: {})",
appliedFileName, conflictSuffixApplied);
return new ManualFileCopySuccess(appliedFileName, conflictSuffixApplied);
}
}
@@ -24,6 +24,8 @@ public record EditorValidationFinding(
Optional<String> fieldKey,
EditorValidationSeverity severity,
String message) {
private static final String FIELD_KEY_NOT_NULL = "fieldKey must not be null";
/**
* Erstellt einen neuen Validierungsbefund.
@@ -47,7 +49,7 @@ public record EditorValidationFinding(
* @return ein neuer Befund mit Schweregrad {@link EditorValidationSeverity#ERROR}
*/
public static EditorValidationFinding error(String fieldKey, String message) {
Objects.requireNonNull(fieldKey, "fieldKey must not be null");
Objects.requireNonNull(fieldKey, FIELD_KEY_NOT_NULL);
return new EditorValidationFinding(Optional.of(fieldKey), EditorValidationSeverity.ERROR, message);
}
@@ -59,7 +61,7 @@ public record EditorValidationFinding(
* @return ein neuer Befund mit Schweregrad {@link EditorValidationSeverity#WARNING}
*/
public static EditorValidationFinding warning(String fieldKey, String message) {
Objects.requireNonNull(fieldKey, "fieldKey must not be null");
Objects.requireNonNull(fieldKey, FIELD_KEY_NOT_NULL);
return new EditorValidationFinding(Optional.of(fieldKey), EditorValidationSeverity.WARNING, message);
}
@@ -71,7 +73,7 @@ public record EditorValidationFinding(
* @return ein neuer Befund mit Schweregrad {@link EditorValidationSeverity#HINT}
*/
public static EditorValidationFinding hint(String fieldKey, String message) {
Objects.requireNonNull(fieldKey, "fieldKey must not be null");
Objects.requireNonNull(fieldKey, FIELD_KEY_NOT_NULL);
return new EditorValidationFinding(Optional.of(fieldKey), EditorValidationSeverity.HINT, message);
}
@@ -93,7 +95,7 @@ public record EditorValidationFinding(
* @return ein neuer Befund mit Schweregrad {@link EditorValidationSeverity#INFO}
*/
public static EditorValidationFinding info(String fieldKey, String message) {
Objects.requireNonNull(fieldKey, "fieldKey must not be null");
Objects.requireNonNull(fieldKey, FIELD_KEY_NOT_NULL);
return new EditorValidationFinding(Optional.of(fieldKey), EditorValidationSeverity.INFO, message);
}
@@ -21,6 +21,8 @@ public sealed interface CorrectionOutcome
permits CorrectionOutcome.Applied,
CorrectionOutcome.Failed,
CorrectionOutcome.NotAttempted {
String SUGGESTION_NOT_NULL = "suggestion must not be null";
/**
* Gibt den Korrekturvorschlag zurück, auf den sich dieses Ergebnis bezieht.
@@ -47,7 +49,7 @@ public sealed interface CorrectionOutcome
* @throws NullPointerException wenn ein Parameter {@code null} ist
*/
public Applied {
Objects.requireNonNull(suggestion, "suggestion must not be null");
Objects.requireNonNull(suggestion, SUGGESTION_NOT_NULL);
Objects.requireNonNull(message, "message must not be null");
}
}
@@ -70,7 +72,7 @@ public sealed interface CorrectionOutcome
* @throws NullPointerException wenn ein Parameter {@code null} ist
*/
public Failed {
Objects.requireNonNull(suggestion, "suggestion must not be null");
Objects.requireNonNull(suggestion, SUGGESTION_NOT_NULL);
Objects.requireNonNull(errorMessage, "errorMessage must not be null");
}
}
@@ -97,7 +99,7 @@ public sealed interface CorrectionOutcome
* @throws NullPointerException wenn ein Parameter {@code null} ist
*/
public NotAttempted {
Objects.requireNonNull(suggestion, "suggestion must not be null");
Objects.requireNonNull(suggestion, SUGGESTION_NOT_NULL);
Objects.requireNonNull(reason, "reason must not be null");
}
}
@@ -21,6 +21,9 @@ public sealed interface CorrectionSuggestion
permits CorrectionSuggestion.CreateDirectory,
CorrectionSuggestion.CreatePromptFile,
CorrectionSuggestion.PrepareSqlitePath {
String PATH_NOT_NULL = "path must not be null";
String DESCRIPTION_NOT_NULL = "descriptionForUser must not be null";
/**
* Gibt eine kurze deutsche Beschreibung der vorgeschlagenen Korrektur zurück,
@@ -53,8 +56,8 @@ public sealed interface CorrectionSuggestion
* @throws IllegalArgumentException wenn {@code path} leer ist
*/
public CreateDirectory {
Objects.requireNonNull(path, "path must not be null");
Objects.requireNonNull(descriptionForUser, "descriptionForUser must not be null");
Objects.requireNonNull(path, PATH_NOT_NULL);
Objects.requireNonNull(descriptionForUser, DESCRIPTION_NOT_NULL);
if (path.isBlank()) {
throw new IllegalArgumentException("path must not be blank");
}
@@ -93,8 +96,8 @@ public sealed interface CorrectionSuggestion
* {@code maxTitleLength < 1}
*/
public CreatePromptFile {
Objects.requireNonNull(path, "path must not be null");
Objects.requireNonNull(descriptionForUser, "descriptionForUser must not be null");
Objects.requireNonNull(path, PATH_NOT_NULL);
Objects.requireNonNull(descriptionForUser, DESCRIPTION_NOT_NULL);
if (path.isBlank()) {
throw new IllegalArgumentException("path must not be blank");
}
@@ -129,8 +132,8 @@ public sealed interface CorrectionSuggestion
* @throws IllegalArgumentException wenn {@code path} leer ist
*/
public PrepareSqlitePath {
Objects.requireNonNull(path, "path must not be null");
Objects.requireNonNull(descriptionForUser, "descriptionForUser must not be null");
Objects.requireNonNull(path, PATH_NOT_NULL);
Objects.requireNonNull(descriptionForUser, DESCRIPTION_NOT_NULL);
if (path.isBlank()) {
throw new IllegalArgumentException("path must not be blank");
}
@@ -1652,6 +1652,7 @@ class BatchRunProcessingUseCaseTest {
@Override
public void debugSensitiveAiContent(String message, Object... args) {
// intentionally empty
}
@Override
@@ -300,8 +300,12 @@ class BatchRunProgressObservationTest {
}
private static final class NoOpLock implements RunLockPort {
@Override public void acquire() { }
@Override public void release() { }
@Override public void acquire() {
// intentionally empty
}
@Override public void release() {
// intentionally empty
}
@Override
public java.util.Optional<de.gecheckt.pdf.umbenenner.application.port.out.RunLockHandle> tryAcquire() {
return java.util.Optional.empty();
@@ -335,11 +339,21 @@ class BatchRunProgressObservationTest {
}
private static final class SilentLogger implements ProcessingLogger {
@Override public void info(String message, Object... args) { }
@Override public void warn(String message, Object... args) { }
@Override public void error(String message, Object... args) { }
@Override public void debug(String message, Object... args) { }
@Override public void debugSensitiveAiContent(String message, Object... args) { }
@Override public void info(String message, Object... args) {
// intentionally empty
}
@Override public void warn(String message, Object... args) {
// intentionally empty
}
@Override public void error(String message, Object... args) {
// intentionally empty
}
@Override public void debug(String message, Object... args) {
// intentionally empty
}
@Override public void debugSensitiveAiContent(String message, Object... args) {
// intentionally empty
}
}
private static final class RecordingObserver implements BatchRunProgressObserver {
@@ -465,21 +479,31 @@ class BatchRunProgressObservationTest {
@Override public DocumentRecordLookupResult findByFingerprint(DocumentFingerprint f) {
return new DocumentUnknown();
}
@Override public void create(de.gecheckt.pdf.umbenenner.application.port.out.DocumentRecord record) { }
@Override public void update(de.gecheckt.pdf.umbenenner.application.port.out.DocumentRecord record) { }
@Override public void deleteByFingerprint(DocumentFingerprint fingerprint) { }
@Override public void create(de.gecheckt.pdf.umbenenner.application.port.out.DocumentRecord record) {
// intentionally empty
}
@Override public void update(de.gecheckt.pdf.umbenenner.application.port.out.DocumentRecord record) {
// intentionally empty
}
@Override public void deleteByFingerprint(DocumentFingerprint fingerprint) {
// intentionally empty
}
}
private static final class NoAttempts implements ProcessingAttemptRepository {
static final NoAttempts INSTANCE = new NoAttempts();
@Override public int loadNextAttemptNumber(DocumentFingerprint fingerprint) { return 1; }
@Override public void save(ProcessingAttempt attempt) { }
@Override public void save(ProcessingAttempt attempt) {
// intentionally empty
}
@Override public List<ProcessingAttempt> findAllByFingerprint(DocumentFingerprint fingerprint) {
return List.of();
}
@Override public ProcessingAttempt findLatestProposalReadyAttempt(
DocumentFingerprint fingerprint) { return null; }
@Override public void deleteAllByFingerprint(DocumentFingerprint fingerprint) { }
@Override public void deleteAllByFingerprint(DocumentFingerprint fingerprint) {
// intentionally empty
}
}
private static final class NoUow implements UnitOfWorkPort {
@@ -499,7 +523,9 @@ class BatchRunProgressObservationTest {
return new ResolvedTargetFilename(baseFilename);
}
@Override public String getTargetFolderLocator() { return "/tmp/target"; }
@Override public void tryDeleteTargetFile(String filename) { }
@Override public void tryDeleteTargetFile(String filename) {
// intentionally empty
}
}
private static final class NoTargetCopy implements TargetFileCopyPort {
@@ -83,17 +83,25 @@ class DefaultDeleteDocumentHistoryUseCaseTest {
UnitOfWorkPort failingPort = operations ->
operations.accept(new UnitOfWorkPort.TransactionOperations() {
@Override
public void saveProcessingAttempt(ProcessingAttempt attempt) { }
public void saveProcessingAttempt(ProcessingAttempt attempt) {
// intentionally empty
}
@Override
public void createDocumentRecord(DocumentRecord record) { }
public void createDocumentRecord(DocumentRecord record) {
// intentionally empty
}
@Override
public void updateDocumentRecord(DocumentRecord record) { }
public void updateDocumentRecord(DocumentRecord record) {
// intentionally empty
}
@Override
public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) {
throw new DocumentPersistenceException("Simulated DB error");
}
@Override
public void resetDocumentStatusForRetry(DocumentFingerprint fingerprint) { }
public void resetDocumentStatusForRetry(DocumentFingerprint fingerprint) {
// intentionally empty
}
});
DefaultDeleteDocumentHistoryUseCase useCase =
@@ -110,11 +118,21 @@ class DefaultDeleteDocumentHistoryUseCaseTest {
private static UnitOfWorkPort noOpPort() {
return operations -> operations.accept(new UnitOfWorkPort.TransactionOperations() {
@Override public void saveProcessingAttempt(ProcessingAttempt a) { }
@Override public void createDocumentRecord(DocumentRecord r) { }
@Override public void updateDocumentRecord(DocumentRecord r) { }
@Override public void resetDocumentByFingerprint(DocumentFingerprint fp) { }
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fp) { }
@Override public void saveProcessingAttempt(ProcessingAttempt a) {
// intentionally empty
}
@Override public void createDocumentRecord(DocumentRecord r) {
// intentionally empty
}
@Override public void updateDocumentRecord(DocumentRecord r) {
// intentionally empty
}
@Override public void resetDocumentByFingerprint(DocumentFingerprint fp) {
// intentionally empty
}
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fp) {
// intentionally empty
}
});
}
@@ -127,9 +145,15 @@ class DefaultDeleteDocumentHistoryUseCaseTest {
final List<DocumentFingerprint> resetByFingerprintFingerprints = new ArrayList<>();
final List<DocumentFingerprint> resetStatusForRetryFingerprints = new ArrayList<>();
@Override public void saveProcessingAttempt(ProcessingAttempt a) { }
@Override public void createDocumentRecord(DocumentRecord r) { }
@Override public void updateDocumentRecord(DocumentRecord r) { }
@Override public void saveProcessingAttempt(ProcessingAttempt a) {
// intentionally empty
}
@Override public void createDocumentRecord(DocumentRecord r) {
// intentionally empty
}
@Override public void updateDocumentRecord(DocumentRecord r) {
// intentionally empty
}
@Override
public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) {
@@ -84,13 +84,21 @@ class DefaultHistoryResetDocumentStatusUseCaseTest {
UnitOfWorkPort failingPort = operations ->
operations.accept(new UnitOfWorkPort.TransactionOperations() {
@Override
public void saveProcessingAttempt(ProcessingAttempt attempt) { }
public void saveProcessingAttempt(ProcessingAttempt attempt) {
// intentionally empty
}
@Override
public void createDocumentRecord(DocumentRecord record) { }
public void createDocumentRecord(DocumentRecord record) {
// intentionally empty
}
@Override
public void updateDocumentRecord(DocumentRecord record) { }
public void updateDocumentRecord(DocumentRecord record) {
// intentionally empty
}
@Override
public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) { }
public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) {
// intentionally empty
}
@Override
public void resetDocumentStatusForRetry(DocumentFingerprint fingerprint) {
throw new DocumentPersistenceException("Simulated DB error");
@@ -111,11 +119,21 @@ class DefaultHistoryResetDocumentStatusUseCaseTest {
private static UnitOfWorkPort noOpPort() {
return operations -> operations.accept(new UnitOfWorkPort.TransactionOperations() {
@Override public void saveProcessingAttempt(ProcessingAttempt a) { }
@Override public void createDocumentRecord(DocumentRecord r) { }
@Override public void updateDocumentRecord(DocumentRecord r) { }
@Override public void resetDocumentByFingerprint(DocumentFingerprint fp) { }
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fp) { }
@Override public void saveProcessingAttempt(ProcessingAttempt a) {
// intentionally empty
}
@Override public void createDocumentRecord(DocumentRecord r) {
// intentionally empty
}
@Override public void updateDocumentRecord(DocumentRecord r) {
// intentionally empty
}
@Override public void resetDocumentByFingerprint(DocumentFingerprint fp) {
// intentionally empty
}
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fp) {
// intentionally empty
}
});
}
@@ -128,9 +146,15 @@ class DefaultHistoryResetDocumentStatusUseCaseTest {
final List<DocumentFingerprint> resetStatusForRetryFingerprints = new ArrayList<>();
final List<DocumentFingerprint> resetByFingerprintFingerprints = new ArrayList<>();
@Override public void saveProcessingAttempt(ProcessingAttempt a) { }
@Override public void createDocumentRecord(DocumentRecord r) { }
@Override public void updateDocumentRecord(DocumentRecord r) { }
@Override public void saveProcessingAttempt(ProcessingAttempt a) {
// intentionally empty
}
@Override public void createDocumentRecord(DocumentRecord r) {
// intentionally empty
}
@Override public void updateDocumentRecord(DocumentRecord r) {
// intentionally empty
}
@Override
public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) {
@@ -100,11 +100,21 @@ class DefaultManualFileCopyUseCaseTest {
private static ProcessingLogger noOpLogger() {
return new ProcessingLogger() {
@Override public void info(String msg, Object... args) { }
@Override public void debug(String msg, Object... args) { }
@Override public void debugSensitiveAiContent(String msg, Object... args) { }
@Override public void warn(String msg, Object... args) { }
@Override public void error(String msg, Object... args) { }
@Override public void info(String msg, Object... args) {
// intentionally empty
}
@Override public void debug(String msg, Object... args) {
// intentionally empty
}
@Override public void debugSensitiveAiContent(String msg, Object... args) {
// intentionally empty
}
@Override public void warn(String msg, Object... args) {
// intentionally empty
}
@Override public void error(String msg, Object... args) {
// intentionally empty
}
};
}
@@ -115,9 +125,15 @@ class DefaultManualFileCopyUseCaseTest {
private static DocumentRecordRepository repositoryReturning(DocumentRecordLookupResult result) {
return new DocumentRecordRepository() {
@Override public DocumentRecordLookupResult findByFingerprint(DocumentFingerprint fp) { return result; }
@Override public void create(DocumentRecord r) { }
@Override public void update(DocumentRecord r) { }
@Override public void deleteByFingerprint(DocumentFingerprint fp) { }
@Override public void create(DocumentRecord r) {
// intentionally empty
}
@Override public void update(DocumentRecord r) {
// intentionally empty
}
@Override public void deleteByFingerprint(DocumentFingerprint fp) {
// intentionally empty
}
};
}
@@ -125,7 +141,9 @@ class DefaultManualFileCopyUseCaseTest {
return new TargetFolderPort() {
@Override public String getTargetFolderLocator() { return "/zielordner"; }
@Override public TargetFilenameResolutionResult resolveUniqueFilename(String baseName, DocumentFingerprint fp) { return result; }
@Override public void tryDeleteTargetFile(String name) { }
@Override public void tryDeleteTargetFile(String name) {
// intentionally empty
}
};
}
@@ -439,7 +457,9 @@ class DefaultManualFileCopyUseCaseTest {
baseNames.add(baseName);
return new ResolvedTargetFilename(baseName);
}
@Override public void tryDeleteTargetFile(String name) { }
@Override public void tryDeleteTargetFile(String name) {
// intentionally empty
}
};
DefaultManualFileCopyUseCase useCase = new DefaultManualFileCopyUseCase(
@@ -545,11 +565,21 @@ class DefaultManualFileCopyUseCaseTest {
// -------------------------------------------------------------------------
private static class NoOpTransactionOperations implements UnitOfWorkPort.TransactionOperations {
@Override public void saveProcessingAttempt(ProcessingAttempt attempt) { }
@Override public void createDocumentRecord(DocumentRecord record) { }
@Override public void updateDocumentRecord(DocumentRecord record) { }
@Override public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) { }
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fingerprint) { }
@Override public void saveProcessingAttempt(ProcessingAttempt attempt) {
// intentionally empty
}
@Override public void createDocumentRecord(DocumentRecord record) {
// intentionally empty
}
@Override public void updateDocumentRecord(DocumentRecord record) {
// intentionally empty
}
@Override public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) {
// intentionally empty
}
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fingerprint) {
// intentionally empty
}
}
private static class RecordCapturingTransactionOperations implements UnitOfWorkPort.TransactionOperations {
@@ -559,10 +589,18 @@ class DefaultManualFileCopyUseCaseTest {
this.captured = captured;
}
@Override public void saveProcessingAttempt(ProcessingAttempt attempt) { }
@Override public void createDocumentRecord(DocumentRecord record) { }
@Override public void saveProcessingAttempt(ProcessingAttempt attempt) {
// intentionally empty
}
@Override public void createDocumentRecord(DocumentRecord record) {
// intentionally empty
}
@Override public void updateDocumentRecord(DocumentRecord record) { captured.add(record); }
@Override public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) { }
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fingerprint) { }
@Override public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) {
// intentionally empty
}
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fingerprint) {
// intentionally empty
}
}
}
@@ -118,11 +118,21 @@ class DefaultManualFileRenameUseCaseTest {
private static ProcessingLogger noOpLogger() {
return new ProcessingLogger() {
@Override public void info(String msg, Object... args) { }
@Override public void debug(String msg, Object... args) { }
@Override public void debugSensitiveAiContent(String msg, Object... args) { }
@Override public void warn(String msg, Object... args) { }
@Override public void error(String msg, Object... args) { }
@Override public void info(String msg, Object... args) {
// intentionally empty
}
@Override public void debug(String msg, Object... args) {
// intentionally empty
}
@Override public void debugSensitiveAiContent(String msg, Object... args) {
// intentionally empty
}
@Override public void warn(String msg, Object... args) {
// intentionally empty
}
@Override public void error(String msg, Object... args) {
// intentionally empty
}
};
}
@@ -133,9 +143,15 @@ class DefaultManualFileRenameUseCaseTest {
private static DocumentRecordRepository repositoryReturning(DocumentRecordLookupResult result) {
return new DocumentRecordRepository() {
@Override public DocumentRecordLookupResult findByFingerprint(DocumentFingerprint fp) { return result; }
@Override public void create(DocumentRecord r) { }
@Override public void update(DocumentRecord r) { }
@Override public void deleteByFingerprint(DocumentFingerprint fp) { }
@Override public void create(DocumentRecord r) {
// intentionally empty
}
@Override public void update(DocumentRecord r) {
// intentionally empty
}
@Override public void deleteByFingerprint(DocumentFingerprint fp) {
// intentionally empty
}
};
}
@@ -143,7 +159,9 @@ class DefaultManualFileRenameUseCaseTest {
return new TargetFolderPort() {
@Override public String getTargetFolderLocator() { return "/zielordner"; }
@Override public TargetFilenameResolutionResult resolveUniqueFilename(String baseName, DocumentFingerprint fp) { return result; }
@Override public void tryDeleteTargetFile(String name) { }
@Override public void tryDeleteTargetFile(String name) {
// intentionally empty
}
};
}
@@ -475,7 +493,9 @@ class DefaultManualFileRenameUseCaseTest {
folderArgs.add(new String[]{baseName});
return new ResolvedTargetFilename(baseName);
}
@Override public void tryDeleteTargetFile(String name) { }
@Override public void tryDeleteTargetFile(String name) {
// intentionally empty
}
};
DefaultManualFileRenameUseCase useCase = new DefaultManualFileRenameUseCase(
@@ -616,11 +636,21 @@ class DefaultManualFileRenameUseCaseTest {
/** Führt keine Persistenzoperationen durch. */
private static class NoOpTransactionOperations implements UnitOfWorkPort.TransactionOperations {
@Override public void saveProcessingAttempt(ProcessingAttempt attempt) { }
@Override public void createDocumentRecord(DocumentRecord record) { }
@Override public void updateDocumentRecord(DocumentRecord record) { }
@Override public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) { }
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fingerprint) { }
@Override public void saveProcessingAttempt(ProcessingAttempt attempt) {
// intentionally empty
}
@Override public void createDocumentRecord(DocumentRecord record) {
// intentionally empty
}
@Override public void updateDocumentRecord(DocumentRecord record) {
// intentionally empty
}
@Override public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) {
// intentionally empty
}
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fingerprint) {
// intentionally empty
}
}
/** Zeichnet updateDocumentRecord-Aufrufe auf. */
@@ -631,10 +661,18 @@ class DefaultManualFileRenameUseCaseTest {
this.captured = captured;
}
@Override public void saveProcessingAttempt(ProcessingAttempt attempt) { }
@Override public void createDocumentRecord(DocumentRecord record) { }
@Override public void saveProcessingAttempt(ProcessingAttempt attempt) {
// intentionally empty
}
@Override public void createDocumentRecord(DocumentRecord record) {
// intentionally empty
}
@Override public void updateDocumentRecord(DocumentRecord record) { captured.add(record); }
@Override public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) { }
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fingerprint) { }
@Override public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) {
// intentionally empty
}
@Override public void resetDocumentStatusForRetry(DocumentFingerprint fingerprint) {
// intentionally empty
}
}
}
@@ -179,11 +179,21 @@ class DefaultResetDocumentStatusUseCaseTest {
private static ProcessingLogger noOpLogger() {
return new ProcessingLogger() {
@Override public void info(String msg, Object... args) { }
@Override public void debug(String msg, Object... args) { }
@Override public void debugSensitiveAiContent(String msg, Object... args) { }
@Override public void warn(String msg, Object... args) { }
@Override public void error(String msg, Object... args) { }
@Override public void info(String msg, Object... args) {
// intentionally empty
}
@Override public void debug(String msg, Object... args) {
// intentionally empty
}
@Override public void debugSensitiveAiContent(String msg, Object... args) {
// intentionally empty
}
@Override public void warn(String msg, Object... args) {
// intentionally empty
}
@Override public void error(String msg, Object... args) {
// intentionally empty
}
};
}
@@ -202,15 +212,21 @@ class DefaultResetDocumentStatusUseCaseTest {
@Override
public void saveProcessingAttempt(
de.gecheckt.pdf.umbenenner.application.port.out.ProcessingAttempt attempt) { }
de.gecheckt.pdf.umbenenner.application.port.out.ProcessingAttempt attempt) {
// intentionally empty
}
@Override
public void createDocumentRecord(
de.gecheckt.pdf.umbenenner.application.port.out.DocumentRecord record) { }
de.gecheckt.pdf.umbenenner.application.port.out.DocumentRecord record) {
// intentionally empty
}
@Override
public void updateDocumentRecord(
de.gecheckt.pdf.umbenenner.application.port.out.DocumentRecord record) { }
de.gecheckt.pdf.umbenenner.application.port.out.DocumentRecord record) {
// intentionally empty
}
@Override
public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) {
@@ -128,11 +128,17 @@ class DefaultResolveHistoricalDocumentContextUseCaseTest {
throw new DocumentPersistenceException("Verbindungsfehler", null);
}
@Override
public void create(DocumentRecord record) {}
public void create(DocumentRecord record) {
// intentionally empty
}
@Override
public void update(DocumentRecord record) {}
public void update(DocumentRecord record) {
// intentionally empty
}
@Override
public void deleteByFingerprint(DocumentFingerprint fingerprint) {}
public void deleteByFingerprint(DocumentFingerprint fingerprint) {
// intentionally empty
}
};
var useCase = new DefaultResolveHistoricalDocumentContextUseCase(throwingRepo);
@@ -151,11 +157,17 @@ class DefaultResolveHistoricalDocumentContextUseCaseTest {
return result;
}
@Override
public void create(DocumentRecord record) {}
public void create(DocumentRecord record) {
// intentionally empty
}
@Override
public void update(DocumentRecord record) {}
public void update(DocumentRecord record) {
// intentionally empty
}
@Override
public void deleteByFingerprint(DocumentFingerprint fingerprint) {}
public void deleteByFingerprint(DocumentFingerprint fingerprint) {
// intentionally empty
}
};
}
@@ -104,11 +104,17 @@ class DefaultResolveHistoricalFileNameUseCaseTest {
throw new DocumentPersistenceException("Verbindungsfehler", null);
}
@Override
public void create(DocumentRecord record) {}
public void create(DocumentRecord record) {
// intentionally empty
}
@Override
public void update(DocumentRecord record) {}
public void update(DocumentRecord record) {
// intentionally empty
}
@Override
public void deleteByFingerprint(DocumentFingerprint fingerprint) {}
public void deleteByFingerprint(DocumentFingerprint fingerprint) {
// intentionally empty
}
};
var useCase = new DefaultResolveHistoricalFileNameUseCase(throwingRepo);
@@ -127,11 +133,17 @@ class DefaultResolveHistoricalFileNameUseCaseTest {
return result;
}
@Override
public void create(DocumentRecord record) {}
public void create(DocumentRecord record) {
// intentionally empty
}
@Override
public void update(DocumentRecord record) {}
public void update(DocumentRecord record) {
// intentionally empty
}
@Override
public void deleteByFingerprint(DocumentFingerprint fingerprint) {}
public void deleteByFingerprint(DocumentFingerprint fingerprint) {
// intentionally empty
}
};
}