Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,8 @@ node_modules/
.sonarqube/

**/appsettings.Development.json

src/TestApi/*
package.json
package-lock.json

16 changes: 15 additions & 1 deletion Geo.NET.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 18
VisualStudioVersion = 18.3.11520.95 d18.3
VisualStudioVersion = 18.3.11520.95
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{B3BD11A7-1752-49E3-AE50-A65B5FE7B7B2}"
ProjectSection(SolutionItems) = preProject
Expand Down Expand Up @@ -57,6 +57,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Geo.Trimble", "src\Geo.Trim
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Geo.Trimble.Tests", "test\Geo.Trimble.Tests\Geo.Trimble.Tests.csproj", "{B2D5A7F3-6E1C-4B9A-8D2F-3C7E5A1B4D60}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geo.OpenRouteService", "src\Geo.OpenRouteService\Geo.OpenRouteService.csproj", "{A93DD279-64E8-EBD9-8A86-C3009B3477D9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geo.OpenRouteService.Tests", "test\Geo.OpenRouteService.Tests\Geo.OpenRouteService.Tests.csproj", "{F62B53A7-CD72-6BDD-4F81-5E2B2F9A044E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -143,6 +147,14 @@ Global
{B2D5A7F3-6E1C-4B9A-8D2F-3C7E5A1B4D60}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B2D5A7F3-6E1C-4B9A-8D2F-3C7E5A1B4D60}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B2D5A7F3-6E1C-4B9A-8D2F-3C7E5A1B4D60}.Release|Any CPU.Build.0 = Release|Any CPU
{A93DD279-64E8-EBD9-8A86-C3009B3477D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A93DD279-64E8-EBD9-8A86-C3009B3477D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A93DD279-64E8-EBD9-8A86-C3009B3477D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A93DD279-64E8-EBD9-8A86-C3009B3477D9}.Release|Any CPU.Build.0 = Release|Any CPU
{F62B53A7-CD72-6BDD-4F81-5E2B2F9A044E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F62B53A7-CD72-6BDD-4F81-5E2B2F9A044E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F62B53A7-CD72-6BDD-4F81-5E2B2F9A044E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F62B53A7-CD72-6BDD-4F81-5E2B2F9A044E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -168,6 +180,8 @@ Global
{E09BD60D-6E8A-4210-9274-695A2DFFE976} = {67253D97-9FC9-4749-80DC-A5D84339DC05}
{7F4A2E61-83B1-4C2D-9A5E-1D3F8B7C4E90} = {8F3BA9BC-542C-450C-96C9-F0D72FECC930}
{B2D5A7F3-6E1C-4B9A-8D2F-3C7E5A1B4D60} = {67253D97-9FC9-4749-80DC-A5D84339DC05}
{A93DD279-64E8-EBD9-8A86-C3009B3477D9} = {8F3BA9BC-542C-450C-96C9-F0D72FECC930}
{F62B53A7-CD72-6BDD-4F81-5E2B2F9A044E} = {67253D97-9FC9-4749-80DC-A5D84339DC05}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C4B688C4-40EC-4577-9EB2-4CF2412DA0B1}
Expand Down
2 changes: 1 addition & 1 deletion src/Geo.Core/DependencyInjection/BaseBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public BaseBuilder(IHttpClientBuilder httpClientBuilder)
}

/// <summary>
/// Gets the <see cref="IHttpClientBuilder"/> used to configure the HttpClient of the <typeparamref name="T"/> instance.
/// Gets the <see cref="IHttpClientBuilder"/> used to configure the HttpClient instance.
/// </summary>
public IHttpClientBuilder HttpClientBuilder { get; }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// <copyright file="IOpenRouteServiceGeocoding.cs" company="Geo.NET">
// Copyright (c) Geo.NET.
// Licensed under the MIT license. See the LICENSE file in the solution root for full license information.
// </copyright>

namespace Geo.OpenRouteService
{
using System.Threading;
using System.Threading.Tasks;
using Geo.Core.Models.Exceptions;
using Geo.OpenRouteService.Models.Parameters;
using Geo.OpenRouteService.Models.Responses;

/// <summary>
/// An interface for calling the OpenRouteService geocoding API.
/// </summary>
public interface IOpenRouteServiceGeocoding
{
/// <summary>
/// Performs a forward geocoding search, converting a text query to coordinates.
/// </summary>
/// <param name="parameters">A <see cref="SearchParameters"/> with the search parameters.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> used to cancel the request.</param>
/// <returns>A <see cref="FeatureCollection"/> containing the matching results.</returns>
/// <exception cref="GeoNETException">Thrown when the parameters are null or invalid, or the API call fails.</exception>
Task<FeatureCollection> SearchAsync(SearchParameters parameters, CancellationToken cancellationToken = default);

/// <summary>
/// Performs an autocomplete search for type-ahead suggestions.
/// </summary>
/// <param name="parameters">An <see cref="AutocompleteParameters"/> with the autocomplete parameters.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> used to cancel the request.</param>
/// <returns>A <see cref="FeatureCollection"/> containing the suggestions.</returns>
/// <exception cref="GeoNETException">Thrown when the parameters are null or invalid, or the API call fails.</exception>
Task<FeatureCollection> AutocompleteAsync(AutocompleteParameters parameters, CancellationToken cancellationToken = default);

/// <summary>
/// Performs a structured geocoding search using individual address components.
/// </summary>
/// <param name="parameters">A <see cref="StructuredSearchParameters"/> with the address component parameters.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> used to cancel the request.</param>
/// <returns>A <see cref="FeatureCollection"/> containing the matching results.</returns>
/// <exception cref="GeoNETException">Thrown when the parameters are null or invalid, or the API call fails.</exception>
Task<FeatureCollection> StructuredSearchAsync(StructuredSearchParameters parameters, CancellationToken cancellationToken = default);

/// <summary>
/// Performs a reverse geocoding search, converting coordinates to an address.
/// </summary>
/// <param name="parameters">A <see cref="ReverseSearchParameters"/> with the reverse geocoding parameters.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> used to cancel the request.</param>
/// <returns>A <see cref="FeatureCollection"/> containing the matching results.</returns>
/// <exception cref="GeoNETException">Thrown when the parameters are null or invalid, or the API call fails.</exception>
Task<FeatureCollection> ReverseAsync(ReverseSearchParameters parameters, CancellationToken cancellationToken = default);
}
}
98 changes: 98 additions & 0 deletions src/Geo.OpenRouteService/Converters/CoordinateConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// <copyright file="CoordinateConverter.cs" company="Geo.NET">
// Copyright (c) Geo.NET.
// Licensed under the MIT license. See the LICENSE file in the solution root for full license information.
// </copyright>

namespace Geo.OpenRouteService.Converters
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
using Geo.Core.Extensions;
using Geo.OpenRouteService.Models;

/// <summary>
/// Converts a GeoJSON <c>[longitude, latitude]</c> coordinate array to and from a <see cref="Coordinate"/>.
/// </summary>
public class CoordinateConverter : JsonConverter<Coordinate>
{
/// <inheritdoc/>
public override Coordinate Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (typeToConvert == null)
{
throw new ArgumentNullException(nameof(typeToConvert));
}

if (options == null)
{
throw new ArgumentNullException(nameof(options));
}

if (reader.TokenType == JsonTokenType.Null)
{
return null;
}

if (reader.TokenType != JsonTokenType.StartArray)
{
throw new JsonException(string.Format(CultureInfo.InvariantCulture, "Unexpected token while parsing the coordinate. Expected to find an array, instead found {0}", reader.TokenType.GetName()));
}

var values = new List<double>();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
break;
}
else if (reader.TokenType == JsonTokenType.Number)
{
values.Add(reader.GetDouble());
}
else
{
throw new JsonException(string.Format(CultureInfo.InvariantCulture, "Unexpected token while parsing the coordinate. Expected to find a double, instead found '{0}'", reader.GetString()));
}
}

if (values.Count != 2)
{
throw new JsonException(string.Format(CultureInfo.InvariantCulture, "Unexpected end of array while parsing the coordinate. Expected to find 2 doubles, instead found {0}", values.Count));
}

return new Coordinate()
{
Longitude = values[0],
Latitude = values[1],
};
}

/// <inheritdoc/>
public override void Write(Utf8JsonWriter writer, Coordinate value, JsonSerializerOptions options)
{
if (writer == null)
{
throw new ArgumentNullException(nameof(writer));
}

if (options == null)
{
throw new ArgumentNullException(nameof(options));
}

if (value == null)
{
writer.WriteNullValue();
return;
}

writer.WriteStartArray();
writer.WriteNumberValue(value.Longitude);
writer.WriteNumberValue(value.Latitude);
writer.WriteEndArray();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// <copyright file="ServiceCollectionExtensions.cs" company="Geo.NET">
// Copyright (c) Geo.NET.
// Licensed under the MIT license. See the LICENSE file in the solution root for full license information.
// </copyright>

namespace Geo.Extensions.DependencyInjection
{
using System;
using Geo.OpenRouteService;
using Geo.OpenRouteService.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

/// <summary>
/// Extension methods for the <see cref="IServiceCollection"/> class.
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// Adds the OpenRouteService geocoding services to the service collection.
/// <para>
/// Adds the services:
/// <list type="bullet">
/// <item><see cref="IOptions{TOptions}"/> of <see cref="IOpenRouteServiceGeocoding"/></item>
/// <item><see cref="IOpenRouteServiceGeocoding"/></item>
/// </list>
/// </para>
/// </summary>
/// <param name="services">An <see cref="IServiceCollection"/> to add the OpenRouteService services to.</param>
/// <returns>A <see cref="KeyBuilder{T}"/> to configure the OpenRouteService geocoding.</returns>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="services"/> is null.</exception>
public static KeyBuilder<IOpenRouteServiceGeocoding> AddOpenRouteServiceGeocoding(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}

services.AddKeyOptions<IOpenRouteServiceGeocoding>();

return new KeyBuilder<IOpenRouteServiceGeocoding>(services.AddHttpClient<IOpenRouteServiceGeocoding, OpenRouteServiceGeocoding>());
}
}
}
99 changes: 99 additions & 0 deletions src/Geo.OpenRouteService/Enums/LayerType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// <copyright file="LayerType.cs" company="Geo.NET">
// Copyright (c) Geo.NET.
// Licensed under the MIT license. See the LICENSE file in the solution root for full license information.
// </copyright>

namespace Geo.OpenRouteService.Enums
{
using System.Runtime.Serialization;

/// <summary>
/// The layer types available to filter ORS geocoding results.
/// </summary>
public enum LayerType
{
/// <summary>
/// A venue such as a restaurant, shop, or point of interest.
/// </summary>
[EnumMember(Value = "venue")]
Venue = 1,

/// <summary>
/// A specific address.
/// </summary>
[EnumMember(Value = "address")]
Address,

/// <summary>
/// A street.
/// </summary>
[EnumMember(Value = "street")]
Street,

/// <summary>
/// A neighbourhood within a locality.
/// </summary>
[EnumMember(Value = "neighbourhood")]
Neighbourhood,

/// <summary>
/// A borough within a city.
/// </summary>
[EnumMember(Value = "borough")]
Borough,

/// <summary>
/// A local administrative area.
/// </summary>
[EnumMember(Value = "localadmin")]
LocalAdmin,

/// <summary>
/// A city or town.
/// </summary>
[EnumMember(Value = "locality")]
Locality,

/// <summary>
/// A county.
/// </summary>
[EnumMember(Value = "county")]
County,

/// <summary>
/// A macro county (larger grouping of counties).
/// </summary>
[EnumMember(Value = "macrocounty")]
MacroCounty,

/// <summary>
/// A region such as a state or province.
/// </summary>
[EnumMember(Value = "region")]
Region,

/// <summary>
/// A macro region (larger grouping of regions).
/// </summary>
[EnumMember(Value = "macroregion")]
MacroRegion,

/// <summary>
/// A country.
/// </summary>
[EnumMember(Value = "country")]
Country,

/// <summary>
/// A coarse result encompassing multiple administrative levels.
/// </summary>
[EnumMember(Value = "coarse")]
Coarse,

/// <summary>
/// A postal code area.
/// </summary>
[EnumMember(Value = "postalcode")]
PostalCode,
}
}
Loading
Loading