public async Task <ActionResult <IEnumerable <CustomDiagnostic> > > GetDiagnosticsAsync()
        {
            List <CustomDiagnostic> diagnostics = new List <CustomDiagnostic>();
            var filterParams = new SearchParams()
                               .Where("identifier=UPTValue");

            Bundle result = await _client.SearchAsync <DiagnosticReport>(filterParams);

            while (result != null)
            {
                foreach (var item in result.Entry)
                {
                    var diagnosticReceived = (DiagnosticReport)item.Resource;
                    var customDiagnostic   = new CustomDiagnostic
                    {
                        Id              = diagnosticReceived.Id,
                        PatientRef      = diagnosticReceived.Performer.FirstOrDefault().ToString(),
                        PractitionerRef = diagnosticReceived.Subject.ToString(),
                        IssueDate       = diagnosticReceived.Issued.Value
                    };
                    diagnostics.Add(customDiagnostic);
                }
                result = _client.Continue(result, PageDirection.Next);
            }

            return(Ok(diagnostics));
        }
        public async Task SearchWithCriteria_SyncContinue_SearchReturned()
        {
            var client = new FhirClient(_endpoint)
            {
                PreferredFormat    = ResourceFormat.Json,
                ReturnFullResource = true
            };

            var result1 = await client.SearchAsync <Patient>(new[] { "family=clark" });

            Assert.IsTrue(result1.Entry.Count >= 1);

            while (result1 != null)
            {
                foreach (var e in result1.Entry)
                {
                    Patient p = (Patient)e.Resource;
                    if (p.Name.Any())
                    {
                        Console.WriteLine(
                            $"NAME: {p.Name[0].Given.FirstOrDefault()} {p.Name[0].Family.FirstOrDefault()}");
                    }
                }
                result1 = client.Continue(result1, PageDirection.Next);
            }

            Console.WriteLine("Test Completed");
        }
Exemple #3
0
        /// <summary>
        /// Executes the specified arguments.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns>System.Int32.</returns>
        /// <remarks>N/A</remarks>
        public override int Execute(Arguments arguments)
        {
            // Get us the needed parameters first
            //
            var url  = arguments["url"];
            var text = new [] { "name=" + arguments["text"] };

            // Query FHIR server for a list of matching patient resources
            //
            try
            {
                var client = new FhirClient(url);
                var result = client.SearchAsync("Patient", text).Result;

                if (result.Entries.Count == 0)
                {
                    Console.WriteLine("Server {0} returned not results for search criteria [{1}]", url, text[0]);
                    return(1);
                }

                foreach (var entry in result.Entries)
                {
                    var rid = new ResourceIdentity(entry.Id);
                    Console.WriteLine("Found patient {0} that matches {1} on {2}", rid.Id, text[0], url);
                }
                return(0);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return(1);
            }
        }
        public async Task SearchUsingPostWithCriteria_AsyncContinue_SearchReturned()
        {
            var client = new FhirClient(_endpointSupportingSearchUsingPost)
            {
                PreferredFormat    = ResourceFormat.Json,
                ReturnFullResource = true
            };

            var result1 = await client.SearchAsync <Patient>(new[] { "family=Chalmers" }, null, 1);

            Assert.IsTrue(result1.Entry.Count >= 1);

            while (result1 != null)
            {
                foreach (var e in result1.Entry)
                {
                    Patient p = (Patient)e.Resource;
                    if (p.Name.Any())
                    {
                        Console.WriteLine(
                            $"NAME: {p.Name[0].Given.FirstOrDefault()} {p.Name[0].Family.FirstOrDefault()}");
                    }
                }
                Console.WriteLine("Fetching more results...");
                result1 = await client.ContinueAsync(result1);
            }

            Console.WriteLine("Test Completed");
        }
        public async Task <ActionResult <IEnumerable <CustomPatient> > > GetPatientsAsync()
        {
            List <CustomPatient> patientList = new List <CustomPatient>();
            var filterParams = new SearchParams()
                               .Where("identifier=UPTValue");

            Bundle result = await _client.SearchAsync <Patient>(filterParams);

            while (result != null)
            {
                foreach (var item in result.Entry)
                {
                    var patientRetrieved = (Patient)item.Resource;
                    var customPatient    = new CustomPatient()
                    {
                        Name       = patientRetrieved.Name.FirstOrDefault().Family,
                        FirstNames = patientRetrieved.Name.FirstOrDefault().Given.ToList(),
                        Id         = patientRetrieved.Id
                    };
                    patientList.Add(customPatient);
                }
                result = _client.Continue(result, PageDirection.Next);
            }

            return(Ok(patientList));
        }
