ConnectionMerger.cs 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. using RackPeek.Domain.Resources.Connections;
  2. namespace RackPeek.Domain.Persistence;
  3. public static class ConnectionMerger {
  4. /// <summary>
  5. /// Merges an imported connections section into the existing set.
  6. /// Returns null when the import carries no connections section — the
  7. /// existing connections are kept untouched in that case (#308).
  8. /// Replace mode swaps the whole set; Merge mode applies the same
  9. /// overwrite rule as the UI (a port holds at most one connection, so
  10. /// each incoming connection evicts anything touching its endpoints).
  11. /// </summary>
  12. public static List<Connection>? Merge(
  13. IReadOnlyList<Connection> existing,
  14. List<Connection>? incoming,
  15. MergeMode mode) {
  16. if (incoming == null)
  17. return null;
  18. if (mode == MergeMode.Replace)
  19. return incoming.ToList();
  20. var merged = existing.ToList();
  21. foreach (Connection connection in incoming) {
  22. merged.RemoveAll(c =>
  23. Touches(c, connection.A) || Touches(c, connection.B));
  24. merged.Add(connection);
  25. }
  26. return merged;
  27. }
  28. public static string Describe(Connection c) =>
  29. $"{Describe(c.A)} <-> {Describe(c.B)}";
  30. private static string Describe(PortReference p) =>
  31. $"{p.Resource}[{p.PortGroup}.{p.PortIndex}]";
  32. private static bool Touches(Connection c, PortReference port) =>
  33. PortsMatch(c.A, port) || PortsMatch(c.B, port);
  34. private static bool PortsMatch(PortReference a, PortReference b) {
  35. return a.Resource.Equals(b.Resource, StringComparison.OrdinalIgnoreCase)
  36. && a.PortGroup == b.PortGroup
  37. && a.PortIndex == b.PortIndex;
  38. }
  39. }