in src/Microsoft.Health.Fhir.Core/Features/Operations/Export/ExportJobTask.cs [274:358]
private async Task RunExportSearch(
ExportJobConfiguration exportJobConfiguration,
ExportJobProgress progress,
List<Tuple<string, string>> sharedQueryParametersList,
CancellationToken cancellationToken)
{
EnsureArg.IsNotNull(exportJobConfiguration, nameof(exportJobConfiguration));
EnsureArg.IsNotNull(progress, nameof(progress));
EnsureArg.IsNotNull(sharedQueryParametersList, nameof(sharedQueryParametersList));
List<Tuple<string, string>> queryParametersList = new List<Tuple<string, string>>(sharedQueryParametersList);
if (progress.ContinuationToken != null)
{
queryParametersList.Add(Tuple.Create(KnownQueryParameterNames.ContinuationToken, progress.ContinuationToken));
}
var requestedResourceTypes = _exportJobRecord.ResourceType?.Split(',');
var filteredResources = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (_exportJobRecord.Filters != null)
{
foreach (var filter in _exportJobRecord.Filters)
{
filteredResources.Add(filter.ResourceType);
}
}
IAnonymizer anonymizer = IsAnonymizedExportJob() ? await CreateAnonymizerAsync(cancellationToken) : null;
if (progress.CurrentFilter != null)
{
await ProcessFilter(exportJobConfiguration, progress, queryParametersList, sharedQueryParametersList, anonymizer, "filter", cancellationToken);
}
if (_exportJobRecord.Filters != null && _exportJobRecord.Filters.Any(filter => !progress.CompletedFilters.Contains(filter)))
{
foreach (var filter in _exportJobRecord.Filters)
{
if (!progress.CompletedFilters.Contains(filter) &&
requestedResourceTypes != null &&
requestedResourceTypes.Contains(filter.ResourceType, StringComparison.OrdinalIgnoreCase) &&
(_exportJobRecord.ExportType == ExportJobType.All || filter.ResourceType.Equals(KnownResourceTypes.Patient, StringComparison.OrdinalIgnoreCase)))
{
progress.SetFilter(filter);
await ProcessFilter(exportJobConfiguration, progress, queryParametersList, sharedQueryParametersList, anonymizer, "filter", cancellationToken);
}
}
}
// The unfiltered search should be run if there were no filters specified, there were types requested that didn't have filters for them, or if a Patient/Group level export didn't have filters for Patients.
// Examples:
// If a patient/group export job with type and type filters is run, but patients aren't in the types requested, the search should be run here but no patients printed to the output
// If a patient/group export job with type and type filters is run, and patients are in the types requested and filtered, the search should not be run as patients were searched above
// If an export job with type and type filters is run, the search should not be run if all the types were searched above.
if (_exportJobRecord.Filters == null ||
_exportJobRecord.Filters.Count == 0 ||
(_exportJobRecord.ExportType == ExportJobType.All &&
!requestedResourceTypes.All(resourceType => filteredResources.Contains(resourceType))) ||
((_exportJobRecord.ExportType == ExportJobType.Patient || _exportJobRecord.ExportType == ExportJobType.Group) &&
!filteredResources.Contains(KnownResourceTypes.Patient)))
{
if (_exportJobRecord.ExportType == ExportJobType.Patient)
{
queryParametersList.Add(Tuple.Create(KnownQueryParameterNames.Type, KnownResourceTypes.Patient));
}
else if (_exportJobRecord.ExportType == ExportJobType.All && requestedResourceTypes != null)
{
List<string> resources = new List<string>();
foreach (var resource in requestedResourceTypes)
{
if (!filteredResources.Contains(resource))
{
resources.Add(resource);
}
}
if (resources.Count > 0)
{
queryParametersList.Add(Tuple.Create(KnownQueryParameterNames.Type, resources.JoinByOrSeparator()));
}
}
await SearchWithFilter(exportJobConfiguration, progress, null, queryParametersList, sharedQueryParametersList, anonymizer, string.Empty, cancellationToken);
}
}