Files
2026-04-30 15:29:07 +02:00

15 KiB
Raw Permalink Blame History

Architektur-Übersicht: Domain & Application

Dieses Dokument beschreibt die fachliche und anwendungsnahe Schicht des PDF-Umbenenners: das Modul pdf-umbenenner-domain und das Modul pdf-umbenenner-application. Es richtet sich an Entwickler, die in diesen beiden Modulen arbeiten, und soll als alleiniger Architekturkontext ausreichen ergänzt durch die CLAUDE.md im Projektroot. Nicht enthalten sind Adapter-Implementierungen (Dateisystem, PDFBox, SQLite, HTTP-Clients); diese sind in adapter-overview.md beschrieben. GUI-spezifische Ports und deren Einbettung in den Konfigurationseditor sind in gui-overview.md dokumentiert.


1. Modulzweck

pdf-umbenenner-domain

Enthält ausschließlich fachliche Kerntypen (Records, Enums, Sealed Interfaces) ohne jegliche Infrastrukturabhängigkeiten. Alle Typen modellieren den Problembereich und sind von anderen Modulen referenzierbar, ohne transitive Abhängigkeiten einzuschleppen.

pdf-umbenenner-application

Definiert Use-Case-Orchestrierung sowie alle Inbound- und Outbound-Ports der hexagonalen Architektur. Enthält anwendungsnahe Dienste (KI-Antwort-Parsing, Pre-Check-Auswertung, Retry-Entscheidung) und Konfigurationsmodelle, aber keinerlei Infrastrukturcode (kein JDBC, kein PDFBox, kein HTTP-Client, kein JavaFX).


2. Paketstruktur

pdf-umbenenner-domain

Paket Verantwortung
de.gecheckt.pdf.umbenenner.domain Wurzelpaket; enthält nur package-info.java
de.gecheckt.pdf.umbenenner.domain.model Alle fachlichen Kerntypen: Records, Sealed Interfaces und Enums, die die Verarbeitungsdomäne beschreiben

pdf-umbenenner-application

Paket Verantwortung
de.gecheckt.pdf.umbenenner.application Wurzelpaket des Application-Moduls
de.gecheckt.pdf.umbenenner.application.port.in Inbound-Ports (Use-Case-Interfaces) Einstiegspunkte für den Aufrufer
de.gecheckt.pdf.umbenenner.application.port.out Outbound-Ports Verträge gegenüber Infrastruktur-Adaptern (Persistenz, Dateisystem, KI, Uhr, Logging)
de.gecheckt.pdf.umbenenner.application.port.out.modelcatalog Spezialisierter Outbound-Port für den Abruf verfügbarer KI-Modelle; ausschließlich im GUI-Pfad genutzt (siehe gui-overview.md)
de.gecheckt.pdf.umbenenner.application.port.out.history Outbound-Port für lesende Historien-Abfragen aus dem Historien-Tab; bewusst getrennt von den bestehenden Repositories, um diese nicht mit GUI-spezifischen Methoden aufzublähen
de.gecheckt.pdf.umbenenner.application.service Anwendungsnahe, zustandslose Dienste: KI-Antwort-Parsing, Pre-Check-Auswertung, Verarbeitungs-Pipeline, Retry-Entscheidung
de.gecheckt.pdf.umbenenner.application.config Konfigurationsmodelle der Anwendungsschicht (RuntimeConfiguration, Provider-Konfiguration)
de.gecheckt.pdf.umbenenner.application.config.startup Vollständiges Startup-Konfigurationsmodell (StartConfiguration)
de.gecheckt.pdf.umbenenner.application.config.provider Modelle für KI-Provider-Konfiguration (Provider-Familie, Einzelkonfiguration, Multi-Provider)
de.gecheckt.pdf.umbenenner.application.validation.editor Validierungslogik für den GUI-Konfigurationseditor (Findings, Report, API-Key-Auflösung); siehe gui-overview.md
de.gecheckt.pdf.umbenenner.application.validation.technicaltest Technischer Selbsttest: Pfad-Checks, Korrekturpläne, Checkpoints; Details in gui-overview.md
de.gecheckt.pdf.umbenenner.application.usecase Paket-Marker für Use-Case-Implementierungen

3. Schlüsselklassen

Domain-Modul

