95 lines
3.5 KiB
C#
95 lines
3.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Reflection;
|
|
using System.Text.RegularExpressions;
|
|
using F4SD.ActionConnector.Payloads;
|
|
|
|
namespace F4SD.ActionConnector.Execution
|
|
{
|
|
/// <summary>
|
|
/// Resolves template variables such as {{Case.Id}} or {{Case.ClosedAt:yyyy-MM-ddTHH:mm:ssZ}}
|
|
/// against a payload object.
|
|
///
|
|
/// Variable format: {{ObjectName.PropertyName[:FormatSpecifier]}}
|
|
/// </summary>
|
|
internal static class PayloadVariableResolver
|
|
{
|
|
private static readonly Regex VariablePattern =
|
|
new Regex(@"\{\{(?<obj>[^.}]+)\.(?<prop>[^:}]+)(?::(?<fmt>[^}]+))?\}\}",
|
|
RegexOptions.Compiled);
|
|
|
|
/// <summary>
|
|
/// Returns a new dictionary with every value in <paramref name="rawParameters"/> having
|
|
/// its template variables replaced by the corresponding payload property values.
|
|
/// Pure single-variable templates (e.g. <c>{{Case.ClosedAt}}</c>) yield the raw typed
|
|
/// object; mixed or formatted templates yield a resolved string.
|
|
/// </summary>
|
|
internal static IDictionary<string, object> Resolve(
|
|
IDictionary<string, string> rawParameters,
|
|
PayloadBase payload)
|
|
{
|
|
var resolved = new Dictionary<string, object>(rawParameters.Count);
|
|
|
|
foreach (var pair in rawParameters)
|
|
resolved[pair.Key] = ResolveValue(pair.Value, payload);
|
|
|
|
return resolved;
|
|
}
|
|
|
|
private static object ResolveValue(string template, PayloadBase payload)
|
|
{
|
|
var match = VariablePattern.Match(template);
|
|
|
|
// Pure single variable with no format specifier → return raw object
|
|
if (match.Success && match.Value == template && !match.Groups["fmt"].Success)
|
|
return ResolveRawProperty(match, payload);
|
|
|
|
// Mixed template, literal, or explicit format specifier → return resolved string
|
|
return ResolveString(template, payload);
|
|
}
|
|
|
|
private static object ResolveRawProperty(Match match, PayloadBase payload)
|
|
{
|
|
string propertyName = match.Groups["prop"].Value;
|
|
|
|
PropertyInfo property = payload.GetType().GetProperty(
|
|
propertyName,
|
|
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
|
|
|
if (property == null)
|
|
return match.Value;
|
|
|
|
return property.GetValue(payload);
|
|
}
|
|
|
|
private static string ResolveString(string template, PayloadBase payload)
|
|
{
|
|
return VariablePattern.Replace(template, match => ResolveMatch(match, payload));
|
|
}
|
|
|
|
private static string ResolveMatch(Match match, PayloadBase payload)
|
|
{
|
|
string propertyName = match.Groups["prop"].Value;
|
|
string formatSpecifier = match.Groups["fmt"].Success ? match.Groups["fmt"].Value : null;
|
|
|
|
PropertyInfo property = payload.GetType().GetProperty(
|
|
propertyName,
|
|
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
|
|
|
if (property == null)
|
|
return match.Value;
|
|
|
|
object value = property.GetValue(payload);
|
|
|
|
if (value == null)
|
|
return string.Empty;
|
|
|
|
if (formatSpecifier != null && value is IFormattable formattable)
|
|
return formattable.ToString(formatSpecifier, CultureInfo.InvariantCulture);
|
|
|
|
return value.ToString();
|
|
}
|
|
}
|
|
}
|