private async Task <List <RouteNetworkEvent> > InsertReplacementRouteSegments(List <RouteSegment> routeSegments) { var routeNetworkEvents = new List <RouteNetworkEvent>(); foreach (var routeSegment in routeSegments) { await _geoDatabase.InsertRouteSegment(routeSegment); var startRouteNode = (await _geoDatabase.GetIntersectingStartRouteNodes(routeSegment)).FirstOrDefault(); var endRouteNode = (await _geoDatabase.GetIntersectingEndRouteNodes(routeSegment)).FirstOrDefault(); var routeSegmentAddedEvent = _routeSegmentEventFactory.CreateAdded(routeSegment, startRouteNode, endRouteNode); routeNetworkEvents.Add(routeSegmentAddedEvent); } return(routeNetworkEvents); }
public async Task Handle(RouteSegmentConnectivityChanged request, CancellationToken token) { _logger.LogInformation($"Starting {nameof(RouteSegmentConnectivityChangedHandler)}"); var startNode = (await _geoDatabase.GetIntersectingStartRouteNodes(request.After)).FirstOrDefault(); var endNode = (await _geoDatabase.GetIntersectingEndRouteNodes(request.After)).FirstOrDefault(); if ((!(startNode is null) && !(endNode is null)) && startNode.Mrid == endNode.Mrid) { _logger.LogWarning($"Reverting RouteSegment with mrid '{request.After.Mrid}', because of both ends intersecting with the same RouteNode with mrid '{startNode.Mrid}'"); await _geoDatabase.UpdateRouteSegment(request.Before); return; } var routeNetworkEvents = new List <RouteNetworkEvent>(); if (startNode is null) { startNode = _routeNodeFactory.Create(request.After.FindStartPoint()); var insertRouteNodeEvent = await InsertRouteNode(startNode); routeNetworkEvents.Add(insertRouteNodeEvent); } else if (_applicationSettings.EnableSegmentEndsAutoSnappingToRouteNode) { var lineString = request.After.GetLineString(); lineString.Coordinates[0] = new Coordinate(startNode.GetPoint().Coordinate); request.After.Coord = lineString.AsBinary(); await _geoDatabase.UpdateRouteSegment(request.After); } if (endNode is null) { endNode = _routeNodeFactory.Create(request.After.FindEndPoint()); var insertRouteNodeEvent = await InsertRouteNode(endNode); routeNetworkEvents.Add(insertRouteNodeEvent); } else if (_applicationSettings.EnableSegmentEndsAutoSnappingToRouteNode) { var lineString = request.After.GetLineString(); lineString.Coordinates[lineString.Coordinates.Count() - 1] = new Coordinate(endNode.GetPoint().Coordinate); request.After.Coord = lineString.AsBinary(); await _geoDatabase.UpdateRouteSegment(request.After); } var(routeSegmentClone, routeSegmentAddedEvent) = await InsertRouteSegmentClone(request.After); routeNetworkEvents.Add(routeSegmentAddedEvent); var routeSegmentMarkedForDeletionEvent = await MarkRouteSegmentForDeletion(request.Before); routeNetworkEvents.Add(routeSegmentMarkedForDeletionEvent); var beforeStartNode = (await _geoDatabase.GetIntersectingStartRouteNodes(request.Before)).FirstOrDefault(); var beforeEndNode = (await _geoDatabase.GetIntersectingEndRouteNodes(request.Before)).FirstOrDefault(); var isBeforeStartNodeDeleteable = await IsRouteNodeDeleteable(beforeStartNode); var isBeforeEndNodeDeletable = await IsRouteNodeDeleteable(beforeEndNode); if (isBeforeStartNodeDeleteable) { var routeNodeMarkedForDeletionEvent = await MarkDeleteRouteNode(beforeStartNode); routeNetworkEvents.Add(routeNodeMarkedForDeletionEvent); } if (isBeforeEndNodeDeletable) { var routeNodeMarkedForDeletionEvent = await MarkDeleteRouteNode(beforeEndNode); routeNetworkEvents.Add(routeNodeMarkedForDeletionEvent); } var cmdId = Guid.NewGuid(); var routeSegmentConnectivityChangedEvent = new RouteNetworkCommand(nameof(RouteSegmentConnectivityChanged), cmdId, routeNetworkEvents.ToArray()); _eventStore.Insert(routeSegmentConnectivityChangedEvent); }
public async Task Handle(RouteNodeLocationChanged request, CancellationToken token) { _logger.LogInformation($"Starting {nameof(RouteNodeLocationChangedHandler)}"); var intersectingSegmentsBeforeChange = (await _geoDatabase.GetIntersectingRouteSegments(request.RouteNodeBefore.Coord)).ToList(); var routeSegmentsToBeUpdated = new List <RouteSegment>(); if (intersectingSegmentsBeforeChange.Count > 0) { var anySegmentIntersectRouteNode = false; foreach (var intersectingSegment in intersectingSegmentsBeforeChange) { var startNode = (await _geoDatabase.GetIntersectingStartRouteNodes(intersectingSegment)).FirstOrDefault(); if (startNode is null) { var lineString = intersectingSegment.GetLineString(); lineString.Coordinates[0] = new Coordinate(request.RouteNodeAfter.GetPoint().Coordinate); intersectingSegment.Coord = lineString.AsBinary(); } else { var lineString = intersectingSegment.GetLineString(); lineString.Coordinates[lineString.Coordinates.Count() - 1] = new Coordinate(request.RouteNodeAfter.GetPoint().Coordinate); intersectingSegment.Coord = lineString.AsBinary(); } anySegmentIntersectRouteNode = (await _geoDatabase.GetAllIntersectingRouteNodesNotIncludingEdges(intersectingSegment.Coord, intersectingSegment.Mrid)).Any(); if (anySegmentIntersectRouteNode) { break; } routeSegmentsToBeUpdated.Add(intersectingSegment); } // Rollback in case of segment intersecting with any route nodes if (anySegmentIntersectRouteNode) { throw new Exception("Route segments intersects with any route nodes"); } } var routeNetworkEvents = new List <RouteNetworkEvent>(); var routeNodeGeometryModifiedEvent = _routeNodeEventFactory.CreateGeometryModified(request.RouteNodeAfter); routeNetworkEvents.Add(routeNodeGeometryModifiedEvent); for (var i = 0; i < routeSegmentsToBeUpdated.Count; i++) { var routeSegmentToBeUpdated = routeSegmentsToBeUpdated[i]; await _geoDatabase.UpdateRouteSegment(routeSegmentToBeUpdated); var routeSegmentGeometryModifiedEvent = _routeSegmentEventFactory.CreateGeometryModified(routeSegmentToBeUpdated, true); routeNetworkEvents.Add(routeSegmentGeometryModifiedEvent); } var cmdId = Guid.NewGuid(); var routeNodeLocationChangedCommand = new RouteNetworkCommand(nameof(RouteNodeLocationChanged), cmdId, routeNetworkEvents.ToArray()); _eventStore.Insert(routeNodeLocationChangedCommand); }
public async Task <IEnumerable <INotification> > CreateUpdatedEvent(RouteSegment before, RouteSegment after) { var routeSegmentShadowTableBeforeUpdate = await _geoDatabase.GetRouteSegmentShadowTable(after.Mrid); if (routeSegmentShadowTableBeforeUpdate is null) { return new List <INotification> { new DoNothing($"{nameof(RouteSegment)} is already deleted, therefore do nothing") } } ; if (AlreadyUpdated(after, routeSegmentShadowTableBeforeUpdate)) { return new List <INotification> { new DoNothing($"{nameof(RouteSegment)} is already updated, therefore do nothing.") } } ; if (!_routeSegmentValidator.LineIsValid(after.GetLineString())) { throw new Exception("Linestring is not valid."); } await _geoDatabase.UpdateRouteSegmentShadowTable(after); if (after.MarkAsDeleted) { return new List <INotification> { CreateRouteSegmentDeleted(after) } } ; var intersectingStartSegments = await _geoDatabase.GetIntersectingStartRouteSegments(after); var intersectingEndSegments = await _geoDatabase.GetIntersectingEndRouteSegments(after); var intersectingStartNodes = await _geoDatabase.GetIntersectingStartRouteNodes(after); var intersectingEndNodes = await _geoDatabase.GetIntersectingEndRouteNodes(after); var allIntersectingRouteNodesNoEdges = await _geoDatabase.GetAllIntersectingRouteNodesNotIncludingEdges(after); if (intersectingStartNodes.Count >= 2 || intersectingEndNodes.Count >= 2) { throw new Exception("Has more than 2 intersecting start or end nodes."); } if (await IsGeometryChanged(intersectingStartNodes.FirstOrDefault(), intersectingEndNodes.FirstOrDefault(), routeSegmentShadowTableBeforeUpdate)) { var events = new List <INotification>(); events.Add(new RouteSegmentLocationChanged { RouteSegment = after }); if (allIntersectingRouteNodesNoEdges.Count > 0) { foreach (var intersectingRouteNode in allIntersectingRouteNodesNoEdges) { var routeSegmentSplitted = CreateExistingRouteSegmentSplitted(null, intersectingRouteNode, false); events.Add(routeSegmentSplitted); } } return(events); } var notifications = new List <INotification>(); notifications.AddRange(HandleExistingRouteSegmentSplitted(intersectingStartSegments.Count, intersectingStartNodes.Count, after.FindStartPoint(), after)); notifications.AddRange(HandleExistingRouteSegmentSplitted(intersectingEndSegments.Count, intersectingEndNodes.Count, after.FindEndPoint(), after)); notifications.Add(new RouteSegmentConnectivityChanged(before, after)); return(notifications); }
public async Task Handle(NewRouteSegmentDigitized request, CancellationToken token) { _logger.LogInformation($"Starting {nameof(NewRouteSegmentDigitizedHandler)}"); if (request.RouteSegment is null) { throw new ArgumentNullException($"{nameof(RouteSegment)} cannot be null."); } var routeSegment = request.RouteSegment; var startNode = (await _geoDatabase.GetIntersectingStartRouteNodes(routeSegment)).FirstOrDefault(); var endNode = (await _geoDatabase.GetIntersectingEndRouteNodes(routeSegment)).FirstOrDefault(); if ((!(startNode is null) && !(endNode is null)) && startNode.Mrid == endNode.Mrid) { _logger.LogWarning($"Deleting RouteSegment with mrid '{routeSegment.Mrid}', because of both ends intersecting with the same RouteNode with mrid '{startNode.Mrid}'"); await _geoDatabase.DeleteRouteSegment(routeSegment.Mrid); return; } var routeNetworkEvents = new List <RouteNetworkEvent>(); if (startNode is null) { var startPoint = routeSegment.FindStartPoint(); startNode = _routeNodeFactory.Create(startPoint); startNode.Username = routeSegment.Username; startNode.WorkTaskMrid = routeSegment.WorkTaskMrid; await _geoDatabase.InsertRouteNode(startNode); var startRouteNodeAddedEvent = _routeNodeEventFactory.CreateAdded(startNode); routeNetworkEvents.Add(startRouteNodeAddedEvent); } else if (_applicationSettings.EnableSegmentEndsAutoSnappingToRouteNode) { var lineString = routeSegment.GetLineString(); lineString.Coordinates[0] = new Coordinate(startNode.GetPoint().Coordinate); routeSegment.Coord = lineString.AsBinary(); await _geoDatabase.UpdateRouteSegment(routeSegment); } if (endNode is null) { var endPoint = routeSegment.FindEndPoint(); endNode = _routeNodeFactory.Create(endPoint); endNode.Username = routeSegment.Username; endNode.WorkTaskMrid = routeSegment.WorkTaskMrid; await _geoDatabase.InsertRouteNode(endNode); var endRouteNodeAddedEvent = _routeNodeEventFactory.CreateAdded(endNode); routeNetworkEvents.Add(endRouteNodeAddedEvent); } else if (_applicationSettings.EnableSegmentEndsAutoSnappingToRouteNode) { var lineString = routeSegment.GetLineString(); lineString.Coordinates[lineString.Coordinates.Count() - 1] = new Coordinate(endNode.GetPoint().Coordinate); routeSegment.Coord = lineString.AsBinary(); await _geoDatabase.UpdateRouteSegment(routeSegment); } var routeSegmentAddedEvent = _routeSegmentEventFactory.CreateAdded(routeSegment, startNode, endNode); routeNetworkEvents.Add(routeSegmentAddedEvent); var cmdId = Guid.NewGuid(); var newRouteSegmentDigitizedCommand = new RouteNetworkCommand(nameof(NewRouteSegmentDigitized), cmdId, routeNetworkEvents.ToArray()); _eventStore.Insert(newRouteSegmentDigitizedCommand); }