From e8ed17e426bd68a5dd642169f80bf587c0cc99a6 Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Fri, 13 Oct 2023 14:14:24 +0200 Subject: [PATCH] Refactored validation logic into SettingsValidator class This commit decomposes the validation logic previously located in the `GenerateCommand` class, and moves it into its own `SettingsValidator` class for better organization and reusability. This provides a cleaner architecture and easier future maintenance, as now settings validation can be altered independent from command generation logic. --- src/Refitter/GenerateCommand.cs | 52 +------------- src/Refitter/SettingsValidator.cs | 116 ++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 50 deletions(-) create mode 100644 src/Refitter/SettingsValidator.cs diff --git a/src/Refitter/GenerateCommand.cs b/src/Refitter/GenerateCommand.cs index f46f1c90..8104ef97 100644 --- a/src/Refitter/GenerateCommand.cs +++ b/src/Refitter/GenerateCommand.cs @@ -19,50 +19,8 @@ public override ValidationResult Validate(CommandContext context, Settings setti if (!settings.NoLogging) Analytics.Configure(); - if (string.IsNullOrWhiteSpace(settings.OpenApiPath) && - string.IsNullOrWhiteSpace(settings.SettingsFilePath)) - return ValidationResult.Error("Input or settings file is required"); - - if (!string.IsNullOrWhiteSpace(settings.OpenApiPath) && - !string.IsNullOrWhiteSpace(settings.SettingsFilePath)) - return ValidationResult.Error( - "You should either specify an input URL/file directly " + - "or use specify it in 'openApiPath' from the settings file, " + - "not both"); - - if (!string.IsNullOrWhiteSpace(settings.SettingsFilePath)) - { - var json = File.ReadAllText(settings.SettingsFilePath); - var refitGeneratorSettings = Serializer.Deserialize(json); - settings.OpenApiPath = refitGeneratorSettings.OpenApiPath; - - if (string.IsNullOrWhiteSpace(refitGeneratorSettings.OpenApiPath)) - return ValidationResult.Error( - "The 'openApiPath' in settings file is required when " + - "URL or file path to OpenAPI Specification file " + - "is not specified in command line argument"); - - if (!string.IsNullOrWhiteSpace(settings.OutputPath) && - settings.OutputPath != Settings.DefaultOutputPath && - (!string.IsNullOrWhiteSpace(refitGeneratorSettings.OutputFolder) || - !string.IsNullOrWhiteSpace(refitGeneratorSettings.OutputFilename))) - return ValidationResult.Error( - "You should either specify an output path directly from --output " + - "or use specify it in 'outputFolder' and 'outputFilename' from the settings file, " + - "not both"); - } - - if (!string.IsNullOrWhiteSpace(settings.OperationNameTemplate) && - !settings.OperationNameTemplate.Contains("{operationName}") && - settings.MultipleInterfaces != MultipleInterfaces.ByEndpoint) - return ValidationResult.Error("'{operationName}' placeholder must be present in operation name template"); - - if (IsUrl(settings.OpenApiPath!)) - return base.Validate(context, settings); - - return File.Exists(settings.OpenApiPath) - ? base.Validate(context, settings) - : ValidationResult.Error($"File not found - {Path.GetFullPath(settings.OpenApiPath!)}"); + return new SettingsValidator() + .Validate(context, settings); } public override async Task ExecuteAsync(CommandContext context, Settings settings) @@ -192,10 +150,4 @@ private static void TryWriteLine( // ignored } } - - private static bool IsUrl(string openApiPath) - { - return Uri.TryCreate(openApiPath, UriKind.Absolute, out var uriResult) && - (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); - } } \ No newline at end of file diff --git a/src/Refitter/SettingsValidator.cs b/src/Refitter/SettingsValidator.cs new file mode 100644 index 00000000..bc9d07f6 --- /dev/null +++ b/src/Refitter/SettingsValidator.cs @@ -0,0 +1,116 @@ +using Refitter.Core; + +using Spectre.Console; +using Spectre.Console.Cli; + +namespace Refitter; + +public class SettingsValidator +{ + public ValidationResult Validate(CommandContext context, Settings settings) + { + if (BothSettingsFilesAreEmpty(settings) || BothSettingsFilesArePresent(settings)) + { + return GetValidationErrorForSettingsFiles(); + } + + return !string.IsNullOrWhiteSpace(settings.SettingsFilePath) + ? ValidateFilePath(settings) + : ValidateOperationNameAndUrl(settings); + } + + private static bool BothSettingsFilesAreEmpty(Settings settings) + { + return string.IsNullOrWhiteSpace(settings.OpenApiPath) && + string.IsNullOrWhiteSpace(settings.SettingsFilePath); + } + + private static bool BothSettingsFilesArePresent(Settings settings) + { + return !string.IsNullOrWhiteSpace(settings.OpenApiPath) && + !string.IsNullOrWhiteSpace(settings.SettingsFilePath); + } + + private static ValidationResult GetValidationErrorForSettingsFiles() + { + return ValidationResult.Error( + "You should either specify an input URL/file directly " + + "or use specify it in 'openApiPath' from the settings file, " + + "not both"); + } + + private ValidationResult ValidateFilePath(Settings settings) + { + var json = File.ReadAllText(settings.SettingsFilePath!); + var refitGeneratorSettings = Serializer.Deserialize(json); + settings.OpenApiPath = refitGeneratorSettings.OpenApiPath; + + return ValidateFileAndOutputSettings(settings, refitGeneratorSettings); + } + + private ValidationResult ValidateFileAndOutputSettings( + Settings settings, + RefitGeneratorSettings refitGeneratorSettings) + { + if (string.IsNullOrWhiteSpace(refitGeneratorSettings.OpenApiPath)) + { + return GetValidationErrorForOpenApiPath(); + } + + if (!string.IsNullOrWhiteSpace(settings.OutputPath) && + settings.OutputPath != Settings.DefaultOutputPath && + (!string.IsNullOrWhiteSpace(refitGeneratorSettings.OutputFolder) || + !string.IsNullOrWhiteSpace(refitGeneratorSettings.OutputFilename))) + { + return GetValidationErrorForOutputPath(); + } + + return ValidateOperationNameAndUrl(settings); + } + + private static ValidationResult GetValidationErrorForOpenApiPath() + { + return ValidationResult.Error( + "The 'openApiPath' in settings file is required when " + + "URL or file path to OpenAPI Specification file " + + "is not specified in command line argument"); + } + + private static ValidationResult GetValidationErrorForOutputPath() + { + return ValidationResult.Error( + "You should either specify an output path directly from --output " + + "or use specify it in 'outputFolder' and 'outputFilename' from the settings file, " + + "not both"); + } + + private ValidationResult ValidateOperationNameAndUrl(Settings settings) + { + if (!string.IsNullOrWhiteSpace(settings.OperationNameTemplate) && + !settings.OperationNameTemplate.Contains("{operationName}") && + settings.MultipleInterfaces != MultipleInterfaces.ByEndpoint) + { + return GetValidationErrorForOperationName(); + } + + return IsUrl(settings.OpenApiPath!) ? ValidationResult.Success() : ValidateFileExistence(settings); + } + + private static ValidationResult GetValidationErrorForOperationName() + { + return ValidationResult.Error("'{operationName}' placeholder must be present in operation name template"); + } + + private ValidationResult ValidateFileExistence(Settings settings) + { + return File.Exists(settings.OpenApiPath) + ? ValidationResult.Success() + : ValidationResult.Error($"File not found - {Path.GetFullPath(settings.OpenApiPath!)}"); + } + + private static bool IsUrl(string openApiPath) + { + return Uri.TryCreate(openApiPath, UriKind.Absolute, out var uriResult) && + (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); + } +} \ No newline at end of file