basic abstraction first commit
This commit is contained in:
commit
6335c8e942
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
/packages/
|
||||||
|
riderModule.iml
|
||||||
|
/_ReSharper.Caches/
|
13
.idea/.idea.Svrnty.GeoManagement/.idea/.gitignore
vendored
Normal file
13
.idea/.idea.Svrnty.GeoManagement/.idea/.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/modules.xml
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/contentModel.xml
|
||||||
|
/.idea.Svrnty.GeoManagement.iml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
4
.idea/.idea.Svrnty.GeoManagement/.idea/encodings.xml
Normal file
4
.idea/.idea.Svrnty.GeoManagement/.idea/encodings.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
8
.idea/.idea.Svrnty.GeoManagement/.idea/indexLayout.xml
Normal file
8
.idea/.idea.Svrnty.GeoManagement/.idea/indexLayout.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/.idea.Svrnty.GeoManagement/.idea/vcs.xml
Normal file
6
.idea/.idea.Svrnty.GeoManagement/.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
58
CLAUDE.md
Normal file
58
CLAUDE.md
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
**Svrnty.GeoManagement** is a .NET 8 library providing abstractions for geocoding and address management services. The solution follows a provider pattern to allow different geocoding service implementations.
|
||||||
|
|
||||||
|
## Solution Structure
|
||||||
|
|
||||||
|
The solution contains two projects:
|
||||||
|
|
||||||
|
- **Svrnty.GeoManagement.Abstractions**: Core abstractions and models for geocoding operations
|
||||||
|
- **Svrnty.GeoManagement.Tests**: xUnit test project
|
||||||
|
|
||||||
|
## Key Architecture Patterns
|
||||||
|
|
||||||
|
### Provider Pattern
|
||||||
|
The library uses the `IGeoManagementProvider` interface to abstract geocoding services. Implementations should provide:
|
||||||
|
- Forward geocoding (address to coordinates)
|
||||||
|
- Reverse geocoding (coordinates to address)
|
||||||
|
- Address normalization
|
||||||
|
|
||||||
|
### Address Model
|
||||||
|
The `Address` record in `Svrnty.GeoManagement.Abstractions/Models/Address.cs` is the central data structure. It:
|
||||||
|
- Implements `IAddress` interface
|
||||||
|
- Includes optional `GeoPoint` location data
|
||||||
|
- Provides formatted address output via `GetFormattedAddress()` method with three format types (Full, Compact, MultiLine)
|
||||||
|
- Has an `IsNormalized` flag to track address validation status
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
|
||||||
|
### Build
|
||||||
|
```bash
|
||||||
|
dotnet build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Tests
|
||||||
|
```bash
|
||||||
|
dotnet test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Specific Test
|
||||||
|
```bash
|
||||||
|
dotnet test --filter "FullyQualifiedName~TestNamespace.TestClass.TestMethod"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restore Dependencies
|
||||||
|
```bash
|
||||||
|
dotnet restore
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Notes
|
||||||
|
|
||||||
|
- Target framework: .NET 8
|
||||||
|
- Nullable reference types are enabled
|
||||||
|
- The Abstractions project is designed to be provider-agnostic - don't add provider-specific dependencies
|
||||||
|
- When implementing `IGeoManagementProvider`, all methods support `CancellationToken` for async operations
|
11
Svrnty.GeoManagement.Abstractions/Abstractions/IAddress.cs
Normal file
11
Svrnty.GeoManagement.Abstractions/Abstractions/IAddress.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace Svrnty.GeoManagement.Abstractions.Abstractions;
|
||||||
|
|
||||||
|
public interface IAddress
|
||||||
|
{
|
||||||
|
public string Line1 { get; }
|
||||||
|
public string? Line2 { get; }
|
||||||
|
public string City { get; }
|
||||||
|
public string Subdivision { get; }
|
||||||
|
public string PostalCode { get; }
|
||||||
|
public string Country { get; }
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
using Svrnty.GeoManagement.Abstractions.Models;
|
||||||
|
|
||||||
|
namespace Svrnty.GeoManagement.Abstractions.Abstractions;
|
||||||
|
|
||||||
|
public interface IGeoManagementProvider
|
||||||
|
{
|
||||||
|
Task<GeoPoint?> GetGeoPointAsync(
|
||||||
|
Address address,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
Task<Address?> ReverseGeocodeAsync(GeoPoint geoPoint,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
Task<Address?> NormalizeAddressAsync(Address address,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
Task<Address?> NormalizeAddressAsync(string address,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
}
|
61
Svrnty.GeoManagement.Abstractions/Models/Address.cs
Normal file
61
Svrnty.GeoManagement.Abstractions/Models/Address.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
using Svrnty.GeoManagement.Abstractions.Abstractions;
|
||||||
|
|
||||||
|
namespace Svrnty.GeoManagement.Abstractions.Models;
|
||||||
|
|
||||||
|
public record GeoPoint(double Latitude, double Longitude);
|
||||||
|
|
||||||
|
public record Address(
|
||||||
|
string Line1,
|
||||||
|
string? Line2,
|
||||||
|
string City,
|
||||||
|
string Subdivision,
|
||||||
|
string PostalCode,
|
||||||
|
string Country,
|
||||||
|
GeoPoint? Location,
|
||||||
|
string? Note,
|
||||||
|
bool IsNormalized = false
|
||||||
|
) : IAddress
|
||||||
|
{
|
||||||
|
public string GetFormattedAddress(
|
||||||
|
FormattedAddressType formatType = FormattedAddressType.Full
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return formatType switch
|
||||||
|
{
|
||||||
|
FormattedAddressType.Full => FormatFullOneLine(),
|
||||||
|
FormattedAddressType.Compact => FormatCompactOneLine(),
|
||||||
|
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}\n{Line1}\n{City}, {Subdivision} {PostalCode}\n{Country}";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
namespace Svrnty.GeoManagement.Abstractions.Models;
|
||||||
|
|
||||||
|
public enum FormattedAddressType
|
||||||
|
{
|
||||||
|
Full,
|
||||||
|
Compact,
|
||||||
|
MultiLine
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
23
Svrnty.GeoManagement.Tests/Svrnty.GeoManagement.Tests.csproj
Normal file
23
Svrnty.GeoManagement.Tests/Svrnty.GeoManagement.Tests.csproj
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
|
||||||
|
<PackageReference Include="xunit" Version="2.5.3"/>
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
22
Svrnty.GeoManagement.sln
Normal file
22
Svrnty.GeoManagement.sln
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Svrnty.GeoManagement.Tests", "Svrnty.GeoManagement.Tests\Svrnty.GeoManagement.Tests.csproj", "{C2DE2776-E457-49B0-A3E2-E31AFE8C922C}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Svrnty.GeoManagement.Abstractions", "Svrnty.GeoManagement.Abstractions\Svrnty.GeoManagement.Abstractions.csproj", "{FB10FC74-7B99-4B3C-A671-6DF451157C98}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C2DE2776-E457-49B0-A3E2-E31AFE8C922C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C2DE2776-E457-49B0-A3E2-E31AFE8C922C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C2DE2776-E457-49B0-A3E2-E31AFE8C922C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C2DE2776-E457-49B0-A3E2-E31AFE8C922C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FB10FC74-7B99-4B3C-A671-6DF451157C98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FB10FC74-7B99-4B3C-A671-6DF451157C98}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FB10FC74-7B99-4B3C-A671-6DF451157C98}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FB10FC74-7B99-4B3C-A671-6DF451157C98}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
Loading…
Reference in New Issue
Block a user