tbf/GenesisCordonelInterface/Core/Config/GciConfigLoader.cs

177 lines
5.2 KiB
C#

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
{
/// <summary>
/// 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=...
/// </summary>
public static class GciConfigLoader
{
/// <summary>
/// Loads default GCI configuration from:
///
/// Config\gci_config.json
/// </summary>
/// <returns>
/// Loaded GCI configuration.
/// </returns>
public static GciConfig LoadDefault()
{
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
string configPath = Path.Combine(
baseDirectory,
"Config",
"gci_config.json");
return Load(configPath, baseDirectory);
}
/// <summary>
/// Loads GCI configuration from specified file.
/// </summary>
/// <param name="configPath">
/// Path to configuration json file.
/// </param>
/// <param name="baseDirectory">
/// Base directory used for resolving relative paths.
/// </param>
/// <returns>
/// Loaded configuration object.
/// </returns>
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<GciConfig>(json);
if (config == null)
throw new InvalidOperationException(
"GCI config could not be loaded.");
NormalizeDataStoragePaths(
config,
baseDirectory ?? Path.GetDirectoryName(configPath));
return config;
}
/// <summary>
/// Normalizes paths for all configured data storage entries.
///
/// Converts relative file paths into absolute paths.
/// Database connection strings remain untouched.
/// </summary>
/// <param name="config">
/// Loaded configuration object.
/// </param>
/// <param name="baseDirectory">
/// Base path used for relative resolution.
/// </param>
private static void NormalizeDataStoragePaths(
GciConfig config,
string baseDirectory)
{
if (config.DataStorageSection == null)
return;
NormalizePath(
config.DataStorageSection.MeterLoginPasswords,
baseDirectory);
NormalizePath(
config.DataStorageSection.PreAdjustmentCalibrationParams,
baseDirectory);
}
/// <summary>
/// Converts relative file paths into absolute paths.
///
/// Applies only to:
/// - LocalCsv
/// - RemoteCsv
/// - LocalJson
/// - RemoteJson
///
/// Does not modify:
/// - Database connection strings
/// - REST URLs
/// </summary>
/// <param name="storageConfig">
/// Storage configuration.
/// </param>
/// <param name="baseDirectory">
/// Base path for resolution.
/// </param>
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));
}
}
}