de.gecheckt.pdf.umbenenner.domain.model.SourceDocumentCandidate Record für einen PDF-Kandidaten aus dem Quellordner. Enthält keinen Path, sondern einen opaken SourceDocumentLocator, damit die Domain frei von NIO-Typen bleibt.

de.gecheckt.pdf.umbenenner.domain.model.DocumentFingerprint Record mit einem SHA-256-Hex-String (64 Zeichen) als stabiler Dokumentidentität; Grundlage für Idempotenz und Persistenz-Lookup.

de.gecheckt.pdf.umbenenner.domain.model.DocumentProcessingOutcome Sealed Interface mit sechs Implementierungen, die alle möglichen Ausgänge der Dokumentverarbeitung exhaustiv abbilden:

Implementierung Bedeutung
PreCheckPassed Vorprüfung bestanden, KI-Pfad freigegeben
PreCheckFailed Deterministischer Inhaltsfehler vor KI-Aufruf
TechnicalDocumentError Technischer Fehler ohne erneuten KI-Aufruf
NamingProposalReady KI-Antwort gültig, Vorschlag liegt vor
AiTechnicalFailure Transienter technischer Fehler beim KI-Aufruf
AiFunctionalFailure Deterministischer fachlicher Fehler der KI-Antwort

de.gecheckt.pdf.umbenenner.domain.model.ProcessingStatus Enum mit acht Zuständen. Dokumentiert Zustandsübergänge und Retry-Schwellen; fachliches Herzstück der Persistenz-Semantik.

Status Bedeutung
READY_FOR_AI Verarbeitbar, KI-Pfad noch nicht durchlaufen
FAILED_RETRYABLE Verarbeitbar, transient fehlgeschlagen
PROPOSAL_READY Eingangszustand für Dateinamensbildung und Zielkopie
SUCCESS Terminaler Enderfolg nur nach Zielkopie und konsistenter Persistenz
FAILED_FINAL Terminal, wird nicht erneut fachlich verarbeitet
SKIPPED_ALREADY_PROCESSED Historisierter Skip für SUCCESS-Dokumente
SKIPPED_FINAL_FAILURE Historisierter Skip für FAILED_FINAL-Dokumente

de.gecheckt.pdf.umbenenner.domain.model.NamingProposal Record mit aufgelöstem Datum, DateSource, validiertem Titel und KI-Begründung. Führende Quelle für die Zieldateinamensbildung.

de.gecheckt.pdf.umbenenner.domain.model.BatchRunContext Klasse mit Run-ID, Zeitstempel und optionalem Fingerabdruck-Filter; steuert den Umfang eines Batch-Laufs.


Application-Modul

de.gecheckt.pdf.umbenenner.application.config.RuntimeConfiguration Schmales Laufzeit-Record (maxPages, maxRetriesTransient, aiContentSensitivity). Wird von den Use Cases verwendet, enthält keine Pfade.

de.gecheckt.pdf.umbenenner.application.config.startup.StartConfiguration Vollständige typisierte Startup-Konfiguration; einziger Ort in der Anwendungsschicht, an dem java.nio.file.Path vorkommt. Wird vom ConfigurationPort geliefert und von Bootstrap ausgewertet.

de.gecheckt.pdf.umbenenner.application.service.DocumentProcessingService Statische Hilfsklasse: überführt ein Extraktionsergebnis über den Pre-Check in ein DocumentProcessingOutcome. Kompakte Pipeline-Klasse; guter Einstieg zum Verständnis der Verarbeitungslogik.

de.gecheckt.pdf.umbenenner.application.service.AiResponseParser Statischer Parser für KI-Antworten in ParsedAiResponse. Erzwingt reines JSON-Objekt; Validierungslogik liegt vollständig in der Anwendungsschicht.

de.gecheckt.pdf.umbenenner.application.port.out.ProcessingAttempt Record für einen Versuchshistorie-Eintrag; enthält u. a. Provider-Identifikator, Modellname, Prompt-Identifikator, aufgelöstes Datum und finalen Zieldateinamen.

de.gecheckt.pdf.umbenenner.application.port.out.DocumentRecord Record für den Dokument-Stammsatz; enthält Gesamtstatus, Fehler- und Transientzähler sowie letzten Zielpfad.

