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; } }