using System; using System.IO; using GenesisCordonelInterface.Core.DataStorage.Reading.Common; using GenesisCordonelInterface.Core.DataStorage.Reading.Common.Models; using Newtonsoft.Json; namespace GenesisCordonelInterface.Core.Config { /// /// Loads GCI configuration from gci_config.json. /// /// Responsibilities: /// - Locate configuration file /// - Deserialize JSON into strongly typed objects /// - Normalize relative file paths /// - Preserve database connection strings and REST URLs /// /// Example: /// /// Config/ /// gci_config.json /// /// Data/ /// meter_passwords.csv /// /// Relative paths: /// Data\file.csv /// /// become: /// /// C:\App\bin\Debug\Data\file.csv /// /// Database sources remain unchanged: /// /// Server=(localdb)\MojaDB;Database=... /// public static class GciConfigLoader { /// /// Loads default GCI configuration from: /// /// Config\gci_config.json /// /// /// Loaded GCI configuration. /// public static GciConfig LoadDefault() { string baseDirectory = AppDomain.CurrentDomain.BaseDirectory; string configPath = Path.Combine( baseDirectory, "Config", "gci_config.json"); return Load(configPath, baseDirectory); } /// /// Loads GCI configuration from specified file. /// /// /// Path to configuration json file. /// /// /// Base directory used for resolving relative paths. /// /// /// Loaded configuration object. /// public static GciConfig Load( string configPath, string baseDirectory = null) { if (string.IsNullOrWhiteSpace(configPath)) throw new ArgumentException( "Config path must not be empty.", nameof(configPath)); if (!File.Exists(configPath)) throw new FileNotFoundException( "GCI config file was not found.", configPath); string json = File.ReadAllText(configPath); GciConfig config = JsonConvert.DeserializeObject(json); if (config == null) throw new InvalidOperationException( "GCI config could not be loaded."); NormalizeDataStoragePaths( config, baseDirectory ?? Path.GetDirectoryName(configPath)); return config; } /// /// Normalizes paths for all configured data storage entries. /// /// Converts relative file paths into absolute paths. /// Database connection strings remain untouched. /// /// /// Loaded configuration object. /// /// /// Base path used for relative resolution. /// private static void NormalizeDataStoragePaths( GciConfig config, string baseDirectory) { if (config.DataStorageSection == null) return; NormalizePath( config.DataStorageSection.MeterLoginPasswords, baseDirectory); NormalizePath( config.DataStorageSection.PreAdjustmentCalibrationParams, baseDirectory); } /// /// Converts relative file paths into absolute paths. /// /// Applies only to: /// - LocalCsv /// - RemoteCsv /// - LocalJson /// - RemoteJson /// /// Does not modify: /// - Database connection strings /// - REST URLs /// /// /// Storage configuration. /// /// /// Base path for resolution. /// private static void NormalizePath( DataStorageConfig storageConfig, string baseDirectory) { if (storageConfig == null) return; if (string.IsNullOrWhiteSpace(storageConfig.DataSource)) return; // Database connection strings and URLs // must never be treated as file paths. if (storageConfig.Type == DataStorageType.LocalDatabase || storageConfig.Type == DataStorageType.RemoteDatabase || storageConfig.Type == DataStorageType.RestApi) { return; } if (Path.IsPathRooted(storageConfig.DataSource)) return; storageConfig.DataSource = Path.GetFullPath( Path.Combine( baseDirectory, storageConfig.DataSource)); } } }