Fix #41: Historischen KI-Dateinamen für übersprungene Dokumente in Ergebnistabelle anzeigen
Neue Komponenten: - ResolveHistoricalFileNameUseCase (port/in) und DefaultResolveHistoricalFileNameUseCase (usecase) - GuiHistoricalFileNamePort (GUI-interner Port, folgt dem Muster von GuiManualFileRenamePort) GuiBatchRunCoordinator ruft in toRow() für SKIPPED-Zeilen ohne finalName den historicalFileNamePort auf und trägt den Rückgabewert als neuen Dateinamen ein. Bootstrap verdrahtet resolveHistoricalFileNameForGui als GuiHistoricalFileNamePort und übergibt ihn über GuiStartupContext an den GUI-Adapter. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+54
-4
@@ -24,6 +24,7 @@ import de.gecheckt.pdf.umbenenner.adapter.in.gui.GuiConfigurationLoadException;
|
||||
import de.gecheckt.pdf.umbenenner.adapter.in.gui.GuiStartupContext;
|
||||
import de.gecheckt.pdf.umbenenner.adapter.in.gui.batchrun.GuiBatchRunLaunchOutcome;
|
||||
import de.gecheckt.pdf.umbenenner.adapter.in.gui.batchrun.GuiBatchRunLauncher;
|
||||
import de.gecheckt.pdf.umbenenner.adapter.in.gui.batchrun.GuiHistoricalFileNamePort;
|
||||
import de.gecheckt.pdf.umbenenner.adapter.in.gui.batchrun.GuiManualFileRenamePort;
|
||||
import de.gecheckt.pdf.umbenenner.adapter.in.gui.editor.GuiConfigurationEditorState;
|
||||
import de.gecheckt.pdf.umbenenner.adapter.in.gui.editor.GuiConfigurationEditorStateFactory;
|
||||
@@ -58,6 +59,8 @@ import de.gecheckt.pdf.umbenenner.application.port.in.BatchRunProcessingUseCase;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.ManualFileRenameRequest;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.ManualFileRenameResult;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.ManualFileRenameUseCase;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.ResolveHistoricalFileNameUseCase;
|
||||
import de.gecheckt.pdf.umbenenner.application.usecase.DefaultResolveHistoricalFileNameUseCase;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.ResetDocumentStatusResult;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.AiContentSensitivity;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.AiInvocationPort;
|
||||
@@ -683,6 +686,7 @@ public class BootstrapRunner {
|
||||
de.gecheckt.pdf.umbenenner.adapter.in.gui.batchrun.GuiResetDocumentStatusPort resetPort =
|
||||
this::resetDocumentStatusForGui;
|
||||
GuiManualFileRenamePort manualRenamePort = this::performGuiManualFileRename;
|
||||
GuiHistoricalFileNamePort historicalFileNamePort = this::resolveHistoricalFileNameForGui;
|
||||
|
||||
if (configPathOverride.isEmpty()) {
|
||||
return new GuiStartupContext(
|
||||
@@ -699,7 +703,8 @@ public class BootstrapRunner {
|
||||
batchRunLauncher,
|
||||
miniRunLauncher,
|
||||
resetPort,
|
||||
manualRenamePort);
|
||||
manualRenamePort,
|
||||
historicalFileNamePort);
|
||||
}
|
||||
|
||||
Path configPath = Paths.get(configPathOverride.get());
|
||||
@@ -721,7 +726,8 @@ public class BootstrapRunner {
|
||||
batchRunLauncher,
|
||||
miniRunLauncher,
|
||||
resetPort,
|
||||
manualRenamePort);
|
||||
manualRenamePort,
|
||||
historicalFileNamePort);
|
||||
}
|
||||
|
||||
LOG.info("GUI startup: configuration file confirmed at: {}", configPath.toAbsolutePath());
|
||||
@@ -730,7 +736,7 @@ public class BootstrapRunner {
|
||||
return new GuiStartupContext(loadedState, Optional.empty(), loader, writer,
|
||||
modelCatalogPort, apiKeyResolutionPort, providerTechnicalTestService, pathCheckPort,
|
||||
technicalTestOrchestrator, correctionExecutionService, batchRunLauncher,
|
||||
miniRunLauncher, resetPort, manualRenamePort);
|
||||
miniRunLauncher, resetPort, manualRenamePort, historicalFileNamePort);
|
||||
} catch (GuiConfigurationLoadException e) {
|
||||
LOG.error("GUI startup: configuration could not be loaded, starting without it: {}",
|
||||
e.getMessage(), e);
|
||||
@@ -748,7 +754,8 @@ public class BootstrapRunner {
|
||||
batchRunLauncher,
|
||||
miniRunLauncher,
|
||||
resetPort,
|
||||
manualRenamePort);
|
||||
manualRenamePort,
|
||||
historicalFileNamePort);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1062,6 +1069,49 @@ public class BootstrapRunner {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the historical AI-proposed target filename for a document identified by
|
||||
* {@code fingerprint}, using the configuration at {@code configFilePath}.
|
||||
* <p>
|
||||
* Loads the configuration, initialises the schema and delegates to
|
||||
* {@link ResolveHistoricalFileNameUseCase}. Technical errors during loading or querying
|
||||
* are caught and returned as an empty {@link Optional}; they are never propagated to the
|
||||
* caller.
|
||||
* <p>
|
||||
* Runs on the GUI worker thread. Blocking I/O is therefore acceptable.
|
||||
*
|
||||
* @param configFilePath path to the active {@code .properties} file; must not be {@code null}
|
||||
* @param fingerprint content-based document identity; must not be {@code null}
|
||||
* @return the last successfully written target filename, or empty if not available
|
||||
*/
|
||||
Optional<String> resolveHistoricalFileNameForGui(
|
||||
Path configFilePath,
|
||||
DocumentFingerprint fingerprint) {
|
||||
Objects.requireNonNull(configFilePath, "configFilePath must not be null");
|
||||
Objects.requireNonNull(fingerprint, "fingerprint must not be null");
|
||||
|
||||
if (!Files.exists(configFilePath)) {
|
||||
LOG.debug("Historischer Dateiname: Konfigurationsdatei nicht gefunden: {}", configFilePath);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
try {
|
||||
migrateConfigurationIfNeeded(configFilePath);
|
||||
StartConfiguration config = loadAndValidateConfiguration(configFilePath);
|
||||
initializeSchema(config);
|
||||
String jdbcUrl = buildJdbcUrl(config);
|
||||
DocumentRecordRepository documentRecordRepository =
|
||||
new SqliteDocumentRecordRepositoryAdapter(jdbcUrl);
|
||||
ResolveHistoricalFileNameUseCase useCase =
|
||||
new DefaultResolveHistoricalFileNameUseCase(documentRecordRepository);
|
||||
return useCase.resolveHistoricalFileName(fingerprint);
|
||||
} catch (Exception e) {
|
||||
LOG.debug("Historischer Dateiname konnte nicht abgefragt werden für {}: {}",
|
||||
fingerprint.sha256Hex(), e.getMessage());
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link ResetDocumentStatusResult} where every requested fingerprint is
|
||||
* recorded as a failure with the given error message.
|
||||
|
||||
Reference in New Issue
Block a user