using RobotNet10.CustomConfiguration.Models; using System.Globalization; namespace RobotNet10.CustomConfiguration.Validators; /// /// Validator cho config files và variables /// public static class ConfigValidator { /// /// Validate một config file /// public static ValidationResult ValidateConfig(ConfigFile config) { var errors = new List(); // Validate ConfigType if (string.IsNullOrWhiteSpace(config.ConfigType)) { errors.Add("ConfigType cannot be empty"); } // Validate Variables if (config.Variables != null && config.Variables.Count > 0) { foreach (var variable in config.Variables) { var variableErrors = ValidateVariable(variable); errors.AddRange(variableErrors); } } return new ValidationResult { IsValid = errors.Count == 0, Errors = errors }; } /// /// Validate một variable /// public static List ValidateVariable(ConfigVariable variable) { var errors = new List(); // Validate Name if (string.IsNullOrWhiteSpace(variable.Name)) { errors.Add("Variable name cannot be empty"); } // Validate Type if (!Enum.IsDefined(variable.Type)) { errors.Add($"Invalid variable type: {variable.Type}"); } // Validate Value theo Type if (variable.Value == null) { errors.Add($"Variable '{variable.Name}' value cannot be null"); } else { var valueErrors = ValidateValueByType(variable.Name, variable.Type, variable.Value, variable.Min, variable.Max, variable); errors.AddRange(valueErrors); } return errors; } /// /// Validate value theo type và Min/Max constraints /// private static List ValidateValueByType(string variableName, ConfigVariableType type, object value, double? min, double? max, ConfigVariable? variable = null) { var errors = new List(); switch (type) { case ConfigVariableType.Int: // Try parse if (int.TryParse(value.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedInt)) { if (min.HasValue && parsedInt < min.Value) errors.Add($"Variable '{variableName}' value {parsedInt} is less than Min {min.Value}"); if (max.HasValue && parsedInt > max.Value) errors.Add($"Variable '{variableName}' value {parsedInt} is greater than Max {max.Value}"); } else { errors.Add($"Variable '{variableName}' must be an integer"); } break; case ConfigVariableType.Double: // Try parse if (double.TryParse(value.ToString(), NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var parsedDouble)) { if (min.HasValue && parsedDouble < min.Value) errors.Add($"Variable '{variableName}' value {parsedDouble} is less than Min {min.Value}"); if (max.HasValue && parsedDouble > max.Value) errors.Add($"Variable '{variableName}' value {parsedDouble} is greater than Max {max.Value}"); } else { errors.Add($"Variable '{variableName}' must be a double"); } break; case ConfigVariableType.Bool: if (!bool.TryParse(value.ToString(), out _)) { errors.Add($"Variable '{variableName}' must be a boolean"); } break; case ConfigVariableType.Object: // Object có thể là Dictionary hoặc JsonElement if (value is not Dictionary && value is not System.Text.Json.JsonElement) { // Try parse as JSON object try { var jsonString = value.ToString(); if (jsonString != null) { using var doc = System.Text.Json.JsonDocument.Parse(jsonString); if (doc.RootElement.ValueKind != System.Text.Json.JsonValueKind.Object) { errors.Add($"Variable '{variableName}' must be a JSON object"); } } } catch (System.Text.Json.JsonException) { errors.Add($"Variable '{variableName}' must be a valid JSON object"); } } break; case ConfigVariableType.Array: // Array có thể là List hoặc JsonElement if (value is not List && value is not System.Text.Json.JsonElement) { // Try parse as JSON array try { var jsonString = value.ToString(); if (jsonString != null) { using var doc = System.Text.Json.JsonDocument.Parse(jsonString); if (doc.RootElement.ValueKind != System.Text.Json.JsonValueKind.Array) { errors.Add($"Variable '{variableName}' must be a JSON array"); } } } catch (System.Text.Json.JsonException) { errors.Add($"Variable '{variableName}' must be a valid JSON array"); } } break; case ConfigVariableType.Enum: if (variable == null || variable.EnumValues == null || variable.EnumValues.Count == 0) { errors.Add($"Variable '{variableName}' of type Enum must have EnumValues defined"); } else { var valueStr = value?.ToString(); if (string.IsNullOrEmpty(valueStr) || !variable.EnumValues.Contains(valueStr)) { errors.Add($"Variable '{variableName}' value '{valueStr}' is not in allowed enum values: {string.Join(", ", variable.EnumValues)}"); } } break; } return errors; } } /// /// Kết quả validation /// public class ValidationResult { public bool IsValid { get; set; } public List Errors { get; set; } = []; }