de.gecheckt.pdf.umbenenner.application.port.out.history.HistoryQuery Record mit den Abfrageparametern für den Historien-Tab: optionaler Suchbegriff (searchText, Teilstring, case-insensitiv), optionaler Status-Filter (statusFilter als Enum-Name) und Limit der zurückzugebenden Zeilen (Standard DEFAULT_LIMIT = 501). Das Limit 501 ermöglicht der aufrufenden Schicht zu erkennen, ob mehr als 500 Treffer vorhanden sind.

de.gecheckt.pdf.umbenenner.application.port.out.history.DocumentHistoryRow Einzelzeile der Dokumentenliste im Historien-Tab. Felder: fingerprint, overallStatus, sourceFileName, targetFileName (null wenn noch kein Erfolg), sourcePath, updatedAt und attemptCount. Stammt aus document_record mit einem COUNT-Ausdruck über processing_attempt.

de.gecheckt.pdf.umbenenner.application.port.out.PromptSaveResult Versiegeltes Ergebnis-Interface für PromptPort.savePrompt(String). Zulässige Ausprägungen: Saved (Erfolg, enthält absoluten Pfad), WriteFailed (I/O-Fehler beim Schreiben der Temp-Datei), TargetDirectoryMissing (Zielordner fehlt), AtomicMoveFailed (atomares Verschieben nicht möglich; kein stiller Fallback).

Neue Use-Case-Implementierungen im Paket de.gecheckt.pdf.umbenenner.application.usecase

Klasse Zweck
DefaultHistoryOverviewUseCase Lädt die gefilterte Dokumentenübersicht über HistoryQueryPort.loadOverview; gibt HistoryOverviewResult mit Liste und hasMore-Flag zurück
DefaultHistoryDetailsUseCase Lädt Stammsatz und alle Verarbeitungsversuche für einen Fingerprint über HistoryQueryPort; gibt HistoryDetailsResult zurück
DefaultHistoryResetDocumentStatusUseCase Feldgenauer Status-Reset via UnitOfWorkPort.TransactionOperations.resetDocumentStatusForRetry; setzt overall_status, content_error_count, transient_error_count und last_failure_instant zurück; lässt die Versuchshistorie unangetastet
DefaultDeleteDocumentHistoryUseCase Löscht Stammsatz und alle Verarbeitungsversuche vollständig und transaktional via UnitOfWorkPort
DefaultPromptEditorUseCase Delegiert Laden, Speichern und Standard-Anlegen der Prompt-Datei an PromptPort und ResourceCreationPort; wird im GUI-Pfad über GuiPromptEditorPort angesteuert

4. Inbound Ports

BatchRunProcessingUseCase

de.gecheckt.pdf.umbenenner.application.port.in.BatchRunProcessingUseCase

Zentraler Use-Case-Einstiegspunkt für den gesamten Batch-Betrieb. Beschreibt den Anwendungszweck in einer einzigen Methode:

BatchRunOutcome execute(BatchRunContext context);

Mögliche Ergebnisse:

Ergebnis Bedeutung
SUCCESS Lauf technisch ordnungsgemäß abgeschlossen
LOCK_UNAVAILABLE Run-Lock konnte nicht erworben werden
FAILURE Harter technischer Fehler beim Laufstart

5. Outbound Ports

Alle Outbound-Ports liegen in de.gecheckt.pdf.umbenenner.application.port.out (bzw. dessen Unterpaket modelcatalog). Implementierungen befinden sich ausschließlich in pdf-umbenenner-adapter-out; Details dort sind in adapter-overview.md beschrieben.

