From 8278a16bbb7deb8819922cb924c8bc155a3f50a2 Mon Sep 17 00:00:00 2001 From: Marcus van Elst Date: Sun, 5 Apr 2026 20:54:42 +0200 Subject: [PATCH] Optimierung: StartConfigurationValidator strukturell vereinfacht --- .../StartConfigurationValidator.java | 161 ++++++++++++------ 1 file changed, 105 insertions(+), 56 deletions(-) diff --git a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/bootstrap/validation/StartConfigurationValidator.java b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/bootstrap/validation/StartConfigurationValidator.java index 80f9977..cc08560 100644 --- a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/bootstrap/validation/StartConfigurationValidator.java +++ b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/bootstrap/validation/StartConfigurationValidator.java @@ -79,26 +79,15 @@ public class StartConfigurationValidator { public void validate(StartConfiguration config) { List errors = new ArrayList<>(); - // Mandatory string/path presence checks - validateSourceFolder(config.sourceFolder(), errors); - validateTargetFolder(config.targetFolder(), errors); - validateSqliteFile(config.sqliteFile(), errors); - validateApiBaseUrl(config.apiBaseUrl(), errors); - validateApiModel(config.apiModel(), errors); - validatePromptTemplateFile(config.promptTemplateFile(), errors); + // Mandatory fields and required paths + validateMandatoryFields(config, errors); - // Numeric validation - validateApiTimeoutSeconds(config.apiTimeoutSeconds(), errors); - validateMaxRetriesTransient(config.maxRetriesTransient(), errors); - validateMaxPages(config.maxPages(), errors); - validateMaxTextCharacters(config.maxTextCharacters(), errors); + // Numeric constraints + validateNumericConstraints(config, errors); - // Path relationship validation + // Path relationships and optional paths validateSourceAndTargetNotSame(config.sourceFolder(), config.targetFolder(), errors); - - // Optional path validations (only if present) - validateRuntimeLockFile(config.runtimeLockFile(), errors); - validateLogDirectory(config.logDirectory(), errors); + validateOptionalPaths(config, errors); if (!errors.isEmpty()) { String errorMessage = "Invalid startup configuration:\n" + String.join("\n", errors); @@ -108,6 +97,27 @@ public class StartConfigurationValidator { LOG.info("Configuration validation successful."); } + private void validateMandatoryFields(StartConfiguration config, List errors) { + validateSourceFolder(config.sourceFolder(), errors); + validateTargetFolder(config.targetFolder(), errors); + validateSqliteFile(config.sqliteFile(), errors); + validateApiBaseUrl(config.apiBaseUrl(), errors); + validateApiModel(config.apiModel(), errors); + validatePromptTemplateFile(config.promptTemplateFile(), errors); + } + + private void validateNumericConstraints(StartConfiguration config, List errors) { + validateApiTimeoutSeconds(config.apiTimeoutSeconds(), errors); + validateMaxRetriesTransient(config.maxRetriesTransient(), errors); + validateMaxPages(config.maxPages(), errors); + validateMaxTextCharacters(config.maxTextCharacters(), errors); + } + + private void validateOptionalPaths(StartConfiguration config, List errors) { + validateRuntimeLockFile(config.runtimeLockFile(), errors); + validateLogDirectory(config.logDirectory(), errors); + } + private void validateSourceFolder(Path sourceFolder, List errors) { if (sourceFolder == null) { errors.add("- source.folder: must not be null"); @@ -120,30 +130,11 @@ public class StartConfigurationValidator { } private void validateTargetFolder(Path targetFolder, List errors) { - if (targetFolder == null) { - errors.add("- target.folder: must not be null"); - return; - } - if (!Files.exists(targetFolder)) { - errors.add("- target.folder: path does not exist: " + targetFolder); - } else if (!Files.isDirectory(targetFolder)) { - errors.add("- target.folder: path is not a directory: " + targetFolder); - } + validateRequiredExistingDirectory(targetFolder, "target.folder", errors); } private void validateSqliteFile(Path sqliteFile, List errors) { - if (sqliteFile == null) { - errors.add("- sqlite.file: must not be null"); - return; - } - Path parent = sqliteFile.getParent(); - if (parent == null) { - errors.add("- sqlite.file: has no parent directory: " + sqliteFile); - } else if (!Files.exists(parent)) { - errors.add("- sqlite.file: parent directory does not exist: " + parent); - } else if (!Files.isDirectory(parent)) { - errors.add("- sqlite.file: parent is not a directory: " + parent); - } + validateRequiredFileParentDirectory(sqliteFile, "sqlite.file", errors); } private void validateApiBaseUrl(java.net.URI apiBaseUrl, List errors) { @@ -192,15 +183,7 @@ public class StartConfigurationValidator { } private void validatePromptTemplateFile(Path promptTemplateFile, List errors) { - if (promptTemplateFile == null) { - errors.add("- prompt.template.file: must not be null"); - return; - } - if (!Files.exists(promptTemplateFile)) { - errors.add("- prompt.template.file: path does not exist: " + promptTemplateFile); - } else if (!Files.isRegularFile(promptTemplateFile)) { - errors.add("- prompt.template.file: path is not a regular file: " + promptTemplateFile); - } + validateRequiredRegularFile(promptTemplateFile, "prompt.template.file", errors); } private void validateSourceAndTargetNotSame(Path sourceFolder, Path targetFolder, List errors) { @@ -219,23 +202,89 @@ public class StartConfigurationValidator { } private void validateRuntimeLockFile(Path runtimeLockFile, List errors) { - if (runtimeLockFile != null && !runtimeLockFile.toString().isBlank()) { - Path parent = runtimeLockFile.getParent(); + validateOptionalFileParentDirectory(runtimeLockFile, "runtime.lock.file", errors); + } + + private void validateLogDirectory(Path logDirectory, List errors) { + validateOptionalExistingDirectory(logDirectory, "log.directory", errors); + } + + // === Helper methods for common validation patterns === + + /** + * Validates that a required path is not null, exists, and is a directory. + */ + private void validateRequiredExistingDirectory(Path path, String fieldName, List errors) { + if (path == null) { + errors.add("- " + fieldName + ": must not be null"); + return; + } + if (!Files.exists(path)) { + errors.add("- " + fieldName + ": path does not exist: " + path); + } else if (!Files.isDirectory(path)) { + errors.add("- " + fieldName + ": path is not a directory: " + path); + } + } + + /** + * Validates that a required file path is not null and its parent directory exists and is a directory. + */ + private void validateRequiredFileParentDirectory(Path filePath, String fieldName, List errors) { + if (filePath == null) { + errors.add("- " + fieldName + ": must not be null"); + return; + } + Path parent = filePath.getParent(); + if (parent == null) { + errors.add("- " + fieldName + ": has no parent directory: " + filePath); + } else if (!Files.exists(parent)) { + errors.add("- " + fieldName + ": parent directory does not exist: " + parent); + } else if (!Files.isDirectory(parent)) { + errors.add("- " + fieldName + ": parent is not a directory: " + parent); + } + } + + /** + * Validates that a required file path is not null, exists, and is a regular file. + */ + private void validateRequiredRegularFile(Path filePath, String fieldName, List errors) { + if (filePath == null) { + errors.add("- " + fieldName + ": must not be null"); + return; + } + if (!Files.exists(filePath)) { + errors.add("- " + fieldName + ": path does not exist: " + filePath); + } else if (!Files.isRegularFile(filePath)) { + errors.add("- " + fieldName + ": path is not a regular file: " + filePath); + } + } + + /** + * Validates that an optional file path, if present and non-blank, has a parent directory + * that exists and is a directory. + */ + private void validateOptionalFileParentDirectory(Path filePath, String fieldName, List errors) { + if (filePath != null && !filePath.toString().isBlank()) { + Path parent = filePath.getParent(); if (parent != null) { if (!Files.exists(parent)) { - errors.add("- runtime.lock.file: parent directory does not exist: " + parent); + errors.add("- " + fieldName + ": parent directory does not exist: " + parent); } else if (!Files.isDirectory(parent)) { - errors.add("- runtime.lock.file: parent is not a directory: " + parent); + errors.add("- " + fieldName + ": parent is not a directory: " + parent); } } } } - private void validateLogDirectory(Path logDirectory, List errors) { - if (logDirectory != null && !logDirectory.toString().isBlank()) { - if (Files.exists(logDirectory)) { - if (!Files.isDirectory(logDirectory)) { - errors.add("- log.directory: exists but is not a directory: " + logDirectory); + /** + * Validates that an optional directory path, if present and non-blank, either does not exist + * or exists and is a directory. + */ + private void validateOptionalExistingDirectory(Path directoryPath, String fieldName, List errors) { + if (directoryPath != null && !directoryPath.toString().isBlank()) { + if (Files.exists(directoryPath)) { + if (!Files.isDirectory(directoryPath)) { + errors.add("- " + fieldName + ": exists but is not a directory: " + directoryPath); } } // If it doesn't exist yet, that's acceptable - we don't auto-create