Files
vigilcare-clinical/VigilCareClinicalAPI/Fhir/Mapping/FhirReferenceResolver.cs
T

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;
}
}