Exemple #6
0
        protected virtual async Task <Model.Observation> GetObservationFromServerAsync(Model.Identifier identifier)
        {
            var searchParams = identifier.ToSearchParams();
            var result       = await _client.SearchAsync <Model.Observation>(searchParams).ConfigureAwait(false);

            return(await result.ReadOneFromBundleWithContinuationAsync <Model.Observation>(_client));
        }
        public override async Task <FhirHealthCheckStatus> CheckHealth(CancellationToken token = default)
        {
            try
            {
                while (!token.IsCancellationRequested)
                {
                    SearchParams          search = new SearchParams().SetCount(1);
                    Hl7.Fhir.Model.Bundle result = await _client.SearchAsync <Hl7.Fhir.Model.StructureDefinition>(search);

                    return(await Task.FromResult(new FhirHealthCheckStatus(string.Empty, 200)));
                }

                token.ThrowIfCancellationRequested();
                return(await Task.FromResult(new FhirHealthCheckStatus(token.ToString(), 500)));
            }
            catch (FhirOperationException ex)
            {
                return(await Task.FromResult(new FhirHealthCheckStatus(ex.Message, (int)ex.Status)));
            }
            catch (IdentityModel.Clients.ActiveDirectory.AdalServiceException ex)
            {
                return(await Task.FromResult(new FhirHealthCheckStatus(ex.Message, ex.StatusCode)));
            }
#pragma warning disable CA1031
            catch (Exception ex)
#pragma warning restore CA1031
            {
                return(await Task.FromResult(new FhirHealthCheckStatus(ex.Message, 500)));
            }
        }
        public async Task Search_UsingSearchParams_SearchReturned()
        {
            var client = new FhirClient(_endpoint)
            {
                PreferredFormat    = ResourceFormat.Json,
                ReturnFullResource = true
            };

            var srch = new SearchParams()
                       .Where("name=Daniel")
                       .LimitTo(10)
                       .SummaryOnly()
                       .OrderBy("birthdate",
                                SortOrder.Descending);

            var result1 = await client.SearchAsync <Patient>(srch);

            Assert.IsTrue(result1.Entry.Count >= 1);

            while (result1 != null)
            {
                foreach (var e in result1.Entry)
                {
                    Patient p = (Patient)e.Resource;
                    Console.WriteLine(
                        $"NAME: {p.Name[0].Given.FirstOrDefault()} {p.Name[0].Family.FirstOrDefault()}");
                }
                result1 = client.Continue(result1, PageDirection.Next);
            }

            Console.WriteLine("Test Completed");
        }
Exemple #9
0
        /// <summary>
        /// Get Practitioner by ID
        /// </summary>
        /// <param name="practitionerId"> ID of practitioner to be fetched </param>
        /// <returns> Practitioner </returns>
        public static async Task <Models.Practitioner> GetPractitioner(string practitionerId)
        {
            Models.Practitioner         practitioner     = null;
            Hl7.Fhir.Model.Practitioner fhirPractitioner = null;

            try
            {
                // limit to 1 to avoid huge response Bundle
                var PractitionerQuery = new SearchParams()
                                        .Where("identifier=http://hl7.org/fhir/sid/us-npi|" + practitionerId)
                                        .LimitTo(1);

                Bundle PractitionerResult = await Client.SearchAsync <Hl7.Fhir.Model.Practitioner>(PractitionerQuery);

                if (PractitionerResult.Entry.Count > 0)
                {
                    // Map the FHIR Practitioner object to App's Practitioner object
                    fhirPractitioner = (Hl7.Fhir.Model.Practitioner)PractitionerResult.Entry[0].Resource;
                    PractitionerMapper mapper = new PractitionerMapper();
                    practitioner = mapper.Map(fhirPractitioner);
                }
            }
            catch (FhirOperationException FhirException)
            {
                System.Diagnostics.Debug.WriteLine("Fhir error message: " + FhirException.Message);
            }
            catch (Exception GeneralException)
            {
                System.Diagnostics.Debug.WriteLine("General error message: " + GeneralException.Message);
            }
            return(practitioner);
        }
