97 lines
3.4 KiB
C#
97 lines
3.4 KiB
C#
using Hl7.Fhir.Model;
|
|
using Microsoft.Extensions.Options;
|
|
using Task = System.Threading.Tasks.Task;
|
|
|
|
public class FhirReferenceResolver
|
|
{
|
|
private readonly IExternalIdentifierService _identifiers;
|
|
private readonly FhirOptions _options;
|
|
|
|
public FhirReferenceResolver(
|
|
IExternalIdentifierService identifiers,
|
|
IOptions<FhirOptions> options)
|
|
{
|
|
_identifiers = identifiers;
|
|
_options = options.Value;
|
|
}
|
|
|
|
public async Task<Guid> ResolvePatientReferenceAsync(ResourceReference reference)
|
|
{
|
|
if (reference.Identifier is not null)
|
|
return await ResolveByIdentifierAsync(
|
|
ExternalResourceType.Patient,
|
|
reference.Identifier.System,
|
|
reference.Identifier.Value,
|
|
_options.PatientIdentifierSystems);
|
|
|
|
if (FhirMappingHelpers.TryParseResourceReference(reference.Reference, out var type, out var id)
|
|
&& type == "Patient"
|
|
&& Guid.TryParse(id, out var guid))
|
|
{
|
|
return guid;
|
|
}
|
|
|
|
throw new FhirMappingException(
|
|
"Patient reference must include a resolvable identifier or UUID.",
|
|
"required");
|
|
}
|
|
|
|
public async Task<Guid> ResolveEncounterReferenceAsync(ResourceReference reference)
|
|
{
|
|
if (reference.Identifier is not null)
|
|
return await ResolveByIdentifierAsync(
|
|
ExternalResourceType.Encounter,
|
|
reference.Identifier.System,
|
|
reference.Identifier.Value,
|
|
_options.EncounterIdentifierSystems);
|
|
|
|
if (FhirMappingHelpers.TryParseResourceReference(reference.Reference, out var type, out var id)
|
|
&& type == "Encounter"
|
|
&& Guid.TryParse(id, out var guid))
|
|
{
|
|
return guid;
|
|
}
|
|
|
|
throw new FhirMappingException(
|
|
"Encounter reference must include a resolvable identifier or UUID.",
|
|
"required");
|
|
}
|
|
|
|
public (string System, string Value)? ExtractPrimaryIdentifier(
|
|
IIdentifiable<List<Identifier>> resource, string[] acceptedSystems)
|
|
{
|
|
foreach (var system in acceptedSystems)
|
|
{
|
|
var match = resource.Identifier?
|
|
.FirstOrDefault(i => i.System == system && !string.IsNullOrWhiteSpace(i.Value));
|
|
if (match is not null)
|
|
return (match.System!, match.Value!);
|
|
}
|
|
|
|
return resource.Identifier?
|
|
.FirstOrDefault(i => !string.IsNullOrWhiteSpace(i.System) && !string.IsNullOrWhiteSpace(i.Value))
|
|
is { } fallback
|
|
? (fallback.System!, fallback.Value!)
|
|
: null;
|
|
}
|
|
|
|
private async Task<Guid> ResolveByIdentifierAsync(
|
|
ExternalResourceType type, string? system, string? value, string[] acceptedSystems)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(system) || string.IsNullOrWhiteSpace(value))
|
|
throw new FhirMappingException("Identifier system and value are required.", "required");
|
|
|
|
if (!acceptedSystems.Contains(system))
|
|
throw new FhirMappingException(
|
|
$"Identifier system '{system}' is not configured.", "not-supported");
|
|
|
|
var internalId = await _identifiers.ResolveInternalIdAsync(type, system, value);
|
|
if (internalId is null)
|
|
throw new NotFoundException(
|
|
$"{type} with identifier {system}|{value} not found.",
|
|
"FHIR_RESOURCE_NOT_FOUND");
|
|
|
|
return internalId.Value;
|
|
}
|
|
}
|