using System.Text.Json.Nodes;
using w4c_workflows.Models.Nodes;
namespace w4c_workflows.Services.Nodes.Executors;
///
/// Merge node. Combines two input ports into one:
/// - append — input 0 items then input 1 items;
/// - chooseBranch — the items of the first non-empty input;
/// - combineByPosition — pair items by index and shallow-merge their
/// fields (input 1 overrides input 0); items past the shorter input pass
/// through unchanged.
/// Runs in all-items mode because it has more than one input port.
///
public sealed class MergeNodeExecutor : INodeExecutor
{
public string Type => "core.merge";
public Task RunAsync(NodeExecutionContext context, CancellationToken ct)
{
var first = context.Input(0);
var second = context.Input(1);
var mode = context.Parameters["mode"] is JsonValue value && value.TryGetValue(out var text)
? text
: "append";
var items = mode switch
{
"chooseBranch" => first.Count > 0 ? first.ToList() : second.ToList(),
"combineByPosition" => CombineByPosition(first, second),
_ => first.Concat(second).ToList(),
};
return Task.FromResult(NodeExecutionOutcome.Single(items));
}
private static List CombineByPosition(
IReadOnlyList first, IReadOnlyList second)
{
var merged = new List(Math.Max(first.Count, second.Count));
for (var i = 0; i < first.Count || i < second.Count; i++)
{
var left = i < first.Count ? first[i] : null;
var right = i < second.Count ? second[i] : null;
if (left == null)
{
merged.Add(right!);
continue;
}
if (right == null)
{
merged.Add(left);
continue;
}
var json = (JsonObject)left.Json.DeepClone();
foreach (var (name, node) in right.Json)
json[name] = node?.DeepClone();
merged.Add(new FlowItem
{
Json = json,
Binary = left.Binary ?? right.Binary,
Origin = left.Origin ?? right.Origin,
});
}
return merged;
}
}