Exemple #10
0
        /// <summary>
        /// Gets Patient's hemoglobin observations
        /// </summary>
        /// <param name="patientId">Patient resource Id</param>
        /// <returns>List of hemoglobin observations</returns>
        public async Task <List <Observation> > GetHemoglobinObservationsForPatientAsync(string patientId)
        {
            List <Observation> result = new List <Observation>();
            var searchParameters      = new SearchParams();

            searchParameters.Parameters.Add(new Tuple <string, string>("patient", patientId));
            var responsBundle = await _fhirClient.SearchAsync <Observation>(searchParameters).ConfigureAwait(false);

            foreach (var entry in responsBundle.Entry)
            {
                var observation = (Observation)entry.Resource;
                if (observation.Code.Coding.Exists(coding => coding.Code == Hemoglobin.CODE))
                {
                    result.Add(observation);
                }
            }
            return(result);
        }
Exemple #11
0
        public static async Task <IEnumerable <TResource> > SearchWithContinuationAsync <TResource>(this FhirClient fhirClient, SearchParams searchParams)
            where TResource : Resource
        {
            EnsureArg.IsNotNull(fhirClient, nameof(fhirClient));
            EnsureArg.IsNotNull(searchParams, nameof(searchParams));

            var result = await fhirClient.SearchAsync <TResource>(searchParams).ConfigureAwait(false);

            return(await result.ReadFromBundleWithContinuationAsync <TResource>(fhirClient, searchParams.Count).ConfigureAwait(false));
        }
        protected static async Task <TResource> GetResourceByIdentityAsync <TResource>(FhirClient client, Model.Identifier identifier)
            where TResource : Model.Resource, new()
        {
            EnsureArg.IsNotNull(client, nameof(client));
            EnsureArg.IsNotNull(identifier, nameof(identifier));
            var searchParams = identifier.ToSearchParams();
            var result       = await client.SearchAsync <TResource>(searchParams).ConfigureAwait(false);

            return(await result.ReadOneFromBundleWithContinuationAsync <TResource>(client));
        }
        /// <summary>
        /// Get Organization by identifier
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns>Organization</returns>
        public async Task <Organization> SearchByIdentifierAsync(string identifier)
        {
            Organization result = null;
            var          bundle = await _fhirClient.SearchAsync <Organization>(new[] { $"identifier={identifier}" }).ConfigureAwait(false);

            if (bundle.Entry.Any())
            {
                result = (Organization)bundle.Entry.First().Resource;
            }
            return(result);
        }
        public void SearchAsync()
        {
            FhirClient client = new FhirClient(testEndpoint);
            Bundle     result;

            result = client.SearchAsync <DiagnosticReport>().Result;
            Assert.IsNotNull(result);
            Assert.IsTrue(result.Entry.Count() > 10, "Test should use testdata with more than 10 reports");

            result = client.SearchAsync <DiagnosticReport>(pageSize: 10).Result;
            Assert.IsNotNull(result);
            Assert.IsTrue(result.Entry.Count <= 10);

            var withSubject =
                result.Entry.ByResourceType <DiagnosticReport>().FirstOrDefault(dr => dr.Resource.Subject != null);

            Assert.IsNotNull(withSubject, "Test should use testdata with a report with a subject");

            ResourceIdentity ri = new ResourceIdentity(withSubject.Id);

            result = client.SearchByIdAsync <DiagnosticReport>(ri.Id,
                                                               includes: new string[] { "DiagnosticReport.subject" }).Result;
            Assert.IsNotNull(result);

            Assert.AreEqual(2, result.Entry.Count);  // should have subject too

            Assert.IsNotNull(result.Entry.Single(entry => new ResourceIdentity(entry.Id).Collection ==
                                                 typeof(DiagnosticReport).GetCollectionName()));
            Assert.IsNotNull(result.Entry.Single(entry => new ResourceIdentity(entry.Id).Collection ==
                                                 typeof(Patient).GetCollectionName()));

            result = client.SearchAsync <Patient>(new string[] { "name=Everywoman", "name=Eve" }).Result;

            Assert.IsNotNull(result);
            Assert.IsTrue(result.Entry.Count > 0);
        }
        public async Task <GetPatientList.Model> Handle(GetPatientList.Query request, CancellationToken cancellationToken)
        {
            var paramsList = new List <string>();
            var queryNames = new SearchParams();

            if (!string.IsNullOrEmpty(request.FirstName))
            {
                request.FirstName = request.FirstName?.ToLower();
                request.FirstName = request.FirstName?.Trim();

                queryNames.Where($"given={request.FirstName}").SummaryOnly(SummaryType.Text);
                paramsList.Add($"given:contains={request.FirstName}");
                // queryNames.Where($"given={request.FirstName}").SummaryOnly(SummaryType.Count);
                //use this for a execute batch but for Medicaions
            }

            if (!string.IsNullOrEmpty(request.LastName))
            {
                request.LastName = request.LastName?.ToLower();
                request.LastName = request.LastName?.Trim();

                queryNames.Where($"family={request.LastName}").SummaryOnly(SummaryType.Text);
                //var p = queryNames.ToParameters().;
                paramsList.Add($"name:contains={request.LastName}");
            }

            // var trans = new TransactionBuilder(client.Endpoint);
            // trans = trans.Search(q, "MedicationRequest").Search(t, "MedicationStatement");
            // //var result = await _client.SearchAsync<MedicationRequest>(q);
            // var tResult = _client.TransactionAsync(trans.ToBundle());

            // var result =
            //     PatientList
            //     .Where(x =>
            //         x.GivenNames.Select(n=> n.ToLower()).Contains(term) ||
            //         x.LastName.ToLower().Contains(term)
            //     )
            //     .ToList();

            //these shpuld be identical
            // var pats = await client.SearchAsync<Patient>(paramsList.ToArray(), default, 10/*, SummaryType.Text*/);
            var pats = await client.SearchAsync <Patient>(queryNames.LimitTo(10));

            return(new GetPatientList.Model()
            {
                Patients = pats
            });
        }
