AddConnectionUseCase.cs 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. using RackPeek.Domain.Helpers;
  2. using RackPeek.Domain.Persistence;
  3. using RackPeek.Domain.Resources.Servers;
  4. using RackPeek.Domain.Resources.SubResources;
  5. namespace RackPeek.Domain.Resources.Connections;
  6. public interface IAddConnectionUseCase {
  7. Task ExecuteAsync(
  8. PortReference a,
  9. PortReference b,
  10. string? label = null,
  11. string? notes = null);
  12. }
  13. public class AddConnectionUseCase(IResourceCollection repository)
  14. : IAddConnectionUseCase {
  15. public async Task ExecuteAsync(
  16. PortReference a,
  17. PortReference b,
  18. string? label,
  19. string? notes) {
  20. a.Resource = Normalize.HardwareName(a.Resource);
  21. b.Resource = Normalize.HardwareName(b.Resource);
  22. ThrowIfInvalid.ResourceName(a.Resource);
  23. ThrowIfInvalid.ResourceName(b.Resource);
  24. if (PortsMatch(a, b))
  25. throw new InvalidOperationException(
  26. "Cannot connect a port to itself.");
  27. await ValidatePortReference(a);
  28. await ValidatePortReference(b);
  29. // Overwrite behavior:
  30. // each PortReference may appear in only one connection,
  31. // so remove any existing connection involving either endpoint.
  32. await repository.RemoveConnectionsForPortAsync(a);
  33. await repository.RemoveConnectionsForPortAsync(b);
  34. var connection = new Connection {
  35. A = a,
  36. B = b,
  37. Label = label,
  38. Notes = notes
  39. };
  40. await repository.AddConnectionAsync(connection);
  41. }
  42. private async Task ValidatePortReference(PortReference port) {
  43. Resource resource =
  44. await repository.GetByNameAsync<Resource>(port.Resource)
  45. ?? throw new NotFoundException($"Resource '{port.Resource}' not found.");
  46. if (resource is not IPortResource pr || pr.Ports == null)
  47. throw new InvalidOperationException($"Resource '{port.Resource}' has no ports.");
  48. if (port.PortGroup < 0 || port.PortGroup >= pr.Ports.Count)
  49. throw new NotFoundException($"Port group {port.PortGroup} not found.");
  50. Port group = pr.Ports[port.PortGroup];
  51. if (port.PortIndex < 0 || port.PortIndex >= (group.Count ?? 0))
  52. throw new NotFoundException($"Port index {port.PortIndex} not found.");
  53. }
  54. private static bool PortsMatch(PortReference a, PortReference b) {
  55. return a.Resource.Equals(b.Resource, StringComparison.OrdinalIgnoreCase)
  56. && a.PortGroup == b.PortGroup
  57. && a.PortIndex == b.PortIndex;
  58. }
  59. }