public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) { var token = securityToken.Split(';').First().Trim('"'); var tokenSecret = securityToken.Split(';').Last().Trim('"'); var tokenAndSecret = new TokenAndSecret(token, tokenSecret); var userId = string.Empty; // https://www.tabsoverspaces.com/233703-named-locks-using-monitor-in-net-implementation/ // https://stackoverflow.com/questions/55188959/what-are-the-options-for-named-locks-in-net-core lock (string.Intern(tokenAndSecret.ToString())) { userId = _cache.ReverseGet(tokenAndSecret); if (string.IsNullOrEmpty(userId)) { var osmGateway = _clientsFactory.CreateOAuthClient(_options.OsmConfiguration.ConsumerKey, _options.OsmConfiguration.ConsumerSecret, tokenAndSecret.Token, tokenAndSecret.TokenSecret); var user = osmGateway.GetUserDetails().Result; userId = user.Id.ToString(); _logger.LogInformation($"User {userId} had just logged in"); _cache.Add(userId, tokenAndSecret); } } validatedToken = new JwtSecurityToken(); if (string.IsNullOrWhiteSpace(userId)) { throw new ArgumentException("Invalid user id", nameof(securityToken)); } var identity = new ClaimsIdentity("Osm"); identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userId)); identity.AddClaim(new Claim(ClaimTypes.Name, userId)); return(new ClaimsPrincipal(identity)); }
public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) { var token = securityToken.Split(';').First().Trim('"'); var tokenSecret = securityToken.Split(';').Last().Trim('"'); var tokenAndSecret = new TokenAndSecret(token, tokenSecret); var userId = _cache.ReverseGet(tokenAndSecret); if (string.IsNullOrEmpty(userId)) { var osmGateway = _httpGatewayFactory.CreateOsmGateway(tokenAndSecret); var user = osmGateway.GetUser().Result; userId = user.Id.ToString(); _logger.LogInformation("User " + userId + " had just logged in"); _cache.Add(userId, tokenAndSecret); } validatedToken = new JwtSecurityToken(); if (string.IsNullOrWhiteSpace(userId)) { throw new ArgumentException("Invalid user id", nameof(securityToken)); } var identity = new ClaimsIdentity("Osm"); identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userId)); identity.AddClaim(new Claim(ClaimTypes.Name, userId)); return(new ClaimsPrincipal(identity)); }
private IAuthClient CreateOsmGateway(TokenAndSecret tokenAndSecret) { return(_clientsFactory.CreateOAuthClient(_options.OsmConfiguration.ConsumerKey, _options.OsmConfiguration.ConsumerSecret, tokenAndSecret.Token, tokenAndSecret.TokenSecret)); }
public IRemoteFileFetcherGateway CreateRemoteFileFetcherGateway(TokenAndSecret tokenAndSecret) { if (tokenAndSecret == null) { return(new RemoteFileFetcherGateway(_logger)); } return(new OsmGateway(tokenAndSecret, _options, _logger)); }
public OsmGateway(TokenAndSecret tokenAndSecret, IOptions <ConfigurationData> options, ILogger logger) : base(logger) { _tokenAndSecret = tokenAndSecret; _options = options.Value; var osmApiBaseAddress = _options.OsmConfiguraion.BaseAddress.Replace("https", "http") + "/api/0.6/"; _baseAddressWithoutProtocol = _options.OsmConfiguraion.BaseAddress.Replace("http://", "").Replace("https://", ""); _userDetailsAddress = osmApiBaseAddress + "user/details"; _createChangesetAddress = osmApiBaseAddress + "changeset/create"; _closeChangesetAddress = osmApiBaseAddress + "changeset/:id/close"; _createElementAddress = osmApiBaseAddress + ":type/create"; _elementAddress = osmApiBaseAddress + ":type/:id"; _completeElementAddress = osmApiBaseAddress + ":type/:id/full"; _traceAddress = osmApiBaseAddress + "gpx/:id"; _getTracesAddress = osmApiBaseAddress + "user/gpx_files"; _createTraceAddress = osmApiBaseAddress + "gpx/create"; }
/// <inheritdoc /> public async Task <PointOfInterestExtended> UpdatePointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { var osmGateway = _httpGatewayFactory.CreateOsmGateway(tokenAndSecret); var id = pointOfInterest.Id; ICompleteOsmGeo completeOsmGeo; if (pointOfInterest.Type == OsmGeoType.Node.ToString().ToLower()) { completeOsmGeo = await osmGateway.GetNode(id); } else if (pointOfInterest.Type == OsmGeoType.Way.ToString().ToLower()) { completeOsmGeo = await osmGateway.GetCompleteWay(id); } else if (pointOfInterest.Type == OsmGeoType.Relation.ToString().ToLower()) { completeOsmGeo = await osmGateway.GetCompleteRelation(id); } else { throw new ArgumentException(nameof(pointOfInterest.Type) + " is not known: " + pointOfInterest.Type); } var featureBeforeUpdate = ConvertOsmToFeature(completeOsmGeo, pointOfInterest.Title); var oldIcon = featureBeforeUpdate.Attributes[FeatureAttributes.ICON].ToString(); completeOsmGeo.Tags[FeatureAttributes.WEBSITE] = pointOfInterest.Url; SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.NAME, pointOfInterest.Title, language); SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.DESCRIPTION, pointOfInterest.Description, language); SyncImages(completeOsmGeo.Tags, pointOfInterest.ImagesUrls); if (pointOfInterest.Icon != oldIcon) { RemoveTagsByIcon(completeOsmGeo.Tags, oldIcon); AddTagsByIcon(completeOsmGeo.Tags, pointOfInterest.Icon); } RemoveEmptyTags(completeOsmGeo.Tags); var changesetId = await osmGateway.CreateChangeset("Update POI interface from IHM site."); await osmGateway.UpdateElement(changesetId, completeOsmGeo); await osmGateway.CloseChangeset(changesetId); var featureToReturn = await UpdateElasticSearch(completeOsmGeo, pointOfInterest.Title); return(await FeatureToExtendedPoi(featureToReturn, language)); }
/// <inheritdoc /> public async Task <PointOfInterestExtended> AddPointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { var osmGateway = CreateOsmGateway(tokenAndSecret); var changesetId = await osmGateway.CreateChangeset($"Added {pointOfInterest.Title} using IsraelHiking.osm.org.il"); var node = new Node { Latitude = pointOfInterest.Location.Lat, Longitude = pointOfInterest.Location.Lng, Tags = new TagsCollection() }; SetWebsiteUrl(node.Tags, pointOfInterest); SetMultipleValuesForTag(node.Tags, FeatureAttributes.IMAGE_URL, pointOfInterest.ImagesUrls); SetTagByLanguage(node.Tags, FeatureAttributes.NAME, pointOfInterest.Title, language); SetTagByLanguage(node.Tags, FeatureAttributes.DESCRIPTION, pointOfInterest.Description, language); AddTagsByIcon(node.Tags, pointOfInterest.Icon); RemoveEmptyTags(node.Tags); node.Id = await osmGateway.CreateElement(changesetId, node); await osmGateway.CloseChangeset(changesetId); var feature = await UpdateElasticSearch(node, pointOfInterest.Title); return(await FeatureToExtendedPoi(feature, language)); }
/// <inheritdoc /> public async Task <PointOfInterestExtended> UpdatePointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { var osmGateway = CreateOsmGateway(tokenAndSecret); var id = pointOfInterest.Id; ICompleteOsmGeo completeOsmGeo = await osmGateway.GetCompleteElement(GeoJsonExtensions.GetOsmId(id), GeoJsonExtensions.GetOsmType(id)); var featureBeforeUpdate = ConvertOsmToFeature(completeOsmGeo, pointOfInterest.Title); var oldIcon = featureBeforeUpdate.Attributes[FeatureAttributes.POI_ICON].ToString(); var oldTags = completeOsmGeo.Tags.ToArray(); SetWebsiteUrl(completeOsmGeo.Tags, pointOfInterest); SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.NAME, pointOfInterest.Title, language); SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.DESCRIPTION, pointOfInterest.Description, language); SyncImages(completeOsmGeo.Tags, pointOfInterest.ImagesUrls); if (pointOfInterest.Icon != oldIcon && pointOfInterest.Icon != SEARCH_ICON) { RemoveTagsByIcon(completeOsmGeo.Tags, oldIcon); AddTagsByIcon(completeOsmGeo.Tags, pointOfInterest.Icon); } RemoveEmptyTags(completeOsmGeo.Tags); if (AreTagsCollectionEqual(oldTags, completeOsmGeo.Tags.ToArray())) { return(pointOfInterest); } var changesetId = await osmGateway.CreateChangeset($"Updated {pointOfInterest.Title} using IsraelHiking.osm.org.il"); await osmGateway.UpdateElement(changesetId, completeOsmGeo); await osmGateway.CloseChangeset(changesetId); var featureToReturn = await UpdateElasticSearch(completeOsmGeo, pointOfInterest.Title); return(await FeatureToExtendedPoi(featureToReturn, language)); }
/// <inheritdoc/> public async Task Add(LineString line, Dictionary <string, string> tags, TokenAndSecret tokenAndSecret) { _osmGateway = _osmApiClientsFactory.CreateOAuthClient(_options.OsmConfiguration.ConsumerKey, _options.OsmConfiguration.ConsumerSecret, tokenAndSecret.Token, tokenAndSecret.TokenSecret); var createdElements = new List <OsmGeo>(); var modifiedElement = new List <OsmGeo>(); int generatedId = -1; var newWayNodes = new List <Node>(); var highways = await GetHighwaysInArea(line); var itmHighways = highways.Select(ToItmLineString).ToList(); var waysToUpdateIds = new List <long?>(); for (int coordinateIndex = 0; coordinateIndex < line.Coordinates.Length; coordinateIndex++) { var coordinate = line.Coordinates[coordinateIndex]; if (coordinateIndex > 0) { var previousCoordinate = line.Coordinates[coordinateIndex - 1]; AddIntersectingNodes(previousCoordinate, coordinate, newWayNodes, itmHighways, highways); } var closetHighway = GetClosetHighway(coordinate, itmHighways, highways); if (closetHighway == null) { // no close highways, adding a new node var node = new Node { Id = generatedId--, Latitude = coordinate.Y, Longitude = coordinate.X }; createdElements.Add(node); newWayNodes.Add(node); continue; } var itmPoint = GetItmCoordinate(coordinate); var closestItmHighway = itmHighways.First(hw => hw.GetOsmId() == closetHighway.GetOsmId()); var closestItmPointInWay = closestItmHighway.Coordinates.OrderBy(c => c.Distance(itmPoint.Coordinate)).First(); var indexOnWay = closestItmHighway.Coordinates.ToList().IndexOf(closestItmPointInWay); var closestNode = CreateNodeFromExistingHighway(closetHighway, indexOnWay); if (!CanAddNewNode(newWayNodes, closestNode.Id.Value)) { continue; } if (closestItmPointInWay.Distance(itmPoint.Coordinate) <= _options.MaxDistanceToExisitngLineForMerge) { // close highway, adding the node id from that highway newWayNodes.Add(closestNode); continue; } // need to add a new node to existing highway var newNode = new Node { Id = generatedId--, Latitude = coordinate.Y, Longitude = coordinate.X }; createdElements.Add(newNode); newWayNodes.Add(newNode); var indexToInsert = GetIndexToInsert(indexOnWay, closestItmHighway, itmPoint); if (modifiedElement.FirstOrDefault(w => w.Id == closestItmHighway.GetOsmId()) is Way modifiedWay && modifiedWay.Nodes[indexToInsert] < 0) { // a new node was added to this highway - no reason to add a new one to the same location continue; } var simpleWay = await AddNewNodeToExistingWay(newNode.Id.ToString(), closestItmHighway.GetOsmId(), indexToInsert); modifiedElement.Add(simpleWay); waysToUpdateIds.Add(simpleWay.Id); } CloseLoopWithStartPointIfNeeded(newWayNodes); var newWay = CreateWay(newWayNodes, tags, generatedId--); createdElements.Add(newWay); waysToUpdateIds.Add(newWay.Id); var changes = new OsmChange { Create = createdElements.ToArray(), Modify = modifiedElement.ToArray(), Delete = new OsmGeo[0] }; var changesetId = await _osmGateway.CreateChangeset(CreateCommentFromTags(tags)); try { var diffResult = await _osmGateway.UploadChangeset(changesetId, changes); waysToUpdateIds = waysToUpdateIds.Select(id => { var newIdResult = diffResult.Results.FirstOrDefault(r => r.OldId.Equals(id)); return(newIdResult?.NewId ?? id); }).ToList(); await AddWaysToElasticSearch(waysToUpdateIds); } finally { await _osmGateway.CloseChangeset(changesetId); } }
/// <inheritdoc /> public Task <PointOfInterestExtended> UpdatePointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { throw new Exception("OffRoad does not support updating."); }
/// <inheritdoc/> public async Task Add(LineString line, Dictionary <string, string> tags, TokenAndSecret tokenAndSecret) { _osmGateway = _httpGatewayFactory.CreateOsmGateway(tokenAndSecret); var changesetId = await _osmGateway.CreateChangeset(CreateCommentFromTags(tags)); try { var nodeIds = new List <string>(); var highways = await GetHighwaysInArea(line); var itmHighways = highways.Select(ToItmLineString).ToList(); var waysToUpdateIds = new List <string>(); for (int coordinateIndex = 0; coordinateIndex < line.Coordinates.Length; coordinateIndex++) { var coordinate = line.Coordinates[coordinateIndex]; if (coordinateIndex > 0) { var previousCoordinate = line.Coordinates[coordinateIndex - 1]; await AddIntersectingNodes(previousCoordinate, coordinate, nodeIds, itmHighways); } var closestCompleteWay = await GetClosetHighway(coordinate, itmHighways); if (closestCompleteWay == null) { // no close highways, adding a new node nodeIds.Add(await _osmGateway.CreateElement(changesetId, new Node { Id = 0, Latitude = coordinate.Y, Longitude = coordinate.X })); continue; } var itmPoint = GetItmCoordinate(coordinate); var closestItmHighway = itmHighways.First(hw => hw.GetOsmId() == closestCompleteWay.Id.ToString()); var closestItmPointInWay = closestItmHighway.Coordinates.OrderBy(c => c.Distance(itmPoint.Coordinate)).First(); var indexOnWay = closestItmHighway.Coordinates.ToList().IndexOf(closestItmPointInWay); var closestNodeId = closestCompleteWay.Nodes[indexOnWay].Id.ToString(); if (nodeIds.Any() && nodeIds.Last() == closestNodeId) { continue; } if (closestItmPointInWay.Distance(itmPoint.Coordinate) <= _options.DistanceToExisitngLineMergeThreshold) { // close hihgway, adding the node id from that highway nodeIds.Add(closestNodeId); continue; } // need to add a new node to existing highway var newNodeId = await _osmGateway.CreateElement(changesetId, new Node { Id = 0, Latitude = coordinate.Y, Longitude = coordinate.X }); nodeIds.Add(newNodeId); var simpleWay = AddNewNodeToExistingWay(newNodeId, closestCompleteWay, closestItmHighway, indexOnWay, itmPoint); await _osmGateway.UpdateElement(changesetId, simpleWay); waysToUpdateIds.Add(simpleWay.Id.ToString()); } var newWayId = await AddWayToOsm(nodeIds, tags, changesetId); waysToUpdateIds.Add(newWayId); await AddWaysToElasticSearch(waysToUpdateIds); } finally { await _osmGateway.CloseChangeset(changesetId); } }
/// <inheritdoc /> public Task <PointOfInterestExtended> UpdatePointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { // Not supported throw new NotImplementedException(); }
/// <inheritdoc /> public Task <PointOfInterestExtended> AddPointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { throw new Exception("Nakeb does not support adding."); }
protected bool Equals(TokenAndSecret other) { return(string.Equals(Token, other.Token) && string.Equals(TokenSecret, other.TokenSecret)); }
/// <inheritdoc /> public async Task <PointOfInterestExtended> UpdatePointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { var osmGateway = _httpGatewayFactory.CreateOsmGateway(tokenAndSecret); var feature = await _elasticSearchGateway.GetPointOfInterestById(pointOfInterest.Id, Sources.OSM); var id = pointOfInterest.Id; ICompleteOsmGeo completeOsmGeo; if (feature.Geometry is Point) { completeOsmGeo = await osmGateway.GetNode(id); } else if (feature.Geometry is LineString || feature.Geometry is Polygon) { completeOsmGeo = await osmGateway.GetCompleteWay(id); } else { completeOsmGeo = await osmGateway.GetCompleteRelation(id); } SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.NAME, pointOfInterest.Title, language); SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.DESCRIPTION, pointOfInterest.Description, language); completeOsmGeo.Tags[FeatureAttributes.IMAGE_URL] = pointOfInterest.ImageUrl; completeOsmGeo.Tags[FeatureAttributes.WEBSITE] = pointOfInterest.Url; var oldIcon = feature.Attributes[FeatureAttributes.ICON].ToString(); if (pointOfInterest.Icon != oldIcon) { RemoveTagsByIcon(completeOsmGeo.Tags, oldIcon); AddTagsByIcon(completeOsmGeo.Tags, pointOfInterest.Icon); } RemoveEmptyTags(completeOsmGeo.Tags); var changesetId = await osmGateway.CreateChangeset("Update POI interface from IHM site."); await osmGateway.UpdateElement(changesetId, completeOsmGeo); await osmGateway.CloseChangeset(changesetId); var featureToReturn = await UpdateElasticSearch(completeOsmGeo, pointOfInterest.Title); return(await FeatureToExtendedPoi(featureToReturn, language)); }
/// <inheritdoc /> public async Task <PointOfInterestExtended> AddPointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { var osmGateway = _httpGatewayFactory.CreateOsmGateway(tokenAndSecret); var changesetId = await osmGateway.CreateChangeset("Add POI interface from IHM site."); var node = new Node { Latitude = pointOfInterest.Location.lat, Longitude = pointOfInterest.Location.lng, Tags = new TagsCollection { { FeatureAttributes.WEBSITE, pointOfInterest.Url } } }; for (var imageIndex = 0; imageIndex < pointOfInterest.ImagesUrls.Length; imageIndex++) { var imageUrl = pointOfInterest.ImagesUrls[imageIndex]; var tagName = imageIndex == 0 ? FeatureAttributes.IMAGE_URL : FeatureAttributes.IMAGE_URL + imageIndex; node.Tags.Add(tagName, imageUrl); } SetTagByLanguage(node.Tags, FeatureAttributes.NAME, pointOfInterest.Title, language); SetTagByLanguage(node.Tags, FeatureAttributes.DESCRIPTION, pointOfInterest.Description, language); AddTagsByIcon(node.Tags, pointOfInterest.Icon); RemoveEmptyTags(node.Tags); var id = await osmGateway.CreateElement(changesetId, node); node.Id = long.Parse(id); await osmGateway.CloseChangeset(changesetId); var feature = await UpdateElasticSearch(node, pointOfInterest.Title); return(await FeatureToExtendedPoi(feature, language)); }
protected bool Equals(TokenAndSecret other) { return string.Equals(Token, other.Token) && string.Equals(TokenSecret, other.TokenSecret); }
public IOsmGateway CreateOsmGateway(TokenAndSecret tokenAndSecret) { return(new OsmGateway(tokenAndSecret, _options, _logger)); }
/// <inheritdoc /> public Task <PointOfInterestExtended> UpdatePointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { throw new Exception("Wikipedia does not support updating from this site."); }
/// <inheritdoc /> public async Task <PointOfInterestExtended> UpdatePointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { var osmGateway = _httpGatewayFactory.CreateOsmGateway(tokenAndSecret); var id = pointOfInterest.Id; ICompleteOsmGeo completeOsmGeo = await osmGateway.GetElement(id, pointOfInterest.Type); var featureBeforeUpdate = ConvertOsmToFeature(completeOsmGeo, pointOfInterest.Title); var oldIcon = featureBeforeUpdate.Attributes[FeatureAttributes.ICON].ToString(); var oldTags = completeOsmGeo.Tags.ToArray(); SetWebsiteUrl(completeOsmGeo.Tags, pointOfInterest); SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.NAME, pointOfInterest.Title, language); SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.DESCRIPTION, pointOfInterest.Description, language); SyncImages(completeOsmGeo.Tags, pointOfInterest.ImagesUrls); if (pointOfInterest.Icon != oldIcon) { RemoveTagsByIcon(completeOsmGeo.Tags, oldIcon); AddTagsByIcon(completeOsmGeo.Tags, pointOfInterest.Icon); } RemoveEmptyTags(completeOsmGeo.Tags); if (AreTagsCollectionEqual(oldTags, completeOsmGeo.Tags.ToArray())) { var feature = ConvertOsmToFeature(completeOsmGeo, pointOfInterest.Title); return(await FeatureToExtendedPoi(feature, language)); } var changesetId = await osmGateway.CreateChangeset("Update POI interface from IHM site."); await osmGateway.UpdateElement(changesetId, completeOsmGeo); await osmGateway.CloseChangeset(changesetId); var featureToReturn = await UpdateElasticSearch(completeOsmGeo, pointOfInterest.Title); return(await FeatureToExtendedPoi(featureToReturn, language)); }
/// <inheritdoc/> public async Task Add(LineString line, Dictionary <string, string> tags, TokenAndSecret tokenAndSecret) { _osmGateway = _httpGatewayFactory.CreateOsmGateway(tokenAndSecret); var createdElements = new List <OsmGeo>(); var modifiedElement = new List <OsmGeo>(); int generatedId = -1; var nodeIds = new List <string>(); var highways = await GetHighwaysInArea(line); var itmHighways = highways.Select(ToItmLineString).ToList(); var waysToUpdateIds = new List <long?>(); for (int coordinateIndex = 0; coordinateIndex < line.Coordinates.Length; coordinateIndex++) { var coordinate = line.Coordinates[coordinateIndex]; if (coordinateIndex > 0) { var previousCoordinate = line.Coordinates[coordinateIndex - 1]; AddIntersectingNodes(previousCoordinate, coordinate, nodeIds, itmHighways, highways); } var closetHighway = GetClosetHighway(coordinate, itmHighways, highways); if (closetHighway == null) { // no close highways, adding a new node var node = new Node { Id = generatedId--, Latitude = coordinate.Y, Longitude = coordinate.X }; createdElements.Add(node); nodeIds.Add(node.Id.ToString()); continue; } var itmPoint = GetItmCoordinate(coordinate); var closestItmHighway = itmHighways.First(hw => hw.GetOsmId() == closetHighway.GetOsmId()); var closestItmPointInWay = closestItmHighway.Coordinates.OrderBy(c => c.Distance(itmPoint.Coordinate)).First(); var indexOnWay = closestItmHighway.Coordinates.ToList().IndexOf(closestItmPointInWay); var closestNodeId = ((List <object>)closetHighway.Attributes[FeatureAttributes.OSM_NODES])[indexOnWay].ToString(); if (!CanAddNewNode(nodeIds, closestNodeId)) { continue; } if (closestItmPointInWay.Distance(itmPoint.Coordinate) <= _options.MaxDistanceToExisitngLineForMerge) { // close hihgway, adding the node id from that highway nodeIds.Add(closestNodeId); continue; } // need to add a new node to existing highway var newNode = new Node { Id = generatedId--, Latitude = coordinate.Y, Longitude = coordinate.X }; createdElements.Add(newNode); nodeIds.Add(newNode.Id.ToString()); var simpleWay = await AddNewNodeToExistingWay(newNode.Id.ToString(), closestItmHighway, indexOnWay, itmPoint); modifiedElement.Add(simpleWay); waysToUpdateIds.Add(simpleWay.Id); } var newWay = CreateWay(nodeIds, tags, generatedId--); createdElements.Add(newWay); waysToUpdateIds.Add(newWay.Id); var changes = new OsmChange { Create = createdElements.ToArray(), Modify = modifiedElement.ToArray(), Delete = new OsmGeo[0] }; var changesetId = await _osmGateway.CreateChangeset(CreateCommentFromTags(tags)); try { var diffResult = await _osmGateway.UploadChangeset(changesetId, changes); waysToUpdateIds = waysToUpdateIds.Select(id => { var newIdResult = diffResult.Results.FirstOrDefault(r => r.OldId.Equals(id)); return(newIdResult?.NewId ?? id); }).ToList(); await AddWaysToElasticSearch(waysToUpdateIds); } finally { await _osmGateway.CloseChangeset(changesetId); } }