Exemple #16
0
        private async Task <List <Organization> > GetOrganizationsFromFHIRAsync()
        {
            List <Organization> organizations = new List <Organization>();
            var result = await _client.SearchAsync <Organization>().ConfigureAwait(false);

            while (result != null)
            {
                if (result.Entry != null)
                {
                    foreach (var e in result.Entry)
                    {
                        organizations.Add((Organization)e.Resource);
                    }
                }
                // get the next page of results
                result = _client.Continue(result);
            }
            return(organizations);
        }
Exemple #17
0
        public async virtual Task <List <Patient> > Search(string term = null)
        {
            if (!string.IsNullOrEmpty(term))
            {
                term = term.ToLower();
                term = term.Trim();

                // var trans = new TransactionBuilder(client.Endpoint);
                // trans = trans.Search(q, "MedicationRequest").Search(t, "MedicationStatement");
                // //var result = await _client.SearchAsync<MedicationRequest>(q);
                // var tResult = _client.TransactionAsync(trans.ToBundle());

                // var result =
                //     PatientList
                //     .Where(x =>
                //         x.GivenNames.Select(n=> n.ToLower()).Contains(term) ||
                //         x.LastName.ToLower().Contains(term)
                //     )
                //     .ToList();

                var queryNames = new SearchParams()
                                 .Where($"given={term}")
                                 .Where($"last={term}")
                                 .LimitTo(50);
                var searchCall = await client.SearchAsync <Patient>(queryNames);


                List <Patient> patients = new List <Patient>();
                while (searchCall != null)
                {
                    foreach (var e in searchCall.Entry)
                    {
                        Patient p = (Patient)e.Resource;
                        patients.Add(p);
                    }
                    searchCall = client.Continue(searchCall, PageDirection.Next);
                }
                return(patients);
            }

            return(PatientList);
        }
        /// <summary>
        /// Get patient's medications
        /// </summary>
        /// <param name="patientId">Patient id</param>
        /// <returns>List of medications</returns>
        public async Task <List <Medication> > GetMedicationDataForPatientAsync(string patientId)
        {
            List <Medication> result;

            var searchParameters = new SearchParams();

            searchParameters.Parameters.Add(new Tuple <string, string>("patient", patientId));
            try
            {
                // https://fhir.cerner.com/millennium/r4/medications/medication-request/#example
                var searchResultResponse = await _client.SearchAsync <MedicationRequest>(searchParameters);

                result = searchResultResponse.Entry.AsParallel() // As parallel since we are making network requests
                         .Select(entry =>
                {
                    var medOrders = _client.Read <MedicationRequest>("MedicationRequest/" + entry.Resource.Id);
                    var safeCast  = (medOrders?.Medication as ResourceReference)?.Reference;
                    if (string.IsNullOrWhiteSpace(safeCast))
                    {
                        return(null);
                    }
                    ;
                    return(_client.Read <Medication>(safeCast));
                })
                         .Where(med => med != null).ToList();
            }
            catch (AggregateException ex)
            {
                throw ex.Flatten();
            }
            catch (FhirOperationException)
            {
                // Error 404 - no medication orders
                result = new List <Medication>();
            }
            return(result);
        }
        /// <summary>
        ///
        /// </summary>Get Patients page
        /// <param name="pageSize">Page size (default 10)</param>
        /// <returns>List of Patients</returns>
        public async Task <IEnumerable <Patient> > GetPatientsAsync(int pageSize = 10)
        {
            var result = await _fhirClient.SearchAsync <Patient>(pageSize : pageSize).ConfigureAwait(false);

            return(result.Entry.Select(x => (Patient)x.Resource));
        }
        public void SearchAsync()
        {
            FhirClient client = new FhirClient(testEndpoint);
            Bundle result;

            result = client.SearchAsync<DiagnosticReport>().Result;
            Assert.IsNotNull(result);
            Assert.IsTrue(result.Entry.Count() > 10, "Test should use testdata with more than 10 reports");

            result = client.SearchAsync<DiagnosticReport>(pageSize: 10).Result;
            Assert.IsNotNull(result);
            Assert.IsTrue(result.Entry.Count <= 10);

            var withSubject = 
                result.Entry.ByResourceType<DiagnosticReport>().FirstOrDefault(dr => dr.Resource.Subject != null);
            Assert.IsNotNull(withSubject, "Test should use testdata with a report with a subject");

            ResourceIdentity ri = new ResourceIdentity(withSubject.Id);

            result = client.SearchByIdAsync<DiagnosticReport>(ri.Id, 
                        includes: new string[] { "DiagnosticReport.subject" }).Result;
            Assert.IsNotNull(result);

            Assert.AreEqual(2, result.Entry.Count);  // should have subject too

            Assert.IsNotNull(result.Entry.Single(entry => new ResourceIdentity(entry.Id).Collection ==
                        typeof(DiagnosticReport).GetCollectionName()));
            Assert.IsNotNull(result.Entry.Single(entry => new ResourceIdentity(entry.Id).Collection ==
                        typeof(Patient).GetCollectionName()));

            result = client.SearchAsync<Patient>(new string[] { "name=Everywoman", "name=Eve" }).Result;

            Assert.IsNotNull(result);
            Assert.IsTrue(result.Entry.Count > 0);
        }
