Compare commits

..

No commits in common. "075a803f4fe523356038cc9470a4e9637d20f7d9" and "35c09f0b3e9bfb702c9ecef2c67dd725bcfae988" have entirely different histories.

8 changed files with 110 additions and 144 deletions

View File

@ -2,10 +2,10 @@ namespace Svrnty.GeoManagement.Abstractions.Abstractions;
public interface IAddress public interface IAddress
{ {
public string Line1 { get; set; } public string Line1 { get; }
public string? Line2 { get; set; } public string? Line2 { get; }
public string City { get; set; } public string City { get; }
public string Subdivision { get; set; } public string Subdivision { get; }
public string PostalCode { get; set; } public string PostalCode { get; }
public string Country { get; set; } public string Country { get; }
} }

View File

@ -2,17 +2,60 @@ using Svrnty.GeoManagement.Abstractions.Abstractions;
namespace Svrnty.GeoManagement.Abstractions.Models; namespace Svrnty.GeoManagement.Abstractions.Models;
public record GeoPoint(decimal Latitude, decimal Longitude); public record GeoPoint(double Latitude, double Longitude);
public record Address(bool Normalized = false) : IAddress public record Address(
string Line1,
string? Line2,
string City,
string Subdivision,
string PostalCode,
string Country,
GeoPoint? Location,
string? Note,
bool IsNormalized = false
) : IAddress
{ {
public required string Line1 { get; set; } public string GetFormattedAddress(
public string? Line2 { get; set; } FormattedAddressType formatType = FormattedAddressType.Full
public required string City { get; set; } )
public required string Subdivision { get; set; } {
public required string PostalCode { get; set; } return formatType switch
public required string Country { get; set; } {
public GeoPoint? Location { get; set; } FormattedAddressType.Full => FormatFullOneLine(),
public string? Note { get; set; } FormattedAddressType.Compact => FormatCompactOneLine(),
public bool IsNormalized() => Normalized; FormattedAddressType.MultiLine => FormatMultiLine(),
_ => FormatFullOneLine()
};
}
private string FormatFullOneLine()
{
if (string.IsNullOrWhiteSpace(Line2))
{
return $"{Line1}, {City}, {Subdivision} {PostalCode}, {Country}";
}
return $"{Line2}, {Line1}, {City}, {Subdivision} {PostalCode}, {Country}";
}
private string FormatCompactOneLine()
{
if (string.IsNullOrWhiteSpace(Line2))
{
return $"{Line1}, {City}, {Subdivision}";
}
return $"{Line2}, {Line1}, {City}, {Subdivision}";
}
private string FormatMultiLine()
{
if (string.IsNullOrWhiteSpace(Line2))
{
return $"{Line1}\n{City}, {Subdivision} {PostalCode}\n{Country}";
}
return $"{Line2}, {Line1}\n{City}, {Subdivision} {PostalCode}\n{Country}";
}
} }

View File

@ -1,68 +0,0 @@
using Svrnty.GeoManagement.Abstractions.Abstractions;
using Svrnty.GeoManagement.Abstractions.Models;
namespace Svrnty.GeoManagement.Abstractions;
public static class ServiceCollectionExtensions
{
public static void To(this IAddress address, IAddress toAddress)
{
toAddress.Line1 = address.Line1;
toAddress.Line2 = address.Line2;
toAddress.City = address.City;
toAddress.PostalCode = address.PostalCode;
toAddress.Country = address.Country;
toAddress.Subdivision = address.Subdivision;
}
public static void From(this IAddress address, IAddress fromAddress)
{
address.Line1 = fromAddress.Line1;
address.Line2 = fromAddress.Line2;
address.City = fromAddress.City;
address.PostalCode = fromAddress.PostalCode;
address.Country = fromAddress.Country;
address.Subdivision = fromAddress.Subdivision;
}
public static string GetFormattedAddress(this IAddress address, FormattedAddressType formatType = FormattedAddressType.Full)
{
return formatType switch
{
FormattedAddressType.Full => FormatFullOneLine(address),
FormattedAddressType.Compact => FormatCompactOneLine(address),
FormattedAddressType.MultiLine => FormatMultiLine(address),
_ => FormatFullOneLine(address)
};
}
private static string FormatFullOneLine(IAddress address)
{
if (string.IsNullOrWhiteSpace(address.Line2))
{
return $"{address.Line1}, {address.City}, {address.Subdivision} {address.PostalCode}, {address.Country}";
}
return $"{address.Line2}, {address.Line1}, {address.City}, {address.Subdivision} {address.PostalCode}, {address.Country}";
}
private static string FormatCompactOneLine(IAddress address)
{
if (string.IsNullOrWhiteSpace(address.Line2))
{
return $"{address.Line1}, {address.City}, {address.Subdivision}";
}
return $"{address.Line2}, {address.Line1}, {address.City}, {address.Subdivision}";
}
private static string FormatMultiLine(IAddress address)
{
if (string.IsNullOrWhiteSpace(address.Line2))
{
return $"{address.Line1}\n{address.City}, {address.Subdivision} {address.PostalCode}\n{address.Country}";
}
return $"{address.Line2}, {address.Line1}\n{address.City}, {address.Subdivision} {address.PostalCode}\n{address.Country}";
}
}