Interface Zweck Hauptmethode(n)
SourceDocumentCandidatesPort Scannt Quellordner, liefert Kandidaten in deterministischer Reihenfolge List<SourceDocumentCandidate> loadCandidates()
FingerprintPort Berechnet SHA-256-Fingerabdruck eines Kandidaten FingerprintResult computeFingerprint(SourceDocumentCandidate)
PdfTextExtractionPort Extrahiert Text und Seitenanzahl aus einer PDF PdfExtractionResult extractTextAndPageCount(...)
AiInvocationPort Ruft den aktiven KI-Dienst auf; provider-neutral AiInvocationResult invoke(AiRequestRepresentation)
PromptPort Lädt das Prompt-Template aus der konfigurierten Quelle; speichert geänderten Inhalt atomar via savePrompt(String) der Pfad stammt aus der Adapter-internen Konfiguration, nicht aus dem Port-Aufruf PromptLoadingResult loadPrompt(), PromptSaveResult savePrompt(String content)
TargetFileCopyPort Kopiert Quelldokument unter aufgelöstem Namen in den Zielordner (Temp + Rename) TargetFileCopyResult copyToTarget(...)
TargetFileRenamePort Atomare Umbenennung einer bereits kopierten Zieldatei (manuelle Korrektur) TargetFileRenameResult rename(...)
RunLockPort Exklusiver Lauf-Lock gegen parallele Instanzen acquire() / release()
PersistenceSchemaInitializationPort Idempotente Schema-Initialisierung der SQLite-Datenbank initializeSchema()
ClockPort Abstraktion des Systemtakts Instant now()
ConfigurationPort Lädt die typisierte Startup-Konfiguration StartConfiguration loadConfiguration()
ProcessingLogger Logging-Delegation; sensibles KI-Content-Logging über Flag gesteuert info/debug/warn/error/debugSensitiveAiContent(...)
AiModelCatalogPort Abruf verfügbarer Modelle vom Provider (nur GUI-Pfad, siehe gui-overview.md) ModelCatalogResult fetchAvailableModels(...)
PathCheckPort Lesende Pfad-Prüfung für den technischen Selbsttest isDirectoryReadable, isDirectoryWritableOrCreatable, isFileReadable, isSqlitePathUsable
ResourceCreationPort Schreibende Korrektur-Aktionen (Ordner anlegen, Prompt-Datei erzeugen, SQLite-Pfad vorbereiten) createDirectory, createPromptFile, prepareSqlitePath
ApiKeyResolutionPort Ermittelt API-Key-Herkunft pro Provider-Familie für die GUI-Validierung EffectiveApiKeyDescriptor resolve(...)
HistoryQueryPort Lesender Zugriff auf die Verarbeitungshistorie für den Historien-Tab; bewusst getrennt von den regulären Repositories List<DocumentHistoryRow> loadOverview(HistoryQuery), Optional<DocumentRecord> findRecordByFingerprint(DocumentFingerprint), List<ProcessingAttempt> findAttemptsByFingerprint(DocumentFingerprint)

Hinweis zu GUI-spezifischen Ports: AiModelCatalogPort, PathCheckPort, ResourceCreationPort, ApiKeyResolutionPort und HistoryQueryPort werden ausschließlich im GUI-Pfad genutzt. Ihre Implementierungen und der Aufrufkontext sind in gui-overview.md bzw. adapter-overview.md beschrieben.

Hinweis zu UnitOfWorkPort.TransactionOperations: Die innere Schnittstelle TransactionOperations wurde um die Methode resetDocumentStatusForRetry(DocumentFingerprint) erweitert. Diese setzt feldgenau overall_status → READY_FOR_AI, content_error_count → 0, transient_error_count → 0 und last_failure_instant → NULL, ohne die Versuchshistorie zu berühren. Die Implementierung liegt in SqliteUnitOfWorkAdapter.


6. Einstiegspunkte für neue Entwickler

Die folgende Lesereihenfolge gibt den kürzesten Weg zum Gesamtverständnis:

  1. de.gecheckt.pdf.umbenenner.application.port.in.BatchRunProcessingUseCase beschreibt den gesamten Anwendungszweck in einer Methode.
  2. de.gecheckt.pdf.umbenenner.domain.model.ProcessingStatus fachliches Herzstück; dokumentiert Zustandsübergänge und Retry-Schwellen.
  3. de.gecheckt.pdf.umbenenner.domain.model (gesamtes Paket) gemeinsame Sprache aller Schichten; vollständig in wenigen Minuten lesbar.
  4. de.gecheckt.pdf.umbenenner.application.service.DocumentProcessingService kompakte Pipeline-Klasse; zeigt, wie Pre-Check und Ergebnis-Typen zusammenspielen.
  5. de.gecheckt.pdf.umbenenner.application.port.out (gesamtes Paket) vollständige Außengrenzen der Architektur; jeder Infrastrukturzugriff ist hier als Port definiert.