Exemple #21
0
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        var port          = config.GetValue <int>("MetricsPort");
        var fetchInterval = TimeSpan.FromSeconds(config.GetValue <int>("FetchIntervalSeconds"));

        using var server = new MetricServer(port: port);
        server.Start();

        log.LogInformation(
            "FHIR Server Prometheus Exporter running on port {port} for {fhirServerUrl}",
            port,
            fhirClient.Endpoint);

        while (!stoppingToken.IsCancellationRequested)
        {
            fhirClient.RequestHeaders.Authorization = await authHeaderProvider.GetAuthHeaderAsync(stoppingToken);

            using (FetchResourceCountDuration.WithLabels(fhirServerName).NewTimer())
            {
                foreach (var customMetric in customMetrics)
                {
                    log.LogInformation("Querying custom metric {name} using {query}", customMetric.Name, customMetric.Query);
                    var resourceTypeAndFilters = customMetric.Query.Split("?");

                    if (resourceTypeAndFilters.Length < 2)
                    {
                        log.LogWarning("Parsing custom metric query string failed. " +
                                       "Should look like: <resourceType>?<name>=<value>&...");
                        continue;
                    }

                    var resourceType = resourceTypeAndFilters[0];
                    var kv           = HttpUtility.ParseQueryString(resourceTypeAndFilters[1]);
                    var paramList    = kv.AllKeys.Select(key => Tuple.Create(key, kv[key]));
                    var sp           = SearchParams.FromUriParamList(paramList);
                    sp.Summary = SummaryType.Count;

                    var result = await fhirClient.SearchAsync(sp, resourceType);

                    if (result.Total.HasValue)
                    {
                        customGauges[customMetric.Name]
                        .WithLabels(resourceType, fhirServerName)
                        .Set(result.Total.Value);
                    }
                    else
                    {
                        log.LogWarning("No 'total' returned for {query}", customMetric.Query);
                    }
                }

                foreach (var resourceType in resourceTypes)
                {
                    await UpdateResourceCountAsync(resourceType);
                }
            }

            await Task.Delay(fetchInterval, stoppingToken);
        }

        await server.StopAsync();
    }