View File

@ -3,7 +3,6 @@ using GoogleApi.Entities.Maps.Geocoding.Address.Request;
using GoogleApi.Entities.Maps.Geocoding.Location.Request; using GoogleApi.Entities.Maps.Geocoding.Location.Request;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Svrnty.GeoManagement.Abstractions;
using Svrnty.GeoManagement.Abstractions.Abstractions; using Svrnty.GeoManagement.Abstractions.Abstractions;
using Svrnty.GeoManagement.Abstractions.Models; using Svrnty.GeoManagement.Abstractions.Models;
using Svrnty.GeoManagement.Google.Configuration; using Svrnty.GeoManagement.Google.Configuration;
@ -92,7 +91,7 @@ public class GeoManagementGoogleProvider : IGeoManagementProvider
var request = new LocationGeocodeRequest var request = new LocationGeocodeRequest
{ {
Key = _options.ApiKey, Key = _options.ApiKey,
Location = new GoogleApi.Entities.Common.Coordinate((double)geoPoint.Latitude, (double)geoPoint.Longitude) Location = new GoogleApi.Entities.Common.Coordinate(geoPoint.Latitude, geoPoint.Longitude)
}; };
if (!string.IsNullOrWhiteSpace(_options.Language) && if (!string.IsNullOrWhiteSpace(_options.Language) &&

View File

@ -26,20 +26,20 @@ internal static class GoogleAddressMapper
var country = GetComponentValue(components, "country") ?? string.Empty; var country = GetComponentValue(components, "country") ?? string.Empty;
var location = googleResult.Geometry?.Location != null var location = googleResult.Geometry?.Location != null
? new GeoPoint((decimal)googleResult.Geometry.Location.Latitude, (decimal)googleResult.Geometry.Location.Longitude) ? new GeoPoint(googleResult.Geometry.Location.Latitude, googleResult.Geometry.Location.Longitude)
: null; : null;
return new Abstractions.Models.Address(Normalized: true) return new Abstractions.Models.Address(
{ Line1: line1,
Line1 = line1, Line2: line2,
Line2 = line2, City: city,
City = city, Subdivision: subdivision,
Subdivision = subdivision, PostalCode: postalCode,
PostalCode = postalCode, Country: country,
Country = country, Location: location,
Location = location, Note: null,
Note = null IsNormalized: true
}; );
} }
private static string BuildLine1(IEnumerable<AddressComponent> components) private static string BuildLine1(IEnumerable<AddressComponent> components)
@ -79,8 +79,8 @@ internal static class GoogleAddressMapper
return null; return null;
return new GeoPoint( return new GeoPoint(
(decimal)googleResult.Geometry.Location.Latitude, googleResult.Geometry.Location.Latitude,
(decimal)googleResult.Geometry.Location.Longitude googleResult.Geometry.Location.Longitude
); );
} }
} }

View File

@ -24,12 +24,12 @@ public class AddressTestData
public class GeoPointTestData public class GeoPointTestData
{ {
public decimal Latitude { get; set; } public double Latitude { get; set; }
public decimal Longitude { get; set; } public double Longitude { get; set; }
} }
public class CoordinateRange public class CoordinateRange
{ {
public decimal Min { get; set; } public double Min { get; set; }
public decimal Max { get; set; } public double Max { get; set; }
} }

View File

