Skip to content

Commit

Permalink
Add support for any SSB classification by providing the known id.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ronny Birkeli committed Mar 20, 2023
1 parent 89a6ab1 commit f98d764
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 22 deletions.
19 changes: 15 additions & 4 deletions src/Altinn.Codelists/SSB/ClassificationCodelistProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Altinn.App.Core.Features;
using Altinn.App.Core.Models;
using Altinn.Codelists.SSB.Models;
using static System.Net.WebRequestMethods;

namespace Altinn.Codelists.SSB;

Expand All @@ -10,16 +11,26 @@ namespace Altinn.Codelists.SSB;
public class ClassificationCodelistProvider : IAppOptionsProvider
{
private readonly IClassificationsClient _classificationsClient;
private readonly Classification _classification;
private readonly int _classificationId;
private readonly Dictionary<string, string> _defaultKeyValuePairs;

/// <summary>
/// Initializes a new instance of the <see cref="ClassificationCodelistProvider"/> class.
/// </summary>
public ClassificationCodelistProvider(string id, Classification classification, IClassificationsClient classificationsClient, Dictionary<string, string>? defaultKeyValuePairs = null)
public ClassificationCodelistProvider(string id, Classification classification, IClassificationsClient classificationsClient, Dictionary<string, string>? defaultKeyValuePairs = null) :
this(id, (int) classification, classificationsClient, defaultKeyValuePairs)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="ClassificationCodelistProvider"/> class.
/// For valid id's please consult the SSB classificaionts api by calling
/// <see href="http://data.ssb.no/api/klass/v1/classifications?size=150&language=en">the classifications index.</see>
/// </summary>
public ClassificationCodelistProvider(string id, int classificationId, IClassificationsClient classificationsClient, Dictionary<string, string>? defaultKeyValuePairs = null)
{
Id = id;
_classification = classification;
_classificationId = classificationId;
_classificationsClient = classificationsClient;
_defaultKeyValuePairs = defaultKeyValuePairs == null ? new Dictionary<string, string>() : defaultKeyValuePairs;
}
Expand All @@ -36,7 +47,7 @@ public async Task<AppOptions> GetAppOptionsAsync(string language, Dictionary<str
DateOnly dateOnly = date == null ? DateOnly.FromDateTime(DateTime.Today) : DateOnly.Parse(date);
string level = mergedKeyValuePairs.GetValueOrDefault("level") ?? string.Empty;

var classificationCode = await _classificationsClient.GetClassificationCodes(_classification, language, dateOnly, level);
var classificationCode = await _classificationsClient.GetClassificationCodes(_classificationId, language, dateOnly, level);

string parentCode = mergedKeyValuePairs.GetValueOrDefault("parentCode") ?? string.Empty;
var appOptions = new AppOptions
Expand Down
7 changes: 3 additions & 4 deletions src/Altinn.Codelists/SSB/Clients/ClassificationsHttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,20 @@ public ClassificationsHttpClient(IOptions<ClassificationSettings> settings, Http
/// <summary>
/// Gets the codes for the specified classification.
/// </summary>
/// <param name="classification">The type of classification to get</param>
/// <param name="classificationId">The id of the classification to get</param>
/// <param name="language">The language code used for the labels. Valid options are nb (norsk bokmål), nn (nynorsk) and en (english)
/// Default if nothing is specified is nb (norsk bokmål).
/// </param>
/// <param name="atDate">The date the classification should be valid</param>
/// <param name="level">The hierarchy level for classifications with multiple levels. Defaults to empty string, ie. all levels.</param>
/// <returns></returns>
public async Task<ClassificationCodes> GetClassificationCodes(Classification classification, string language="nb", DateOnly? atDate = null, string level = "")
public async Task<ClassificationCodes> GetClassificationCodes(int classificationId, string language="nb", DateOnly? atDate = null, string level = "")
{
int classificationNumber = (int)classification;
DateOnly date = atDate ?? DateOnly.FromDateTime(DateTime.Today);
string atDateformatted = date.ToString("yyyy-MM-dd");
string selectLevel = level == string.Empty ? string.Empty : $"&selectLevel={level}";

var response = await _httpClient.GetAsync($"{classificationNumber}/codesAt?date={atDateformatted}&language={language}{selectLevel}");
var response = await _httpClient.GetAsync($"{classificationId}/codesAt?date={atDateformatted}&language={language}{selectLevel}");
var responseJson = await response.Content.ReadAsStringAsync();

var classificationCodes = JsonSerializer.Deserialize<ClassificationCodes>(responseJson);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,25 @@ public static IServiceCollection AddSSBClassifications(this IServiceCollection s
/// <param name="id">The codelist id</param>
/// <param name="classification">The <see cref="Classification"/> to return</param>
/// <param name="defaultKeyValuePairs">Default set of key/value pairs to be used. Will be overriden by matching qyery parameters runtime.</param>
/// <returns></returns>
public static IServiceCollection AddSSBClassificationCodelistProvider(this IServiceCollection services, string id, Classification classification, Dictionary<string, string>? defaultKeyValuePairs = null)
{
services.AddTransient<IAppOptionsProvider>(sp => new ClassificationCodelistProvider(id, classification, sp.GetRequiredService<IClassificationsClient>(), defaultKeyValuePairs));

return services;
}

/// <summary>
/// Adds the specified classification based on the known classification id. If it is an id mapped to the <see cref="Classification"/> enum
/// the correct enum will be set, otherwise Custom will be used as enum value but the id will be sent to the underlying api.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to add to</param>
/// <param name="id">The codelist id</param>
/// <param name="classificationId">The id of the classification to return</param>
/// <param name="defaultKeyValuePairs">Default set of key/value pairs to be used. Will be overriden by matching qyery parameters runtime.</param>
public static IServiceCollection AddSSBClassificationCodelistProvider(this IServiceCollection services, string id, int classificationId, Dictionary<string, string>? defaultKeyValuePairs = null)
{
services.AddTransient<IAppOptionsProvider>(sp => new ClassificationCodelistProvider(id, classificationId, sp.GetRequiredService<IClassificationsClient>(), defaultKeyValuePairs));

return services;
}
}
2 changes: 1 addition & 1 deletion src/Altinn.Codelists/SSB/IClassificationsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ public interface IClassificationsClient
/// <summary>
/// Gets the codes for the specified classification. If no date is specified, the current date is used.
/// </summary>
Task<ClassificationCodes> GetClassificationCodes(Classification classification, string language = "nb", DateOnly? atDate = null, string level = "");
Task<ClassificationCodes> GetClassificationCodes(int classificationId, string language = "nb", DateOnly? atDate = null, string level = "");
}
}
5 changes: 0 additions & 5 deletions test/Altinn.Codelists.Tests/Altinn.Codelists.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<Compile Remove="SSB\Clients\ClassificationsHttpClientTests.cs" />
</ItemGroup>

<ItemGroup>
<None Remove="Kartverket\AdministrativeUnits\Testdata\fylke46_kommuner.json" />
<None Remove="Kartverket\AdministrativeUnits\Testdata\fylker.json" />
Expand All @@ -31,7 +27,6 @@
<EmbeddedResource Include="Kartverket\AdministrativeUnits\Testdata\fylker.json" />
<EmbeddedResource Include="Kartverket\AdministrativeUnits\Testdata\kommuner.json" />
<EmbeddedResource Include="Posten\Testdata\Postnummerregister-ansi.txt" />
<EmbeddedResource Include="SSB\Clients\ClassificationsHttpClientTests.cs" />
<EmbeddedResource Include="SSB\Testdata\baseAmountNationalInsurance.json" />
<EmbeddedResource Include="SSB\Testdata\municipalities.json" />
<EmbeddedResource Include="SSB\Testdata\counties.json" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
using Altinn.Codelists.SSB.Clients;
using Altinn.Codelists.SSB.Models;

namespace Altinn.Codelists.Tests.SSB.Clients;

public class ClassificationsHttpClientTests
{
[Fact(Skip = "Disabled. This actually calls out to the api and is primarily used to test during development.")]
public async Task GetClassificationCodes_MaritalStats_ShouldReturnAllClassificationCodes()
public async Task GetClassificationCodes_ShouldReturnAllClassificationCodes()
{
var options = Options.Create(new ClassificationSettings());
var client = new ClassificationsHttpClient(options, new HttpClient());

var classificationCodes = await client.GetClassificationCodes(Classification.MaritalStatus, "nn", DateOnly.FromDateTime(DateTime.Today));
var classificationCodes = await client.GetClassificationCodes(19, "nn", DateOnly.FromDateTime(DateTime.Today));

classificationCodes.Codes.Should().HaveCountGreaterThan(2);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ public ClassificationsHttpClientMock(IOptions<ClassificationSettings> classifica
_client = new ClassificationsHttpClient(_options, new HttpClient(HttpMessageHandlerMock));
}

public async Task<ClassificationCodes> GetClassificationCodes(Classification classification, string language = "nb", DateOnly? atDate = null, string level = "")
public async Task<ClassificationCodes> GetClassificationCodes(int classificationId, string language = "nb", DateOnly? atDate = null, string level = "")
{
ClassificationCodes classificationCodes = await _client.GetClassificationCodes(classification, language, atDate, level);
ClassificationCodes classificationCodes = await _client.GetClassificationCodes(classificationId, language, atDate, level);

return level == string.Empty
? classificationCodes
Expand Down
16 changes: 14 additions & 2 deletions test/Altinn.Codelists.Tests/SSB/SexCodelistProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

namespace Altinn.Codelists.Tests.SSB;

public class SexStatusCodelistProviderTests
public class SexCodelistProviderTests
{
[Fact]
public async Task GetAppOptionsAsync_ShouldReturnListOfCodes()
public async Task GetAppOptionsAsync_EnumProvided_ShouldReturnListOfCodes()
{
var httpClientMock = new ClassificationsHttpClientMock(Options.Create(new ClassificationSettings()));
IAppOptionsProvider appOptionsProvider = new ClassificationCodelistProvider("sex", Classification.Sex, httpClientMock);
Expand All @@ -19,4 +19,16 @@ public async Task GetAppOptionsAsync_ShouldReturnListOfCodes()
appOptions.Options.Should().HaveCount(2);
appOptions.Options.First(x => x.Value == "2").Label.Should().Be("Kvinne");
}

[Fact]
public async Task GetAppOptionsAsync_IdProvided_ShouldReturnListOfCodes()
{
var httpClientMock = new ClassificationsHttpClientMock(Options.Create(new ClassificationSettings()));
IAppOptionsProvider appOptionsProvider = new ClassificationCodelistProvider("sex", 2, httpClientMock);

var appOptions = await appOptionsProvider.GetAppOptionsAsync("nb", new Dictionary<string, string>());

appOptions.Options.Should().HaveCount(2);
appOptions.Options.First(x => x.Value == "1").Label.Should().Be("Mann");
}
}

0 comments on commit f98d764

Please sign in to comment.