From 7e45205147545d9ce5fc9703937c363f29b3d601 Mon Sep 17 00:00:00 2001 From: Rune Nielsen Date: Tue, 4 Aug 2020 16:20:35 +0200 Subject: [PATCH] implements routenode moved without connecting segments --- .../RouteNodeGeometryModified.cs | 23 +++++ .../Factories/RouteNodeEventFactory.cs | 10 +- .../Notifications/RouteNodeLocationChanged.cs | 49 ++++++++++ .../RouteSegmentLocationChanged.cs | 2 - .../RouteNodeGeometryModifiedTest.cs | 39 ++++++++ .../Factories/RouteNodeEventFactoryTest.cs | 91 +++++++++++++++++++ 6 files changed, 209 insertions(+), 5 deletions(-) create mode 100644 src/OpenFTTH.GDBIntegrator.Integrator/EventMessages/RouteNodeGeometryModified.cs create mode 100644 src/OpenFTTH.GDBIntegrator.Integrator/Notifications/RouteNodeLocationChanged.cs create mode 100644 test/OpenFTTH.GDBIntegrator.Integrator.Tests/EventMessages/RouteNodeGeometryModifiedTest.cs diff --git a/src/OpenFTTH.GDBIntegrator.Integrator/EventMessages/RouteNodeGeometryModified.cs b/src/OpenFTTH.GDBIntegrator.Integrator/EventMessages/RouteNodeGeometryModified.cs new file mode 100644 index 0000000..da2eafb --- /dev/null +++ b/src/OpenFTTH.GDBIntegrator.Integrator/EventMessages/RouteNodeGeometryModified.cs @@ -0,0 +1,23 @@ +using System; + +namespace OpenFTTH.GDBIntegrator.Integrator.EventMessages +{ + public class RouteNodeGeometryModified + { + public readonly string EventType = nameof(RouteSegmentGeometryModified); + public readonly string EventTs = DateTime.UtcNow.ToString("o"); + public readonly Guid EventId = Guid.NewGuid(); + public Guid CmdId { get; } + public string CmdType { get; } + public Guid NodeId { get; } + public string Geometry { get; } + + public RouteNodeGeometryModified(Guid cmdId, Guid nodeId, string cmdType, string geometry) + { + CmdId = cmdId; + NodeId = nodeId; + CmdType = cmdType; + Geometry = geometry; + } + } +} diff --git a/src/OpenFTTH.GDBIntegrator.Integrator/Factories/RouteNodeEventFactory.cs b/src/OpenFTTH.GDBIntegrator.Integrator/Factories/RouteNodeEventFactory.cs index 712dc2f..5cb9029 100644 --- a/src/OpenFTTH.GDBIntegrator.Integrator/Factories/RouteNodeEventFactory.cs +++ b/src/OpenFTTH.GDBIntegrator.Integrator/Factories/RouteNodeEventFactory.cs @@ -35,18 +35,22 @@ public async Task CreateUpdatedEvent(RouteNode before, RouteNode if (AlreadyUpdated(after, shadowTableNode)) return new DoNothing($"{nameof(RouteNode)} with id: '{after.Mrid}' was already updated therefore do nothing."); + var shadowTableNodeIntersectingSegments = await _geoDatabase.GetIntersectingRouteSegments(shadowTableNode); + if (shadowTableNodeIntersectingSegments.Count > 0) + return new RollbackInvalidRouteNodeOperation(before); + await _geoDatabase.UpdateRouteNodeShadowTable(after); var intersectingRouteSegments = await _geoDatabase.GetIntersectingRouteSegments(after); - - if (intersectingRouteSegments.Count > 0) + var intersectingRouteNodes = await _geoDatabase.GetIntersectingRouteNodes(after); + if (intersectingRouteSegments.Count > 0 || intersectingRouteNodes.Count > 0) return new RollbackInvalidRouteNodeOperation(before); var cmdId = Guid.NewGuid(); if (after.MarkAsDeleted) return new RouteNodeDeleted { CmdId = cmdId, RouteNode = after }; - return new DoNothing($"{nameof(RouteNode)} with id: '{after.Mrid}' found not suitable action for {nameof(CreateUpdatedEvent)}."); + return new RouteNodeLocationChanged { CmdId = cmdId, RouteNode = after }; } public async Task CreateDigitizedEvent(RouteNode routeNode) diff --git a/src/OpenFTTH.GDBIntegrator.Integrator/Notifications/RouteNodeLocationChanged.cs b/src/OpenFTTH.GDBIntegrator.Integrator/Notifications/RouteNodeLocationChanged.cs new file mode 100644 index 0000000..74f286c --- /dev/null +++ b/src/OpenFTTH.GDBIntegrator.Integrator/Notifications/RouteNodeLocationChanged.cs @@ -0,0 +1,49 @@ +using OpenFTTH.GDBIntegrator.RouteNetwork; +using OpenFTTH.GDBIntegrator.Config; +using OpenFTTH.GDBIntegrator.Producer; +using MediatR; +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace OpenFTTH.GDBIntegrator.Integrator.Notifications +{ + public class RouteNodeLocationChanged : INotification + { + public RouteNode RouteNode { get; set; } + public Guid CmdId { get; set; } + } + + public class RouteNodeLocationChangedHandler : INotificationHandler + { + private readonly ILogger _logger; + private readonly KafkaSetting _kafkaSettings; + private readonly IProducer _producer; + + public RouteNodeLocationChangedHandler( + ILogger logger, + IOptions kafkaSettings, + IProducer producer) + { + _logger = logger; + _kafkaSettings = kafkaSettings.Value; + _producer = producer; + } + + public async Task Handle(RouteNodeLocationChanged request, CancellationToken token) + { + _logger.LogInformation($"Sending {nameof(RouteNodeLocationChanged)} with mrid '{request.RouteNode.Mrid}' to producer"); + + await _producer.Produce(_kafkaSettings.EventRouteNetworkTopicName, + new EventMessages.RouteNodeGeometryModified + ( + request.CmdId, + request.RouteNode.Mrid, + nameof(RouteNodeLocationChanged), + request.RouteNode.GetGeoJsonCoordinate() + )); + } + } +} diff --git a/src/OpenFTTH.GDBIntegrator.Integrator/Notifications/RouteSegmentLocationChanged.cs b/src/OpenFTTH.GDBIntegrator.Integrator/Notifications/RouteSegmentLocationChanged.cs index ac79cf9..0025410 100644 --- a/src/OpenFTTH.GDBIntegrator.Integrator/Notifications/RouteSegmentLocationChanged.cs +++ b/src/OpenFTTH.GDBIntegrator.Integrator/Notifications/RouteSegmentLocationChanged.cs @@ -1,12 +1,10 @@ using OpenFTTH.GDBIntegrator.RouteNetwork; using OpenFTTH.GDBIntegrator.Config; using OpenFTTH.GDBIntegrator.Producer; -using OpenFTTH.GDBIntegrator.Integrator; using MediatR; using System; using System.Threading; using System.Threading.Tasks; -using System.Collections.Generic; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; diff --git a/test/OpenFTTH.GDBIntegrator.Integrator.Tests/EventMessages/RouteNodeGeometryModifiedTest.cs b/test/OpenFTTH.GDBIntegrator.Integrator.Tests/EventMessages/RouteNodeGeometryModifiedTest.cs new file mode 100644 index 0000000..4976f3a --- /dev/null +++ b/test/OpenFTTH.GDBIntegrator.Integrator.Tests/EventMessages/RouteNodeGeometryModifiedTest.cs @@ -0,0 +1,39 @@ +using System; +using Xunit; +using FluentAssertions; +using FluentAssertions.Execution; +using OpenFTTH.GDBIntegrator.Integrator.EventMessages; + +namespace OpenFTTH.GDBIntegrator.Integrator.Tests.EventMessages +{ + public class RouteNodeGeometryModifiedTest + { + [Fact] + public void RouteNodeGeometryModified_ShouldSetInitialValues_OnConstruction() + { + var cmdId = Guid.NewGuid(); + var nodeId = Guid.NewGuid(); + var geometry = "[565931.444690517626197297.75114815]"; + var cmdType = "RouteSegmentLocationChanged"; + + var routeNodeGeometryModified = new RouteNodeGeometryModified + ( + cmdId, + nodeId, + cmdType, + geometry + ); + + using (new AssertionScope()) + { + routeNodeGeometryModified.Geometry.Should().Be(geometry); + routeNodeGeometryModified.EventId.Should().NotBeEmpty(); + routeNodeGeometryModified.NodeId.Should().Be(nodeId); + routeNodeGeometryModified.CmdId.Should().Be(cmdId); + routeNodeGeometryModified.EventType.Should().Be(nameof(RouteSegmentGeometryModified)); + routeNodeGeometryModified.EventTs.Should().NotBeEmpty(); + routeNodeGeometryModified.CmdType.Should().Be(cmdType); + } + } + } +} diff --git a/test/OpenFTTH.GDBIntegrator.Integrator.Tests/Factories/RouteNodeEventFactoryTest.cs b/test/OpenFTTH.GDBIntegrator.Integrator.Tests/Factories/RouteNodeEventFactoryTest.cs index d09b378..38bbcab 100644 --- a/test/OpenFTTH.GDBIntegrator.Integrator.Tests/Factories/RouteNodeEventFactoryTest.cs +++ b/test/OpenFTTH.GDBIntegrator.Integrator.Tests/Factories/RouteNodeEventFactoryTest.cs @@ -175,6 +175,30 @@ public async Task CreateUpdatedEvent_ShouldReturnRollbackInvalidRouteNodeOperati result.Should().BeEquivalentTo(expected); } + [Fact] + public async Task CreateUpdatedEvent_ShouldReturnRollbackInvalidRouteNodeOperation_OnRouteNodeIntersectingWithOtherRouteNodes() + { + var applicationSetting = A.Fake>(); + var geoDatabase = A.Fake(); + var beforeNode = A.Fake(); + var afterNode = A.Fake(); + + A.CallTo(() => afterNode.MarkAsDeleted).Returns(true); + + A.CallTo(() => geoDatabase.GetIntersectingRouteSegments(afterNode)) + .Returns(new List()); + + A.CallTo(() => geoDatabase.GetIntersectingRouteNodes(afterNode)) + .Returns(new List { A.Fake() }); + + var factory = new RouteNodeEventFactory(applicationSetting, geoDatabase); + var result = await factory.CreateUpdatedEvent(beforeNode, afterNode); + + var expected = new RollbackInvalidRouteNodeOperation(beforeNode); + + result.Should().BeEquivalentTo(expected); + } + [Fact] public async Task CreateUpdatedEvent_ShouldReturnDoNothing_OnRouteNodeMarkedAsDeletedAndCoordBeingTheSame() { @@ -264,5 +288,72 @@ public async Task CreateUpdatedEvent_ShouldReturnDoNothing_OnShadowTableRouteNod result.Should().BeOfType(typeof(DoNothing)); } + + [Fact] + public async Task CreateUpdatedEvent_ShouldReturnRollbackRouteNode_OnShadowTableRouteNodeIntersectingWithSegment() + { + var applicationSetting = A.Fake>(); + var geoDatabase = A.Fake(); + var beforeNode = A.Fake(); + var afterNode = A.Fake(); + var shadowTableRouteNode = A.Fake(); + + A.CallTo(() => afterNode.Mrid).Returns(Guid.NewGuid()); + A.CallTo(() => geoDatabase.GetRouteNodeShadowTable(afterNode.Mrid)).Returns(shadowTableRouteNode); + A.CallTo(() => geoDatabase.GetIntersectingRouteSegments(shadowTableRouteNode)) + .Returns(new List { A.Fake() }); + + A.CallTo(() => afterNode.GetGeoJsonCoordinate()) + .Returns("[665931.4446905176,7197297.75114815]"); + A.CallTo(() => afterNode.MarkAsDeleted).Returns(false); + + A.CallTo(() => shadowTableRouteNode.GetGeoJsonCoordinate()) + .Returns("[565931.4446905176,6197297.75114815]"); + A.CallTo(() => shadowTableRouteNode.MarkAsDeleted).Returns(false); + + var factory = new RouteNodeEventFactory(applicationSetting, geoDatabase); + + var result = (RollbackInvalidRouteNodeOperation)(await factory.CreateUpdatedEvent(beforeNode, afterNode)); + + using (var scope = new AssertionScope()) + { + result.Should().BeOfType(typeof(RollbackInvalidRouteNodeOperation)); + result.RollbackToNode.Should().Be(beforeNode); + } + } + + [Fact] + public async Task CreateUpdatedEvent_ShouldReturnRouteNodeLocationChanged_OnRouteNodeChangedWithNoChecksFailing() + { + var applicationSetting = A.Fake>(); + var geoDatabase = A.Fake(); + var beforeNode = A.Fake(); + var afterNode = A.Fake(); + var shadowTableRouteNode = A.Fake(); + + A.CallTo(() => afterNode.Mrid).Returns(Guid.NewGuid()); + A.CallTo(() => geoDatabase.GetRouteNodeShadowTable(afterNode.Mrid)).Returns(shadowTableRouteNode); + A.CallTo(() => geoDatabase.GetIntersectingRouteSegments(shadowTableRouteNode)) + .Returns(new List()); + + A.CallTo(() => afterNode.GetGeoJsonCoordinate()) + .Returns("[665931.4446905176,7197297.75114815]"); + A.CallTo(() => afterNode.MarkAsDeleted).Returns(false); + + A.CallTo(() => shadowTableRouteNode.GetGeoJsonCoordinate()) + .Returns("[565931.4446905176,6197297.75114815]"); + A.CallTo(() => shadowTableRouteNode.MarkAsDeleted).Returns(false); + + var factory = new RouteNodeEventFactory(applicationSetting, geoDatabase); + + var result = (RouteNodeLocationChanged)(await factory.CreateUpdatedEvent(beforeNode, afterNode)); + + using (var scope = new AssertionScope()) + { + result.Should().BeOfType(typeof(RouteNodeLocationChanged)); + result.RouteNode.Should().Be(afterNode); + result.CmdId.Should().NotBeEmpty(); + } + } } }