@ -54,17 +54,15 @@ public class GoogleProviderTests : IDisposable
public async Task GetGeoPointAsync_WithValidAddress_ReturnsCoordinates() public async Task GetGeoPointAsync_WithValidAddress_ReturnsCoordinates()
{ {
// Arrange // Arrange
var address = new Address var address = new Address(
{ Line1: _testData.ValidAddress.Line1,
Line1 = _testData.ValidAddress.Line1, Line2: _testData.ValidAddress.Line2,
Line2 = _testData.ValidAddress.Line2, City: _testData.ValidAddress.City,
City = _testData.ValidAddress.City, Subdivision: _testData.ValidAddress.Subdivision,
Subdivision = _testData.ValidAddress.Subdivision, PostalCode: _testData.ValidAddress.PostalCode,
PostalCode = _testData.ValidAddress.PostalCode, Country: _testData.ValidAddress.Country,
Country = _testData.ValidAddress.Country, Location: null,
Location = null, Note: null);
Note = null
};
// Act // Act
var result = await _provider.GetGeoPointAsync(address); var result = await _provider.GetGeoPointAsync(address);
@ -91,7 +89,7 @@ public class GoogleProviderTests : IDisposable
Assert.NotNull(result.Line1); Assert.NotNull(result.Line1);
Assert.NotNull(result.City); Assert.NotNull(result.City);
Assert.NotNull(result.Country); Assert.NotNull(result.Country);
Assert.True(result.IsNormalized()); Assert.True(result.IsNormalized);
Assert.NotNull(result.Location); Assert.NotNull(result.Location);
} }
@ -99,24 +97,22 @@ public class GoogleProviderTests : IDisposable
public async Task NormalizeAddressAsync_WithAddressObject_ReturnsNormalizedAddress() public async Task NormalizeAddressAsync_WithAddressObject_ReturnsNormalizedAddress()
{ {
// Arrange // Arrange
var address = new Address var address = new Address(
{ Line1: _testData.NormalizeTestAddress.Line1,
Line1 = _testData.NormalizeTestAddress.Line1, Line2: _testData.NormalizeTestAddress.Line2,
Line2 = _testData.NormalizeTestAddress.Line2, City: _testData.NormalizeTestAddress.City,
City = _testData.NormalizeTestAddress.City, Subdivision: _testData.NormalizeTestAddress.Subdivision,
Subdivision = _testData.NormalizeTestAddress.Subdivision, PostalCode: _testData.NormalizeTestAddress.PostalCode,
PostalCode = _testData.NormalizeTestAddress.PostalCode, Country: _testData.NormalizeTestAddress.Country,
Country = _testData.NormalizeTestAddress.Country, Location: null,
Location = null, Note: null);
Note = null
};
// Act // Act
var result = await _provider.NormalizeAddressAsync(address); var result = await _provider.NormalizeAddressAsync(address);
// Assert // Assert
Assert.NotNull(result); Assert.NotNull(result);
Assert.True(result.IsNormalized()); Assert.True(result.IsNormalized);
Assert.NotNull(result.Location); Assert.NotNull(result.Location);
Assert.NotNull(result.Line1); Assert.NotNull(result.Line1);
Assert.Contains("Amphitheatre", result.Line1, StringComparison.OrdinalIgnoreCase); Assert.Contains("Amphitheatre", result.Line1, StringComparison.OrdinalIgnoreCase);
@ -133,7 +129,7 @@ public class GoogleProviderTests : IDisposable
// Assert // Assert
Assert.NotNull(result); Assert.NotNull(result);
Assert.True(result.IsNormalized()); Assert.True(result.IsNormalized);
Assert.NotNull(result.Location); Assert.NotNull(result.Location);
Assert.NotNull(result.Line1); Assert.NotNull(result.Line1);
Assert.Contains("Mountain View", result.City, StringComparison.OrdinalIgnoreCase); Assert.Contains("Mountain View", result.City, StringComparison.OrdinalIgnoreCase);
@ -143,17 +139,15 @@ public class GoogleProviderTests : IDisposable
public async Task GetGeoPointAsync_WithInvalidAddress_ReturnsNull() public async Task GetGeoPointAsync_WithInvalidAddress_ReturnsNull()
{ {
// Arrange // Arrange
var address = new Address var address = new Address(
{ Line1: _testData.InvalidAddress.Line1,
Line1 = _testData.InvalidAddress.Line1, Line2: _testData.InvalidAddress.Line2,
Line2 = _testData.InvalidAddress.Line2, City: _testData.InvalidAddress.City,
City = _testData.InvalidAddress.City, Subdivision: _testData.InvalidAddress.Subdivision,
Subdivision = _testData.InvalidAddress.Subdivision, PostalCode: _testData.InvalidAddress.PostalCode,
PostalCode = _testData.InvalidAddress.PostalCode, Country: _testData.InvalidAddress.Country,
Country = _testData.InvalidAddress.Country, Location: null,
Location = null, Note: null);
Note = null
};
// Act // Act
var result = await _provider.GetGeoPointAsync(address); var result = await _provider.GetGeoPointAsync(address);
@ -178,7 +172,7 @@ public class GoogleProviderTests : IDisposable
// This test just verifies it doesn't crash // This test just verifies it doesn't crash
if (result != null) if (result != null)
{ {
Assert.True(result.IsNormalized()); Assert.True(result.IsNormalized);
} }
} }

View File

@ -1,2 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AResult_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FSourcesCache_003F728eee8ccad23b8fff516dba093eb71b49fb5ee8839f2118392e9747de4ebb_003FResult_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>