using System; using System.Globalization; namespace FrameworkBLL.GOP.Transform { // ============================================================ // ITransformExpression — extension point for mapping node transforms. // // Each implementation handles one transform key (e.g. "UPPER", "ROUND"). // The Key property is matched case-insensitively against the // MMAPPINGNODE.TRANSFORMEXPRESSION column value. // // Expression syntax: // "UPPER" → Key="UPPER", argument=null // "ROUND:2" → Key="ROUND", argument="2" // "FORMAT_DATE:yyyy-MM-dd" → Key="FORMAT_DATE", argument="yyyy-MM-dd" // // Registration (Program.cs in any SL project): // services.AddTransformExpression(); // services.AddTransformExpression(); // ============================================================ public interface ITransformExpression { /// /// The transform key matched against MMAPPINGNODE.TRANSFORMEXPRESSION. /// Comparison is case-insensitive. /// string Key { get; } /// /// Apply the transform to . /// /// The raw string value extracted from the source path. /// /// The part of the expression after the first colon, or null if none. /// Example: for "ROUND:2" the argument is "2". /// /// The transformed string value, or the original if transformation cannot be applied. string Transform(string value, string? argument); } // ────────────────────────────────────────────────────────────── // Built-in implementations // ────────────────────────────────────────────────────────────── /// Converts the value to upper-case. public sealed class UpperTransform : ITransformExpression { public string Key => "UPPER"; public string Transform(string value, string? argument) => value.ToUpperInvariant(); } /// Converts the value to lower-case. public sealed class LowerTransform : ITransformExpression { public string Key => "LOWER"; public string Transform(string value, string? argument) => value.ToLowerInvariant(); } /// Trims leading and trailing whitespace. public sealed class TrimTransform : ITransformExpression { public string Key => "TRIM"; public string Transform(string value, string? argument) => value.Trim(); } /// Returns an empty string if the value is null or whitespace. public sealed class NullToEmptyTransform : ITransformExpression { public string Key => "NULL_TO_EMPTY"; public string Transform(string value, string? argument) => string.IsNullOrWhiteSpace(value) ? string.Empty : value; } /// /// Ignores the resolved source value entirely and returns the fixed literal /// supplied as the argument. Lets a mapping node populate a target field with /// a constant (e.g. a default status code) regardless of what SourcePath resolves to. /// Expression: "CONST:Active" (argument = "Active"). /// public sealed class ConstTransform : ITransformExpression { public string Key => "CONST"; public string Transform(string value, string? argument) => argument ?? string.Empty; } /// /// Rounds a decimal value to N decimal places. /// Expression: "ROUND:2" (argument = "2"). /// Falls through unchanged if the value is not a valid decimal or argument is invalid. /// public sealed class RoundTransform : ITransformExpression { public string Key => "ROUND"; public string Transform(string value, string? argument) { if (!decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var d)) return value; if (!int.TryParse(argument, out int places) || places < 0 || places > 28) return value; return Math.Round(d, places, MidpointRounding.AwayFromZero) .ToString(CultureInfo.InvariantCulture); } } /// /// Formats a date/time value using the supplied format string. /// Expression: "FORMAT_DATE:yyyy-MM-dd" (argument = "yyyy-MM-dd"). /// Falls through unchanged if the value cannot be parsed as a DateTime. /// public sealed class FormatDateTransform : ITransformExpression { public string Key => "FORMAT_DATE"; public string Transform(string value, string? argument) { if (string.IsNullOrWhiteSpace(argument)) return value; if (!DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var dt)) return value; return dt.ToString(argument, CultureInfo.InvariantCulture); } } /// /// Parses the value as a decimal and returns it in invariant-culture numeric format /// (removes currency symbols, thousand separators, normalises locale decimal point). /// Falls through unchanged if the value cannot be parsed. /// public sealed class ToNumberTransform : ITransformExpression { public string Key => "TO_NUMBER"; public string Transform(string value, string? argument) { if (!decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var d)) return value; return d.ToString(CultureInfo.InvariantCulture); } } /// /// Parses the value as a DateTime and returns it in ISO 8601 UTC format (yyyy-MM-ddTHH:mm:ssZ). /// Falls through unchanged if the value cannot be parsed. /// public sealed class ToDateTimeTransform : ITransformExpression { public string Key => "TO_DATETIME"; public string Transform(string value, string? argument) { if (!DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var dt)) return value; return dt.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture); } } }