diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/BindingGroupBuilder.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/BindingGroupBuilder.cs index 43b2cb77..e801b162 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/BindingGroupBuilder.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/BindingGroupBuilder.cs @@ -114,4 +114,22 @@ public static class BindingGroupBuilder } return any ? (candidate, false) : (null, false); } + + /// Result of a bulk apply for one member. + public sealed record BindingChange(string CanonicalName, int? ConnectionId, string? Override); + + /// + /// Rewrites every member of to + /// {objectPath}.{memberTail} on . A blank + /// clears the overrides (template default applies) and + /// leaves the connection as given. Surrounding whitespace and a trailing '.' are tolerated. + /// + public static IReadOnlyList ApplyObject(BindingGroup group, int? connectionId, string? objectPath) + { + var obj = (objectPath ?? string.Empty).Trim().TrimEnd('.'); + return group.Members + .Select(m => new BindingChange(m.Row.CanonicalName, connectionId, + obj.Length == 0 ? null : obj + "." + m.MemberTail)) + .ToList(); + } } diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Services/BindingGroupBuilderTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Services/BindingGroupBuilderTests.cs index 21b969a4..488c4901 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Services/BindingGroupBuilderTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Services/BindingGroupBuilderTests.cs @@ -111,4 +111,35 @@ public class BindingGroupBuilderTests var rows = new[] { Row("M.A", "A", 1, "Obj.A"), Row("M.B", "B", 1, "Obj.Other") }; Assert.True(Assert.Single(BindingGroupBuilder.Build(rows)).IsObjectMixed); } + + [Fact] + public void ApplyObject_RewritesEveryMember_AndSetsConnection() + { + var g = Assert.Single(BindingGroupBuilder.Build(new[] + { + Row("RightMESReceiver.MoveInFlag", "MoveInFlag", 1, "MESReceiver_024.MoveInFlag"), + Row("RightMESReceiver.ScanStateCmd", "ScanStateCmd", null, null), + })); + var changes = BindingGroupBuilder.ApplyObject(g, connectionId: 1, objectPath: " MESReceiver_022. "); + Assert.Equal(2, changes.Count); + Assert.Equal(("RightMESReceiver.MoveInFlag", 1, "MESReceiver_022.MoveInFlag"), (changes[0].CanonicalName, changes[0].ConnectionId, changes[0].Override)); + Assert.Equal(("RightMESReceiver.ScanStateCmd", 1, "MESReceiver_022.ScanStateCmd"), (changes[1].CanonicalName, changes[1].ConnectionId, changes[1].Override)); + } + + [Fact] + public void ApplyObject_NestedTail_KeepsNesting() + { + var g = Assert.Single(BindingGroupBuilder.Build(new[] { Row("LeftReactorSide.LeakTest.DeltaVac", "DeltaVac", 1, null) })); + var c = Assert.Single(BindingGroupBuilder.ApplyObject(g, 1, "Left_002")); + Assert.Equal("Left_002.LeakTest.DeltaVac", c.Override); + } + + [Fact] + public void ApplyObject_EmptyObject_ClearsOverrides_KeepsConnection() + { + var g = Assert.Single(BindingGroupBuilder.Build(new[] { Row("M.A", "A", 1, "Obj.A") })); + var c = Assert.Single(BindingGroupBuilder.ApplyObject(g, 2, "")); + Assert.Null(c.Override); + Assert.Equal(2, c.ConnectionId); + } }