w4c-workflows-api/Services/Nodes/Executors/NodeValueAccess.cs
2026-09-12 01:02:46 +03:00

88 lines
3.2 KiB
C#

using System.Globalization;
using System.Text.Json.Nodes;
namespace w4c_workflows.Services.Nodes.Executors;
/// <summary>
/// Typed readers over resolved node parameters. YAML scalars arrive as int,
/// long, decimal, double, bool or string, so the readers normalise the shapes
/// and apply a fallback instead of throwing. Shared so every executor reads a
/// bool/number/array the same way.
/// </summary>
internal static class NodeValueAccess
{
public static string? ReadString(JsonObject parameters, string name)
=> parameters[name] is JsonValue value && value.TryGetValue<string>(out var text) ? text : null;
public static bool ReadBool(JsonObject parameters, string name, bool defaultValue = false)
=> parameters[name] is JsonValue value && value.TryGetValue<bool>(out var flag) ? flag : defaultValue;
public static int ReadInt(JsonObject parameters, string name, int defaultValue)
=> TryReadNumber(parameters[name], out var number) ? (int)number : defaultValue;
public static double ReadNumber(JsonObject parameters, string name, double defaultValue)
=> TryReadNumber(parameters[name], out var number) ? number : defaultValue;
public static JsonArray? ReadArray(JsonObject parameters, string name)
=> parameters[name] as JsonArray;
public static JsonObject? ReadObject(JsonObject parameters, string name)
=> parameters[name] as JsonObject;
/// <summary>Reads any JSON number shape (int/long/decimal/double) or a numeric string.</summary>
public static bool TryReadNumber(JsonNode? node, out double value)
{
value = 0;
if (node is not JsonValue jsonValue)
return false;
if (jsonValue.TryGetValue<double>(out var doubleValue))
{
value = doubleValue;
return true;
}
if (jsonValue.TryGetValue<decimal>(out var decimalValue))
{
value = (double)decimalValue;
return true;
}
if (jsonValue.TryGetValue<long>(out var longValue))
{
value = longValue;
return true;
}
if (jsonValue.TryGetValue<int>(out var intValue))
{
value = intValue;
return true;
}
return jsonValue.TryGetValue<string>(out var text)
&& double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out value);
}
/// <summary>
/// Renders a fixed-collection parameter as a list of objects. The
/// interpolator yields an array for the normal case, but a single entry may
/// arrive as a bare object; both are accepted.
/// </summary>
public static IReadOnlyList<JsonObject> ReadEntries(JsonObject parameters, string name)
{
var entries = new List<JsonObject>();
switch (parameters[name])
{
case JsonArray array:
foreach (var element in array)
{
if (element is JsonObject entry)
entries.Add(entry);
}
break;
case JsonObject single:
entries.Add(single);
break;
}
return entries;
}
}