예제 #1
0
        /// <summary>
        /// Generate the FHIR Operation Parameter Resource for the HI Service operation call
        /// </summary>
        /// <returns></returns>
        private Parameters GenerateRequestParametersResource()
        {
            var ParametersResource = new Parameters();

            ParametersResource.Parameter = new List <Parameters.ParameterComponent>();

            var UserParam = new Parameters.ParameterComponent();

            UserParam.Name  = "UserId";
            UserParam.Value = new FhirString("UserABC");
            ParametersResource.Parameter.Add(UserParam);

            var UserIdQualifierParam = new Parameters.ParameterComponent();

            UserIdQualifierParam.Name  = "UserIdQualifier";
            UserIdQualifierParam.Value = new FhirUri("http://ns.yourcompany.com.au/id/yoursoftware/userid/1.0");
            ParametersResource.Parameter.Add(UserIdQualifierParam);

            var ReturnAuditEventParam = new Parameters.ParameterComponent();

            ReturnAuditEventParam.Name  = "ReturnAuditEvent";
            ReturnAuditEventParam.Value = new FhirBoolean(true);
            ParametersResource.Parameter.Add(ReturnAuditEventParam);

            var RequestPatientParam = new Parameters.ParameterComponent();

            RequestPatientParam.Name     = "RequestPatient";
            RequestPatientParam.Resource = GetRequestPatientResource();
            ParametersResource.Parameter.Add(RequestPatientParam);
            return(ParametersResource);
        }
예제 #2
0
        /// <summary>
        /// Deserialize JSON into a FHIR Parameters#Parameter
        /// </summary>
        public static void DeserializeJson(this Parameters.ParameterComponent current, ref Utf8JsonReader reader, JsonSerializerOptions options)
        {
            string propertyName;

            while (reader.Read())
            {
                if (reader.TokenType == JsonTokenType.EndObject)
                {
                    return;
                }

                if (reader.TokenType == JsonTokenType.PropertyName)
                {
                    propertyName = reader.GetString();
                    if (Hl7.Fhir.Serialization.FhirSerializerOptions.Debug)
                    {
                        Console.WriteLine($"Parameters.ParameterComponent >>> Parameters#Parameter.{propertyName}, depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}");
                    }
                    reader.Read();
                    current.DeserializeJsonProperty(ref reader, options, propertyName);
                }
            }

            throw new JsonException($"Parameters.ParameterComponent: invalid state! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}");
        }
예제 #3
0
        private string paramValueToString(Parameters.ParameterComponent parameter)
        {
            if (parameter.Value != null)
            {
                switch (parameter.Value)
                {
                case Identifier id:
                    return(id.ToToken());

                case Coding coding:
                    return(coding.ToToken());

                case ContactPoint contactPoint:
                    return(contactPoint.ToToken());

                case CodeableConcept codeableConcept:
                    return(codeableConcept.ToToken());

                default:
                    if (ModelInfo.IsPrimitive(parameter.Value.GetType()))
                    {
                        return(parameter.Value.ToString());
                    }
                    break;
                }
            }
            throw Error.InvalidOperation($"Parameter '{parameter.Name}' has a non-primitive type, which is not allowed.");
        }
예제 #4
0
        public static bool TryGetBooleanValue(this Parameters parameters, string name, out bool booleanValue)
        {
            Parameters.ParameterComponent param = parameters?.GetSingle(name);

            if (param == null)
            {
                booleanValue = false;
                return(false);
            }

            return(param.TryGetBooleanValue(out booleanValue));
        }
        private bool SetSearchParameterServerIndex(string Id)
        {
            string     ResourceName = ResourceType.SearchParameter.GetLiteral();
            Parameters Parameters   = new Parameters();

            Parameters.Parameter = new List <Parameters.ParameterComponent>();
            var ParameterComponent = new Parameters.ParameterComponent();

            Parameters.Parameter.Add(ParameterComponent);
            ParameterComponent.Name = $"{ResourceName}";
            var          Ref             = new ResourceReference();
            IRequestMeta RequestMetaTemp = IRequestMetaFactory.CreateRequestMeta().Set($"{ResourceName}/{Id}");

            Ref.Reference            = $"{RequestMetaTemp.PyroRequestUri.FhirRequestUri.OriginalString}";
            ParameterComponent.Value = Ref;
            string       OperationName = FhirOperationEnum.OperationType.ServerIndexesSet.GetPyroLiteral();
            IRequestMeta RequestMeta   = IRequestMetaFactory.CreateRequestMeta().Set("");

            try
            {
                IFhirBaseOperationService FhirBaseOperationService = IFhirBaseOperationServiceFactory.CreateFhirBaseOperationService();
                IResourceServiceOutcome   ResourceServiceOutcome   = IServerSearchParameterOperation.ProcessSet(RequestMeta.PyroRequestUri, RequestMeta.SearchParameterGeneric, Parameters, true);
                if (ResourceServiceOutcome.HttpStatusCode == System.Net.HttpStatusCode.OK)
                {
                    return(true);
                }
                else
                {
                    string OperationOutcomeMessage = string.Empty;
                    if (ResourceServiceOutcome.ResourceResult != null && ResourceServiceOutcome.ResourceResult is OperationOutcome OptOut)
                    {
                        OptOut.Issue.ForEach(x => OperationOutcomeMessage = OperationOutcomeMessage + " " + x.Details.Text);
                        string Message = $"Internal Server Error: Failed to Set SearchParameter Server index calling operation ${OperationName} with the SearchParmeter Resource {RequestMetaTemp.PyroRequestUri.FhirRequestUri.OriginalString} with extra detail: {OperationOutcomeMessage}";
                        ILog.Error(Message);
                        throw new Exception(Message);
                    }
                    else
                    {
                        string Message = $"Internal Server Error: Failed to Set SearchParameter Server index calling operation ${OperationName} with the SearchParmeter Resource {RequestMetaTemp.PyroRequestUri.FhirRequestUri.OriginalString}";
                        ILog.Error(Message);
                        throw new Exception(Message);
                    }
                }
            }
            catch (Exception Exec)
            {
                string Message = $"{Exec.Message},  Internal Server Error: Failed to Set SearchParameter Server index calling operation ${OperationName}";
                ILog.Error(Exec, Message);
                throw new Exception(Message);
            }
        }
        public async Task GivenANewSearchParam_WhenReindexingComplete_ThenResourcesSearchedWithNewParamReturned()
        {
            var patientName = Guid.NewGuid().ToString().ComputeHash().Substring(28).ToLower();
            var patient     = new Patient {
                Name = new List <HumanName> {
                    new HumanName {
                        Family = patientName
                    }
                }
            };
            var searchParam = Samples.GetJsonSample <SearchParameter>("SearchParameter");

            // POST a new patient
            FhirResponse <Patient> expectedPatient = await Client.CreateAsync(patient);

            // POST a second patient to show it is filtered and not returned when using the new search parameter
            await Client.CreateAsync(Samples.GetJsonSample <Patient>("Patient"));

            // POST a new Search parameter
            await Client.CreateAsync(searchParam);

            Uri reindexJobUri;

            try
            {
                // Start a reindex job
                (_, reindexJobUri) = await Client.PostReindexJobAsync(new Parameters());
            }
            catch (FhirException ex) when(ex.StatusCode == HttpStatusCode.BadRequest && ex.Message.Contains("not enabled"))
            {
                Skip.If(!_fixture.IsUsingInProcTestServer, "Reindex is not enabled on this server.");
                return;
            }

            await WaitForReindexStatus(reindexJobUri, "Running", "Completed");

            FhirResponse <Parameters> reindexJobResult = await Client.CheckReindexAsync(reindexJobUri);

            Parameters.ParameterComponent param = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == "searchParams");

            Assert.Contains("http://hl7.org/fhir/SearchParameter/Patient-foo", param.Value.ToString());

            await WaitForReindexStatus(reindexJobUri, "Completed");

            // When job complete, search for resources using new parameter
            await ExecuteAndValidateBundle($"Patient?foo:exact={patientName}", expectedPatient.Resource);
        }
        public async Task DocumentOperationPOSTReturn200OnSuccess()
        {
            // Setup Composition resource
            var composition   = CreateTestCompositionNoReferences();
            var compositionId = "test";
            var searchResult  = new SearchResult(new List <IResource>()
            {
                composition
            }, 1, 1);

            _searchMock.Setup(repo => repo.Search(
                                  It.Is <IArgumentCollection>(args => args.GetArgument(ArgumentNames.resourceId).ArgumentValue == compositionId),
                                  It.IsAny <SearchOptions>())).ReturnsAsync(searchResult);

            // Create VonkContext for $document (POST / Type level)
            var testContext = new VonkTestContext(VonkInteraction.instance_custom);

            testContext.Arguments.AddArguments(new[]
            {
                new Argument(ArgumentSource.Path, ArgumentNames.resourceType, "Composition")
            });
            testContext.TestRequest.CustomOperation = "document";
            testContext.TestRequest.Method          = "POST";

            var parameters         = new Parameters();
            var idValue            = new FhirUri(compositionId);
            var parameterComponent = new Parameters.ParameterComponent {
                Name = "id"
            };

            parameterComponent.Value = idValue;
            parameters.Parameter.Add(parameterComponent);

            testContext.TestRequest.Payload = new RequestPayload(true, parameters.ToIResource());

            // Execute $document
            await _documentService.DocumentTypePOST(testContext);

            // Check response status
            testContext.Response.HttpResult.Should().Be(StatusCodes.Status200OK, "$document should succeed with HTTP 200 - OK on test composition");
            testContext.Response.Payload.Should().NotBeNull();
            var bundleType = testContext.Response.Payload.SelectText("type");

            bundleType.Should().Be("document", "Bundle.type should be set to 'document'");
        }
예제 #8
0
        public FHIRTerminologyServer(string endpoint)
        {
            Endpoint = endpoint;
            client   = new FhirClient(endpoint);

            valuesetIdParameter = new Parameters.ParameterComponent {
                Name = "identifier"
            };
            filterParameter = new Parameters.ParameterComponent {
                Name = "filter"
            };
            countParameter = new Parameters.ParameterComponent {
                Name = "limit"
            };
            systemParameter = new Parameters.ParameterComponent {
                Name = "system"
            };
            codeParameter = new Parameters.ParameterComponent {
                Name = "code"
            };

            //Parameters.ParameterComponent limit = new Parameters.ParameterComponent();
        }
예제 #9
0
        public async Task GivenANewSearchParam_WhenReindexingComplete_ThenResourcesSearchedWithNewParamReturned()
        {
            var patientName = Guid.NewGuid().ToString().ComputeHash().Substring(28).ToLower();
            var patient     = new Patient {
                Name = new List <HumanName> {
                    new HumanName {
                        Family = patientName
                    }
                }
            };
            var searchParam = Samples.GetJsonSample <SearchParameter>("SearchParameter");

            searchParam.Code = "fooCode";

            // POST a new patient
            FhirResponse <Patient> expectedPatient = await Client.CreateAsync(patient);

            // POST a second patient to show it is filtered and not returned when using the new search parameter
            await Client.CreateAsync(Samples.GetJsonSample <Patient>("Patient"));

            // POST a new Search parameter
            FhirResponse <SearchParameter> searchParamPosted = null;

            try
            {
                searchParamPosted = await Client.CreateAsync(searchParam);
            }
            catch (Exception ex)
            {
                _output.WriteLine("We encountered an error creating SearchParameter, the next step is to delete and re-add.");
                _output.WriteLine(ex.Message);

                // if the SearchParameter exists, we should delete it and recreate it
                var searchParamBundle = await Client.SearchAsync(ResourceType.SearchParameter, $"url={searchParam.Url}");

                if (searchParamBundle.Resource?.Entry[0] != null && searchParamBundle.Resource?.Entry[0].Resource.ResourceType == ResourceType.SearchParameter)
                {
                    await DeleteSearchParameterAndVerify(searchParamBundle.Resource?.Entry[0].Resource as SearchParameter);

                    searchParamPosted = await Client.CreateAsync(searchParam);
                }
                else
                {
                    throw;
                }
            }

            Uri reindexJobUri;

            try
            {
                // Start a reindex job
                (_, reindexJobUri) = await Client.PostReindexJobAsync(new Parameters());
            }
            catch (FhirException ex) when(ex.StatusCode == HttpStatusCode.BadRequest && ex.Message.Contains("not enabled"))
            {
                Skip.If(!_fixture.IsUsingInProcTestServer, "Reindex is not enabled on this server.");
                return;
            }

            await WaitForReindexStatus(reindexJobUri, "Running", "Completed");

            FhirResponse <Parameters> reindexJobResult = await Client.CheckReindexAsync(reindexJobUri);

            Parameters.ParameterComponent param = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == "searchParams");

            Assert.Contains("http://hl7.org/fhir/SearchParameter/Patient-foo", param.Value.ToString());

            reindexJobResult = await WaitForReindexStatus(reindexJobUri, "Completed");

            _output.WriteLine("Reindex job is completed, it should have reindexed the Patient resources with foo");

            var floatParse = float.TryParse(
                reindexJobResult.Resource.Parameter.FirstOrDefault(predicate => predicate.Name == "resourcesSuccessfullyReindexed").Value.ToString(),
                out float resourcesReindexed);

            _output.WriteLine($"Reindex job is completed, {resourcesReindexed} Patient ressources Reindexed");

            Assert.True(floatParse);
            Assert.True(resourcesReindexed > 0.0);

            // When job complete, search for resources using new parameter
            await ExecuteAndValidateBundle($"Patient?{searchParam.Code}:exact={patientName}", expectedPatient.Resource);

            // Clean up new SearchParameter
            await DeleteSearchParameterAndVerify(searchParamPosted.Resource);
        }
예제 #10
0
        public static bool TryGetUriValue(this Parameters.ParameterComponent paramComponent, out Uri uriValue)
        {
            Element uriElement = paramComponent?.Value;

            return(Uri.TryCreate(uriElement?.ToString(), UriKind.RelativeOrAbsolute, out uriValue));
        }
예제 #11
0
        public IResourceServiceOutcome Process(
            IPyroRequestUri RequestUri,
            ISearchParameterGeneric SearchParameterGeneric,
            Resource Resource)
        {
            IResourceServiceOutcome ResourceServiceOutcome = IResourceServiceOutcomeFactory.CreateResourceServiceOutcome();
            var IssueList = new List <OperationOutcome.IssueComponent>();

            ISearchParameterService         SearchService = ISearchParameterServiceFactory.CreateSearchParameterService();
            ISearchParametersServiceOutcome SearchParametersServiceOutcome = SearchService.ProcessBaseSearchParameters(SearchParameterGeneric);

            if (SearchParametersServiceOutcome.FhirOperationOutcome != null)
            {
                ResourceServiceOutcome.ResourceResult = SearchParametersServiceOutcome.FhirOperationOutcome;
                ResourceServiceOutcome.HttpStatusCode = SearchParametersServiceOutcome.HttpStatusCode;
                ResourceServiceOutcome.FormatMimeType = SearchParametersServiceOutcome.SearchParameters.Format;
                return(ResourceServiceOutcome);
            }

            if (Resource is Parameters Parameters)
            {
                if (Parameters.Parameter != null && Parameters.Parameter.Count > 0)
                {
                    if (Parameters.Parameter[0].Name.ToLower() == _ParameterName)
                    {
                        if (Parameters.Parameter[0].Resource != null)
                        {
                            if (Parameters.Parameter[0].Resource is QuestionnaireResponse QuestionnaireResponse)
                            {
                                if (QuestionnaireResponse.Meta == null)
                                {
                                    QuestionnaireResponse.Meta = new Meta();
                                }
                                if (QuestionnaireResponse.Meta.Tag == null)
                                {
                                    QuestionnaireResponse.Meta.Tag = new List <Coding>();
                                }
                                QuestionnaireResponse.Meta.Tag.Add(new Coding("https://pyrohealth.net/fhir/CodeSystem/connectathon-answer", "hidden"));

                                if (QuestionnaireResponse.Id == null || string.IsNullOrWhiteSpace(QuestionnaireResponse.Id))
                                {
                                    IRequestMeta RequestMeta = IRequestMetaFactory.CreateRequestMeta().Set($"{FHIRAllTypes.QuestionnaireResponse.GetLiteral()}");
                                    ResourceServiceOutcome = this.IResourceServices.Post(QuestionnaireResponse, RequestMeta);
                                }
                                else
                                {
                                    IRequestMeta RequestMeta = IRequestMetaFactory.CreateRequestMeta().Set($"{FHIRAllTypes.QuestionnaireResponse.GetLiteral()}/{QuestionnaireResponse.Id}");
                                    ResourceServiceOutcome = this.IResourceServices.Put(QuestionnaireResponse.Id, QuestionnaireResponse, RequestMeta);
                                }
                                if (ResourceServiceOutcome.SuccessfulTransaction)
                                {
                                    Parameters ParametersResult = new Parameters();
                                    ParametersResult.Parameter = new List <Parameters.ParameterComponent>();
                                    var Param = new Parameters.ParameterComponent();
                                    Param.Name = "You answers have been submitted.";
                                    ParametersResult.Parameter.Add(Param);
                                    var Param2 = new Parameters.ParameterComponent();
                                    Param2.Name     = FHIRAllTypes.QuestionnaireResponse.GetLiteral();
                                    Param2.Resource = ResourceServiceOutcome.ResourceResult;
                                    ParametersResult.Parameter.Add(Param2);
                                    ResourceServiceOutcome.HttpStatusCode        = System.Net.HttpStatusCode.OK;
                                    ResourceServiceOutcome.ResourceResult        = ParametersResult;
                                    ResourceServiceOutcome.OperationType         = Enum.RestEnum.CrudOperationType.Update;
                                    ResourceServiceOutcome.SuccessfulTransaction = true;

                                    IRequestMeta RequestMeta = IRequestMetaFactory.CreateRequestMeta().Set($"{FHIRAllTypes.QuestionnaireResponse.GetLiteral()}/{_PrimaryQuestionnaireResponseAnswerResourceId}");
                                    var          Answers     = this.IResourceServices.GetRead("AngusA1", RequestMeta);

                                    QuestionnaireResults QuestionnaireResults = QuestionnaireResponseChecker.Check(Answers.ResourceResult as QuestionnaireResponse, QuestionnaireResponse);
                                }
                                else
                                {
                                    Parameters ParametersResult = new Parameters();
                                    ParametersResult.Parameter = new List <Parameters.ParameterComponent>();
                                    var Param = new Parameters.ParameterComponent();
                                    Param.Name = "Oh no, there was an error is submitting your answers.";
                                    ParametersResult.Parameter.Add(Param);
                                    var Param2 = new Parameters.ParameterComponent();
                                    Param2.Name     = FHIRAllTypes.OperationOutcome.GetLiteral();
                                    Param2.Resource = ResourceServiceOutcome.ResourceResult;
                                    ParametersResult.Parameter.Add(Param2);
                                    ResourceServiceOutcome.HttpStatusCode        = System.Net.HttpStatusCode.BadRequest;
                                    ResourceServiceOutcome.ResourceResult        = ParametersResult;
                                    ResourceServiceOutcome.OperationType         = Enum.RestEnum.CrudOperationType.Update;
                                    ResourceServiceOutcome.SuccessfulTransaction = false;
                                }
                            }
                            else
                            {
                                IssueList.Add(Pyro.Common.Tools.FhirOperationOutcomeSupport.CreateIssue(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Invalid, $"The ${_OperationName} expects the {FHIRAllTypes.Parameters.GetLiteral()} resource to have one parameter with the 'Name' element equal to '{_ParameterName}' where the Resource element is set to a {FHIRAllTypes.QuestionnaireResponse.GetLiteral()} FHIR Resource. The server found here a Resource of type {Parameters.Parameter[0].Resource.ResourceType}."));
                            }
                        }
                        else
                        {
                            IssueList.Add(Pyro.Common.Tools.FhirOperationOutcomeSupport.CreateIssue(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Invalid, $"The ${_OperationName} expects the {FHIRAllTypes.Parameters.GetLiteral()} resource to have one Parameter with the Name element equal to '{_ParameterName}' where the Resource element is set to a {FHIRAllTypes.QuestionnaireResponse.GetLiteral()} FHIR Resource. The server found no {FHIRAllTypes.QuestionnaireResponse.GetLiteral()} Resource"));
                        }
                    }
                    else
                    {
                        IssueList.Add(Pyro.Common.Tools.FhirOperationOutcomeSupport.CreateIssue(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Invalid, $"The ${_OperationName} expects the {FHIRAllTypes.Parameters.GetLiteral()} resource to have one Parameter with the Name element equal to '{_ParameterName}'."));
                    }
                }
                else
                {
                    IssueList.Add(Pyro.Common.Tools.FhirOperationOutcomeSupport.CreateIssue(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Invalid, $"The ${_OperationName} expects the {FHIRAllTypes.Parameters.GetLiteral()} resource to have one Parameter element."));
                }
            }
            else
            {
                IssueList.Add(Pyro.Common.Tools.FhirOperationOutcomeSupport.CreateIssue(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Invalid, $"The ${_OperationName} expects a FHIR {FHIRAllTypes.Parameters.GetLiteral()} resource as the call body."));
            }

            if (IssueList.Count > 0)
            {
                var Op = Common.Tools.FhirOperationOutcomeSupport.Generate(IssueList);
                ResourceServiceOutcome.HttpStatusCode        = System.Net.HttpStatusCode.BadRequest;
                ResourceServiceOutcome.ResourceResult        = Op;
                ResourceServiceOutcome.OperationType         = Enum.RestEnum.CrudOperationType.Update;
                ResourceServiceOutcome.SuccessfulTransaction = false;
                return(ResourceServiceOutcome);
            }
            else
            {
                return(ResourceServiceOutcome);
            }
        }
예제 #12
0
        public static bool TryGetStringValue(this Parameters.ParameterComponent paramComponent, out string stringValue)
        {
            stringValue = paramComponent?.Value?.ToString();

            return(stringValue != null);
        }
예제 #13
0
        public static bool TryGetBooleanValue(this Parameters.ParameterComponent paramComponent, out bool boolValue)
        {
            Element booleanElement = paramComponent?.Value;

            return(bool.TryParse(booleanElement?.ToString(), out boolValue));
        }
        public IResourceServiceOutcome Process(ISearchParameterGeneric SearchParameterGeneric)
        {
            if (SearchParameterGeneric == null)
            {
                throw new NullReferenceException("SearchParameterGeneric cannot be null.");
            }
            if (IResourceServices == null)
            {
                throw new NullReferenceException("ResourceServices cannot be null.");
            }

            try
            {
                IResourceServiceOutcome ResourceServiceOutcome = IResourceServiceOutcomeFactory.CreateResourceServiceOutcome();

                ISearchParameterService         SearchService = ISearchParameterServiceFactory.CreateSearchParameterService();
                ISearchParametersServiceOutcome SearchParametersServiceOutcome = SearchService.ProcessBaseSearchParameters(SearchParameterGeneric);
                if (SearchParametersServiceOutcome.FhirOperationOutcome != null)
                {
                    ResourceServiceOutcome.ResourceResult = SearchParametersServiceOutcome.FhirOperationOutcome;
                    ResourceServiceOutcome.HttpStatusCode = SearchParametersServiceOutcome.HttpStatusCode;
                    ResourceServiceOutcome.FormatMimeType = SearchParametersServiceOutcome.SearchParameters.Format;
                    return(ResourceServiceOutcome);
                }

                var ReturnParametersResource = new Parameters();
                ReturnParametersResource.Parameter = new List <Parameters.ParameterComponent>();
                foreach (string ResourceName in ModelInfo.SupportedResources)
                {
                    var ResourceReportParameter = new Parameters.ParameterComponent();
                    ResourceReportParameter.Name = ResourceName;
                    ResourceReportParameter.Part = new List <Parameters.ParameterComponent>();
                    ReturnParametersResource.Parameter.Add(ResourceReportParameter);

                    ResourceType CurrentResourceType = Pyro.Common.Tools.ResourceNameResolutionSupport.GetResourceType(ResourceName);
                    int          TotalCount          = IResourceServices.GetTotalCurrentResourceCount(CurrentResourceType);

                    var TotalCountParameter = new Parameters.ParameterComponent();
                    TotalCountParameter.Name  = $"TotalCount";
                    TotalCountParameter.Value = new FhirDecimal(TotalCount);
                    ResourceReportParameter.Part.Add(TotalCountParameter);

                    if (TotalCount > 0)
                    {
                        DateTimeOffset?LastUpdated = IResourceServices.GetLastCurrentResourceLastUpdatedValue(CurrentResourceType);
                        if (LastUpdated.HasValue)
                        {
                            var LastUpdatedParameter = new Parameters.ParameterComponent();
                            LastUpdatedParameter.Name  = $"LastUpdated";
                            LastUpdatedParameter.Value = new FhirDateTime(LastUpdated.Value);
                            ResourceReportParameter.Part.Add(LastUpdatedParameter);
                        }
                    }
                }

                ResourceServiceOutcome.HttpStatusCode        = System.Net.HttpStatusCode.OK;
                ResourceServiceOutcome.ResourceResult        = ReturnParametersResource;
                ResourceServiceOutcome.OperationType         = Enum.RestEnum.CrudOperationType.Update;
                ResourceServiceOutcome.SuccessfulTransaction = true;
                return(ResourceServiceOutcome);
            }

            catch (Exception Exec)
            {
                throw new Exception("ServerResourceReport exception thrown", Exec);
            }
        }
예제 #15
0
        public static bool TryGetUriValue(this Parameters parameters, string name, out Uri uriValue)
        {
            Parameters.ParameterComponent param = parameters.GetSingle(name);

            return(param.TryGetUriValue(out uriValue));
        }
예제 #16
0
        public async Task GivenANewSearchParam_WhenReindexingComplete_ThenResourcesSearchedWithNewParamReturned()
        {
            var randomName  = Guid.NewGuid().ToString().ComputeHash().Substring(0, 14).ToLower();
            var searchParam = Samples.GetJsonSample <SearchParameter>("SearchParameter-AppointmentStatus");

            searchParam.Name = randomName;
            searchParam.Url  = searchParam.Url.Replace("foo", randomName);
            searchParam.Code = randomName + "Code";

            // POST a new appointment
            var appointment = Samples.GetJsonSample <Appointment>("Appointment");

            appointment.Status = Appointment.AppointmentStatus.Noshow;
            var tag = new Coding(null, randomName);

            appointment.Meta = new Meta();
            appointment.Meta.Tag.Add(tag);
            FhirResponse <Appointment> expectedAppointment = await Client.CreateAsync(appointment);

            // POST a second appointment to show it is filtered and not returned when using the new search parameter
            var appointment2 = Samples.GetJsonSample <Appointment>("Appointment");

            appointment2.Status = Appointment.AppointmentStatus.Booked;
            appointment2.Meta   = new Meta();
            appointment2.Meta.Tag.Add(tag);
            await Client.CreateAsync(appointment2);

            // POST a new Search parameter
            FhirResponse <SearchParameter> searchParamPosted = null;

            try
            {
                searchParamPosted = await Client.CreateAsync(searchParam);

                _output.WriteLine($"SearchParameter is posted {searchParam.Url}");

                Uri reindexJobUri;

                // Start a reindex job
                (_, reindexJobUri) = await Client.PostReindexJobAsync(new Parameters());

                await WaitForReindexStatus(reindexJobUri, "Running", "Completed");

                FhirResponse <Parameters> reindexJobResult = await Client.CheckReindexAsync(reindexJobUri);

                Parameters.ParameterComponent param = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == "searchParams");
                _output.WriteLine("ReindexJobDocument:");
                var serializer = new FhirJsonSerializer();
                _output.WriteLine(serializer.SerializeToString(reindexJobResult.Resource));

                Assert.Contains(searchParamPosted.Resource.Url, param.Value.ToString());

                reindexJobResult = await WaitForReindexStatus(reindexJobUri, "Completed");

                _output.WriteLine($"Reindex job is completed, it should have reindexed the resources with {randomName}");

                var floatParse = float.TryParse(
                    reindexJobResult.Resource.Parameter.FirstOrDefault(predicate => predicate.Name == "resourcesSuccessfullyReindexed").Value.ToString(),
                    out float resourcesReindexed);

                _output.WriteLine($"Reindex job is completed, {resourcesReindexed} resources Reindexed");

                Assert.True(floatParse);
                Assert.True(resourcesReindexed > 0.0);

                // When job complete, search for resources using new parameter
                // When there are multiple instances of the fhir-server running, it could take some time
                // for the search parameter/reindex updates to propogate to all instances. Hence we are
                // adding some retries below to account for that delay.
                int  retryCount = 0;
                bool success    = true;
                do
                {
                    success = true;
                    retryCount++;
                    try
                    {
                        await ExecuteAndValidateBundle(
                            $"Appointment?{searchParam.Code}={Appointment.AppointmentStatus.Noshow.ToString().ToLower()}&_tag={tag.Code}",
                            expectedAppointment.Resource);
                    }
                    catch (Exception ex)
                    {
                        _output.WriteLine($"Failed to validate bundle: {ex}");
                        success = false;
                        await Task.Delay(10000);
                    }
                }while (!success && retryCount < 3);

                Assert.True(success);
            }
            catch (FhirException ex) when(ex.StatusCode == HttpStatusCode.BadRequest && ex.Message.Contains("not enabled"))
            {
                Skip.If(!_fixture.IsUsingInProcTestServer, "Reindex is not enabled on this server.");
                return;
            }
            catch (Exception e)
            {
                _output.WriteLine($"Exception: {e.Message}");
                _output.WriteLine($"Stack Trace: {e.StackTrace}");
                throw;
            }
            finally
            {
                // Clean up new SearchParameter
                await DeleteSearchParameterAndVerify(searchParamPosted?.Resource);
            }
        }
예제 #17
0
        public static Parameters AddPatchParameter(this Parameters parameters, string operationType, string path = "", string name = "", Base value = null)
        {
            var component = new Parameters.ParameterComponent
            {
                Name = "operation",
                Part = new List <Parameters.ParameterComponent>
                {
                    new Parameters.ParameterComponent
                    {
                        Name  = "type",
                        Value = new FhirString(operationType),
                    },
                },
            };

            if (!string.IsNullOrEmpty(path))
            {
                component.Part.Add(
                    new Parameters.ParameterComponent
                {
                    Name  = "path",
                    Value = new FhirString(path),
                });
            }

            if (!string.IsNullOrEmpty(name))
            {
                component.Part.Add(
                    new Parameters.ParameterComponent
                {
                    Name  = "name",
                    Value = new FhirString(name),
                });
            }

            if (value is not null)
            {
                if (value is DataType valueDataType)
                {
                    component.Part.Add(
                        new Parameters.ParameterComponent
                    {
                        Name  = "value",
                        Value = valueDataType,
                    });
                }
                else if (value is Parameters.ParameterComponent valueParameter)
                {
                    component.Part.Add(
                        new Parameters.ParameterComponent
                    {
                        Name = "value",
                        Part = new List <Parameters.ParameterComponent> {
                            valueParameter
                        },
                    });
                }
                else
                {
                    throw new ArgumentOutOfRangeException($"Value must be of type {typeof(DataType)} or {typeof(Parameters.ParameterComponent)}.");
                }
            }

            parameters.Parameter.Add(component);
            return(parameters);
        }
        public async Task GivenASearchParameterWithMultipleBaseResourceTypes_WhenTargetingReindexJobToResourceType_ThenOnlyTargetedTypesAreReindexed()
        {
            var randomName  = Guid.NewGuid().ToString().ComputeHash().Substring(0, 14).ToLower();
            var searchParam = Samples.GetJsonSample <SearchParameter>("SearchParameter-Resource-idfoo");

            searchParam.Name = searchParam.Name.Replace("foo", randomName);
            searchParam.Url  = searchParam.Url.Replace("foo", randomName);
            searchParam.Code = randomName + "Code";

            // POST a new appointment
            var appointment = Samples.GetJsonSample <Appointment>("Appointment");
            FhirResponse <Appointment> expectedAppointment = await Client.CreateAsync(appointment);

            // POST a second appointment to show it is filtered and not returned when using the new search parameter
            var appointment2 = Samples.GetJsonSample <Appointment>("Appointment");
            await Client.CreateAsync(appointment2);

            // POST a new patient
            var patient = new Patient {
                Name = new List <HumanName> {
                    new HumanName {
                        Family = randomName
                    }
                }
            };
            FhirResponse <Patient> expectedPatient = await Client.CreateAsync(patient);

            // POST a new Search parameter
            FhirResponse <SearchParameter> searchParamPosted = null;

            try
            {
                searchParamPosted = await Client.CreateAsync(searchParam);

                _output.WriteLine($"SearchParameter is posted {searchParam.Url}");

                Uri reindexJobUri;

                // Start a reindex job
                var reindexParameters = new Parameters();
                reindexParameters.Add("targetResourceTypes", new FhirString("Appointment"));
                (_, reindexJobUri) = await Client.PostReindexJobAsync(reindexParameters);

                await WaitForReindexStatus(reindexJobUri, "Completed");

                FhirResponse <Parameters> reindexJobResult = await Client.CheckReindexAsync(reindexJobUri);

                Parameters.ParameterComponent searchParamListParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == "searchParams");
                Parameters.ParameterComponent targetResourcesParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.TargetResourceTypes);
                Parameters.ParameterComponent resourcesParam       = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.Resources);

                // output reindex job for debugging
                _output.WriteLine("ReindexJobDocument:");
                var serializer = new FhirJsonSerializer();
                _output.WriteLine(serializer.SerializeToString(reindexJobResult.Resource));

                Assert.Contains(searchParamPosted.Resource.Url, searchParamListParam.Value.ToString());
                Assert.Equal("Appointment", targetResourcesParam.Value.ToString());
                Assert.Equal("Appointment", resourcesParam.Value.ToString());

                _output.WriteLine($"Reindex job is completed, it should have reindexed the resources of type Appointment only.");

                var floatParse = float.TryParse(
                    reindexJobResult.Resource.Parameter.FirstOrDefault(predicate => predicate.Name == "resourcesSuccessfullyReindexed").Value.ToString(),
                    out float resourcesReindexed);

                _output.WriteLine($"Reindex job is completed, {resourcesReindexed} resources Reindexed");

                Assert.True(floatParse);
                Assert.True(resourcesReindexed > 0.0);

                // When job complete, search for resources using new parameter
                // When there are multiple instances of the fhir-server running, it could take some time
                // for the search parameter/reindex updates to propogate to all instances. Hence we are
                // adding some retries below to account for that delay.
                int  retryCount = 0;
                bool success    = true;
                do
                {
                    success = true;
                    retryCount++;
                    try
                    {
                        await ExecuteAndValidateBundle(
                            $"Appointment?{searchParam.Code}={expectedAppointment.Resource.Id}",
                            Tuple.Create("x-ms-use-partial-indices", "true"),
                            expectedAppointment.Resource);
                    }
                    catch (Exception ex)
                    {
                        _output.WriteLine($"Failed to validate bundle: {ex}");
                        success = false;
                        await Task.Delay(10000);
                    }

                    // now searching for patient with same search parameter should not work
                    var    searchUrl = $"Patient?{searchParam.Code}={expectedPatient.Resource.Id}";
                    Bundle bundle    = await Client.SearchAsync(searchUrl, Tuple.Create("x-ms-use-partial-indices", "true"));

                    Assert.Empty(bundle.Entry);

                    // finally searching with new SearchParam but without partial header should not use
                    // new search parameter, because it should not be marked fully reindexed
                    searchUrl = $"Patient?{searchParam.Code}={expectedPatient.Resource.Id}";
                    bundle    = await Client.SearchAsync(searchUrl);

                    Assert.DoesNotContain(searchParam.Code, bundle.SelfLink.ToString());
                }while (!success && retryCount < 10);

                Assert.True(success);
            }
            catch (FhirException ex) when(ex.StatusCode == HttpStatusCode.BadRequest && ex.Message.Contains("not enabled"))
            {
                Skip.If(!_fixture.IsUsingInProcTestServer, "Reindex is not enabled on this server.");
                return;
            }
            catch (Exception e)
            {
                _output.WriteLine($"Exception: {e.Message}");
                _output.WriteLine($"Stack Trace: {e.StackTrace}");
                throw;
            }
            finally
            {
                // Clean up new SearchParameter
                await DeleteSearchParameterAndVerify(searchParamPosted?.Resource);
            }
        }
예제 #19
0
        public async Task GivenASearchParam_WhenUpdatingParam_ThenResourcesIndexedWithUpdatedParam()
        {
            var randomName = Guid.NewGuid().ToString().ComputeHash().Substring(28).ToLower();
            var patient    = new Patient {
                Name = new List <HumanName> {
                    new HumanName {
                        Family = randomName
                    }
                }
            };
            var searchParam = Samples.GetJsonSample <SearchParameter>("SearchParameter");

            searchParam.Name = randomName;
            searchParam.Url  = searchParam.Url.Replace("foo", randomName);
            searchParam.Code = randomName;
            searchParam.Id   = randomName;

            // POST a new patient
            FhirResponse <Patient> expectedPatient = await Client.CreateAsync(patient);

            // POST a new Search parameter
            FhirResponse <SearchParameter> searchParamPosted = null;

            try
            {
                searchParamPosted = await Client.CreateAsync(searchParam);

                // now update the new search parameter
                var randomNameUpdated = randomName + "U";
                searchParamPosted.Resource.Name = randomNameUpdated;
                searchParamPosted.Resource.Url  = "http://hl7.org/fhir/SearchParameter/Patient-" + randomNameUpdated;
                searchParamPosted.Resource.Code = randomNameUpdated;
                searchParamPosted = await Client.UpdateAsync(searchParamPosted.Resource);

                Uri reindexJobUri;
                FhirResponse <Parameters> reindexJobResult;

                // Reindex just a single patient, so we can try searching with a partially indexed search param
                (reindexJobResult, reindexJobUri) = await Client.PostReindexJobAsync(new Parameters(), $"Patient/{expectedPatient.Resource.Id}/");

                Parameters.ParameterComponent param = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == randomNameUpdated);

                if (param == null)
                {
                    _output.WriteLine($"Parameter with name equal to randomly generated name of this test case: {randomNameUpdated} not found in reindex result.");
                }

                Assert.NotNull(param);
                Assert.Equal(randomName, param.Value.ToString());

                // When job complete, search for resources using new parameter
                await ExecuteAndValidateBundle(
                    $"Patient?{searchParamPosted.Resource.Code}:exact={randomName}",
                    Tuple.Create("x-ms-use-partial-indices", "true"),
                    expectedPatient.Resource);
            }
            catch (FhirException ex) when(ex.StatusCode == HttpStatusCode.BadRequest && ex.Message.Contains("not enabled"))
            {
                Skip.If(!_fixture.IsUsingInProcTestServer, "Reindex is not enabled on this server.");
                return;
            }
            catch (Exception e)
            {
                _output.WriteLine($"Exception: {e.Message}");
                _output.WriteLine($"Stack Trace: {e.StackTrace}");
                throw;
            }
            finally
            {
                // Clean up new SearchParameter
                await DeleteSearchParameterAndVerify(searchParamPosted?.Resource);
            }
        }
예제 #20
0
        /// <summary>
        /// Serialize a FHIR Parameters#Parameter into JSON
        /// </summary>
        public static void SerializeJson(this Parameters.ParameterComponent current, Utf8JsonWriter writer, JsonSerializerOptions options, bool includeStartObject = true)
        {
            if (includeStartObject)
            {
                writer.WriteStartObject();
            }
            // Component: Parameters#Parameter, Export: ParameterComponent, Base: BackboneElement (BackboneElement)
            ((Hl7.Fhir.Model.BackboneElement)current).SerializeJson(writer, options, false);

            writer.WriteString("name", current.NameElement.Value);

            if (current.Value != null)
            {
                switch (current.Value)
                {
                case Base64Binary v_Base64Binary:
                    if (v_Base64Binary != null)
                    {
                        if (v_Base64Binary.Value != null)
                        {
                            writer.WriteString("valueBase64Binary", System.Convert.ToBase64String(v_Base64Binary.Value));
                        }
                        if (v_Base64Binary.HasExtensions() || (!string.IsNullOrEmpty(v_Base64Binary.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueBase64Binary", false, v_Base64Binary.Extension, v_Base64Binary.ElementId);
                        }
                    }
                    break;

                case FhirBoolean v_FhirBoolean:
                    if (v_FhirBoolean != null)
                    {
                        if (v_FhirBoolean.Value != null)
                        {
                            writer.WriteBoolean("valueBoolean", (bool)v_FhirBoolean.Value);
                        }
                        if (v_FhirBoolean.HasExtensions() || (!string.IsNullOrEmpty(v_FhirBoolean.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueBoolean", false, v_FhirBoolean.Extension, v_FhirBoolean.ElementId);
                        }
                    }
                    break;

                case Canonical v_Canonical:
                    if (v_Canonical != null)
                    {
                        if (!string.IsNullOrEmpty(v_Canonical.Value))
                        {
                            writer.WriteString("valueCanonical", v_Canonical.Value);
                        }
                        if (v_Canonical.HasExtensions() || (!string.IsNullOrEmpty(v_Canonical.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueCanonical", false, v_Canonical.Extension, v_Canonical.ElementId);
                        }
                    }
                    break;

                case Code v_Code:
                    if (v_Code != null)
                    {
                        if (!string.IsNullOrEmpty(v_Code.Value))
                        {
                            writer.WriteString("valueCode", v_Code.Value.Trim());
                        }
                        if (v_Code.HasExtensions() || (!string.IsNullOrEmpty(v_Code.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueCode", false, v_Code.Extension, v_Code.ElementId);
                        }
                    }
                    break;

                case Date v_Date:
                    if (v_Date != null)
                    {
                        if (!string.IsNullOrEmpty(v_Date.Value))
                        {
                            writer.WriteString("valueDate", v_Date.Value);
                        }
                        if (v_Date.HasExtensions() || (!string.IsNullOrEmpty(v_Date.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueDate", false, v_Date.Extension, v_Date.ElementId);
                        }
                    }
                    break;

                case FhirDateTime v_FhirDateTime:
                    if (v_FhirDateTime != null)
                    {
                        if (!string.IsNullOrEmpty(v_FhirDateTime.Value))
                        {
                            writer.WriteString("valueDateTime", v_FhirDateTime.Value);
                        }
                        if (v_FhirDateTime.HasExtensions() || (!string.IsNullOrEmpty(v_FhirDateTime.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueDateTime", false, v_FhirDateTime.Extension, v_FhirDateTime.ElementId);
                        }
                    }
                    break;

                case FhirDecimal v_FhirDecimal:
                    if (v_FhirDecimal != null)
                    {
                        if (v_FhirDecimal.Value != null)
                        {
                            writer.WriteNumber("valueDecimal", (decimal)v_FhirDecimal.Value);
                        }
                        if (v_FhirDecimal.HasExtensions() || (!string.IsNullOrEmpty(v_FhirDecimal.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueDecimal", false, v_FhirDecimal.Extension, v_FhirDecimal.ElementId);
                        }
                    }
                    break;

                case Id v_Id:
                    if (v_Id != null)
                    {
                        if (!string.IsNullOrEmpty(v_Id.Value))
                        {
                            writer.WriteString("valueId", v_Id.Value);
                        }
                        if (v_Id.HasExtensions() || (!string.IsNullOrEmpty(v_Id.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueId", false, v_Id.Extension, v_Id.ElementId);
                        }
                    }
                    break;

                case Instant v_Instant:
                    if (v_Instant != null)
                    {
                        if (v_Instant.Value != null)
                        {
                            writer.WriteString("valueInstant", ((DateTimeOffset)v_Instant.Value).ToString("yyyy-MM-dd'T'HH:mm:ss.FFFFFFFK", System.Globalization.CultureInfo.InvariantCulture));
                        }
                        if (v_Instant.HasExtensions() || (!string.IsNullOrEmpty(v_Instant.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueInstant", false, v_Instant.Extension, v_Instant.ElementId);
                        }
                    }
                    break;

                case Integer v_Integer:
                    if (v_Integer != null)
                    {
                        if (v_Integer.Value != null)
                        {
                            writer.WriteNumber("valueInteger", (int)v_Integer.Value);
                        }
                        if (v_Integer.HasExtensions() || (!string.IsNullOrEmpty(v_Integer.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueInteger", false, v_Integer.Extension, v_Integer.ElementId);
                        }
                    }
                    break;

                case Markdown v_Markdown:
                    if (v_Markdown != null)
                    {
                        if (!string.IsNullOrEmpty(v_Markdown.Value))
                        {
                            writer.WriteString("valueMarkdown", v_Markdown.Value);
                        }
                        if (v_Markdown.HasExtensions() || (!string.IsNullOrEmpty(v_Markdown.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueMarkdown", false, v_Markdown.Extension, v_Markdown.ElementId);
                        }
                    }
                    break;

                case Oid v_Oid:
                    if (v_Oid != null)
                    {
                        if (!string.IsNullOrEmpty(v_Oid.Value))
                        {
                            writer.WriteString("valueOid", v_Oid.Value);
                        }
                        if (v_Oid.HasExtensions() || (!string.IsNullOrEmpty(v_Oid.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueOid", false, v_Oid.Extension, v_Oid.ElementId);
                        }
                    }
                    break;

                case PositiveInt v_PositiveInt:
                    if (v_PositiveInt != null)
                    {
                        if (v_PositiveInt.Value != null)
                        {
                            writer.WriteNumber("valuePositiveInt", (int)v_PositiveInt.Value);
                        }
                        if (v_PositiveInt.HasExtensions() || (!string.IsNullOrEmpty(v_PositiveInt.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valuePositiveInt", false, v_PositiveInt.Extension, v_PositiveInt.ElementId);
                        }
                    }
                    break;

                case FhirString v_FhirString:
                    if (v_FhirString != null)
                    {
                        if (!string.IsNullOrEmpty(v_FhirString.Value))
                        {
                            writer.WriteString("valueString", v_FhirString.Value);
                        }
                        if (v_FhirString.HasExtensions() || (!string.IsNullOrEmpty(v_FhirString.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueString", false, v_FhirString.Extension, v_FhirString.ElementId);
                        }
                    }
                    break;

                case Time v_Time:
                    writer.WritePropertyName("valueTime");
                    v_Time.SerializeJson(writer, options);
                    break;

                case UnsignedInt v_UnsignedInt:
                    if (v_UnsignedInt != null)
                    {
                        if (v_UnsignedInt.Value != null)
                        {
                            writer.WriteNumber("valueUnsignedInt", (int)v_UnsignedInt.Value);
                        }
                        if (v_UnsignedInt.HasExtensions() || (!string.IsNullOrEmpty(v_UnsignedInt.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueUnsignedInt", false, v_UnsignedInt.Extension, v_UnsignedInt.ElementId);
                        }
                    }
                    break;

                case FhirUri v_FhirUri:
                    if (v_FhirUri != null)
                    {
                        if (!string.IsNullOrEmpty(v_FhirUri.Value))
                        {
                            writer.WriteString("valueUri", v_FhirUri.Value);
                        }
                        if (v_FhirUri.HasExtensions() || (!string.IsNullOrEmpty(v_FhirUri.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueUri", false, v_FhirUri.Extension, v_FhirUri.ElementId);
                        }
                    }
                    break;

                case FhirUrl v_FhirUrl:
                    if (v_FhirUrl != null)
                    {
                        if (!string.IsNullOrEmpty(v_FhirUrl.Value))
                        {
                            writer.WriteString("valueUrl", v_FhirUrl.Value);
                        }
                        if (v_FhirUrl.HasExtensions() || (!string.IsNullOrEmpty(v_FhirUrl.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueUrl", false, v_FhirUrl.Extension, v_FhirUrl.ElementId);
                        }
                    }
                    break;

                case Uuid v_Uuid:
                    if (v_Uuid != null)
                    {
                        if (!string.IsNullOrEmpty(v_Uuid.Value))
                        {
                            writer.WriteString("valueUuid", v_Uuid.Value);
                        }
                        if (v_Uuid.HasExtensions() || (!string.IsNullOrEmpty(v_Uuid.ElementId)))
                        {
                            JsonStreamUtilities.SerializeExtensionList(writer, options, "_valueUuid", false, v_Uuid.Extension, v_Uuid.ElementId);
                        }
                    }
                    break;

                case Address v_Address:
                    writer.WritePropertyName("valueAddress");
                    v_Address.SerializeJson(writer, options);
                    break;

                case Age v_Age:
                    writer.WritePropertyName("valueAge");
                    v_Age.SerializeJson(writer, options);
                    break;

                case Annotation v_Annotation:
                    writer.WritePropertyName("valueAnnotation");
                    v_Annotation.SerializeJson(writer, options);
                    break;

                case Attachment v_Attachment:
                    writer.WritePropertyName("valueAttachment");
                    v_Attachment.SerializeJson(writer, options);
                    break;

                case CodeableConcept v_CodeableConcept:
                    writer.WritePropertyName("valueCodeableConcept");
                    v_CodeableConcept.SerializeJson(writer, options);
                    break;

                case Coding v_Coding:
                    writer.WritePropertyName("valueCoding");
                    v_Coding.SerializeJson(writer, options);
                    break;

                case ContactPoint v_ContactPoint:
                    writer.WritePropertyName("valueContactPoint");
                    v_ContactPoint.SerializeJson(writer, options);
                    break;

                case Count v_Count:
                    writer.WritePropertyName("valueCount");
                    v_Count.SerializeJson(writer, options);
                    break;

                case Distance v_Distance:
                    writer.WritePropertyName("valueDistance");
                    v_Distance.SerializeJson(writer, options);
                    break;

                case Duration v_Duration:
                    writer.WritePropertyName("valueDuration");
                    v_Duration.SerializeJson(writer, options);
                    break;

                case HumanName v_HumanName:
                    writer.WritePropertyName("valueHumanName");
                    v_HumanName.SerializeJson(writer, options);
                    break;

                case Identifier v_Identifier:
                    writer.WritePropertyName("valueIdentifier");
                    v_Identifier.SerializeJson(writer, options);
                    break;

                case Money v_Money:
                    writer.WritePropertyName("valueMoney");
                    v_Money.SerializeJson(writer, options);
                    break;

                case Period v_Period:
                    writer.WritePropertyName("valuePeriod");
                    v_Period.SerializeJson(writer, options);
                    break;

                case Quantity v_Quantity:
                    writer.WritePropertyName("valueQuantity");
                    v_Quantity.SerializeJson(writer, options);
                    break;

                case Range v_Range:
                    writer.WritePropertyName("valueRange");
                    v_Range.SerializeJson(writer, options);
                    break;

                case Ratio v_Ratio:
                    writer.WritePropertyName("valueRatio");
                    v_Ratio.SerializeJson(writer, options);
                    break;

                case ResourceReference v_ResourceReference:
                    writer.WritePropertyName("valueReference");
                    v_ResourceReference.SerializeJson(writer, options);
                    break;

                case SampledData v_SampledData:
                    writer.WritePropertyName("valueSampledData");
                    v_SampledData.SerializeJson(writer, options);
                    break;

                case Signature v_Signature:
                    writer.WritePropertyName("valueSignature");
                    v_Signature.SerializeJson(writer, options);
                    break;

                case Timing v_Timing:
                    writer.WritePropertyName("valueTiming");
                    v_Timing.SerializeJson(writer, options);
                    break;

                case ContactDetail v_ContactDetail:
                    writer.WritePropertyName("valueContactDetail");
                    v_ContactDetail.SerializeJson(writer, options);
                    break;

                case Contributor v_Contributor:
                    writer.WritePropertyName("valueContributor");
                    v_Contributor.SerializeJson(writer, options);
                    break;

                case DataRequirement v_DataRequirement:
                    writer.WritePropertyName("valueDataRequirement");
                    v_DataRequirement.SerializeJson(writer, options);
                    break;

                case Expression v_Expression:
                    writer.WritePropertyName("valueExpression");
                    v_Expression.SerializeJson(writer, options);
                    break;

                case ParameterDefinition v_ParameterDefinition:
                    writer.WritePropertyName("valueParameterDefinition");
                    v_ParameterDefinition.SerializeJson(writer, options);
                    break;

                case RelatedArtifact v_RelatedArtifact:
                    writer.WritePropertyName("valueRelatedArtifact");
                    v_RelatedArtifact.SerializeJson(writer, options);
                    break;

                case TriggerDefinition v_TriggerDefinition:
                    writer.WritePropertyName("valueTriggerDefinition");
                    v_TriggerDefinition.SerializeJson(writer, options);
                    break;

                case UsageContext v_UsageContext:
                    writer.WritePropertyName("valueUsageContext");
                    v_UsageContext.SerializeJson(writer, options);
                    break;

                case Dosage v_Dosage:
                    writer.WritePropertyName("valueDosage");
                    v_Dosage.SerializeJson(writer, options);
                    break;

                case Meta v_Meta:
                    writer.WritePropertyName("valueMeta");
                    v_Meta.SerializeJson(writer, options);
                    break;
                }
            }
            if (current.Resource != null)
            {
                writer.WritePropertyName("resource");
                JsonSerializer.Serialize <object>(writer, (Hl7.Fhir.Model.Resource)current.Resource, options);
            }

            if ((current.Part != null) && (current.Part.Count != 0))
            {
                writer.WritePropertyName("part");
                writer.WriteStartArray();
                foreach (Parameters.ParameterComponent val in current.Part)
                {
                    val.SerializeJson(writer, options, true);
                }
                writer.WriteEndArray();
            }

            if (includeStartObject)
            {
                writer.WriteEndObject();
            }
        }
예제 #21
0
        /// <summary>
        /// Deserialize JSON into a FHIR Parameters#Parameter
        /// </summary>
        public static void DeserializeJsonProperty(this Parameters.ParameterComponent current, ref Utf8JsonReader reader, JsonSerializerOptions options, string propertyName)
        {
            switch (propertyName)
            {
            case "name":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.NameElement = new FhirString();
                    reader.Skip();
                }
                else
                {
                    current.NameElement = new FhirString(reader.GetString());
                }
                break;

            case "_name":
                if (current.NameElement == null)
                {
                    current.NameElement = new FhirString();
                }
                ((Hl7.Fhir.Model.Element)current.NameElement).DeserializeJson(ref reader, options);
                break;

            case "valueBase64Binary":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new Base64Binary();
                    reader.Skip();
                }
                else
                {
                    current.Value = new Base64Binary(System.Convert.FromBase64String(reader.GetString()));
                }
                break;

            case "_valueBase64Binary":
                if (current.Value == null)
                {
                    current.Value = new Base64Binary();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueBoolean":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new FhirBoolean();
                    reader.Skip();
                }
                else
                {
                    current.Value = new FhirBoolean(reader.GetBoolean());
                }
                break;

            case "_valueBoolean":
                if (current.Value == null)
                {
                    current.Value = new FhirBoolean();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueCanonical":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new Canonical();
                    reader.Skip();
                }
                else
                {
                    current.Value = new Canonical(reader.GetString());
                }
                break;

            case "_valueCanonical":
                if (current.Value == null)
                {
                    current.Value = new Canonical();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueCode":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new Code();
                    reader.Skip();
                }
                else
                {
                    current.Value = new Code(reader.GetString());
                }
                break;

            case "_valueCode":
                if (current.Value == null)
                {
                    current.Value = new Code();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueDate":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new Date();
                    reader.Skip();
                }
                else
                {
                    current.Value = new Date(reader.GetString());
                }
                break;

            case "_valueDate":
                if (current.Value == null)
                {
                    current.Value = new Date();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueDateTime":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new FhirDateTime();
                    reader.Skip();
                }
                else
                {
                    current.Value = new FhirDateTime(reader.GetString());
                }
                break;

            case "_valueDateTime":
                if (current.Value == null)
                {
                    current.Value = new FhirDateTime();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueDecimal":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new FhirDecimal();
                    reader.Skip();
                }
                else
                {
                    current.Value = new FhirDecimal(reader.GetDecimal());
                }
                break;

            case "_valueDecimal":
                if (current.Value == null)
                {
                    current.Value = new FhirDecimal();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueId":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new Id();
                    reader.Skip();
                }
                else
                {
                    current.Value = new Id(reader.GetString());
                }
                break;

            case "_valueId":
                if (current.Value == null)
                {
                    current.Value = new Id();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueInstant":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new Instant();
                    reader.Skip();
                }
                else
                {
                    current.Value = new Instant(DateTimeOffset.Parse(reader.GetString()));
                }
                break;

            case "_valueInstant":
                if (current.Value == null)
                {
                    current.Value = new Instant();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueInteger":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new Integer();
                    reader.Skip();
                }
                else
                {
                    current.Value = new Integer(reader.GetInt32());
                }
                break;

            case "_valueInteger":
                if (current.Value == null)
                {
                    current.Value = new Integer();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueMarkdown":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new Markdown();
                    reader.Skip();
                }
                else
                {
                    current.Value = new Markdown(reader.GetString());
                }
                break;

            case "_valueMarkdown":
                if (current.Value == null)
                {
                    current.Value = new Markdown();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueOid":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new Oid();
                    reader.Skip();
                }
                else
                {
                    current.Value = new Oid(reader.GetString());
                }
                break;

            case "_valueOid":
                if (current.Value == null)
                {
                    current.Value = new Oid();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valuePositiveInt":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new PositiveInt();
                    reader.Skip();
                }
                else
                {
                    current.Value = new PositiveInt(reader.GetInt32());
                }
                break;

            case "_valuePositiveInt":
                if (current.Value == null)
                {
                    current.Value = new PositiveInt();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueString":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new FhirString();
                    reader.Skip();
                }
                else
                {
                    current.Value = new FhirString(reader.GetString());
                }
                break;

            case "_valueString":
                if (current.Value == null)
                {
                    current.Value = new FhirString();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueTime":
                current.Value = new Hl7.Fhir.Model.Time();
                ((Hl7.Fhir.Model.Time)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueUnsignedInt":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new UnsignedInt();
                    reader.Skip();
                }
                else
                {
                    current.Value = new UnsignedInt(reader.GetInt32());
                }
                break;

            case "_valueUnsignedInt":
                if (current.Value == null)
                {
                    current.Value = new UnsignedInt();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueUri":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new FhirUri();
                    reader.Skip();
                }
                else
                {
                    current.Value = new FhirUri(reader.GetString());
                }
                break;

            case "_valueUri":
                if (current.Value == null)
                {
                    current.Value = new FhirUri();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueUrl":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new FhirUrl();
                    reader.Skip();
                }
                else
                {
                    current.Value = new FhirUrl(reader.GetString());
                }
                break;

            case "_valueUrl":
                if (current.Value == null)
                {
                    current.Value = new FhirUrl();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueUuid":
                if (reader.TokenType == JsonTokenType.Null)
                {
                    current.Value = new Uuid();
                    reader.Skip();
                }
                else
                {
                    current.Value = new Uuid(reader.GetString());
                }
                break;

            case "_valueUuid":
                if (current.Value == null)
                {
                    current.Value = new Uuid();
                }
                ((Hl7.Fhir.Model.Element)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueAddress":
                current.Value = new Hl7.Fhir.Model.Address();
                ((Hl7.Fhir.Model.Address)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueAge":
                current.Value = new Hl7.Fhir.Model.Age();
                ((Hl7.Fhir.Model.Age)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueAnnotation":
                current.Value = new Hl7.Fhir.Model.Annotation();
                ((Hl7.Fhir.Model.Annotation)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueAttachment":
                current.Value = new Hl7.Fhir.Model.Attachment();
                ((Hl7.Fhir.Model.Attachment)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueCodeableConcept":
                current.Value = new Hl7.Fhir.Model.CodeableConcept();
                ((Hl7.Fhir.Model.CodeableConcept)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueCoding":
                current.Value = new Hl7.Fhir.Model.Coding();
                ((Hl7.Fhir.Model.Coding)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueContactPoint":
                current.Value = new Hl7.Fhir.Model.ContactPoint();
                ((Hl7.Fhir.Model.ContactPoint)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueCount":
                current.Value = new Hl7.Fhir.Model.Count();
                ((Hl7.Fhir.Model.Count)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueDistance":
                current.Value = new Hl7.Fhir.Model.Distance();
                ((Hl7.Fhir.Model.Distance)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueDuration":
                current.Value = new Hl7.Fhir.Model.Duration();
                ((Hl7.Fhir.Model.Duration)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueHumanName":
                current.Value = new Hl7.Fhir.Model.HumanName();
                ((Hl7.Fhir.Model.HumanName)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueIdentifier":
                current.Value = new Hl7.Fhir.Model.Identifier();
                ((Hl7.Fhir.Model.Identifier)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueMoney":
                current.Value = new Hl7.Fhir.Model.Money();
                ((Hl7.Fhir.Model.Money)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valuePeriod":
                current.Value = new Hl7.Fhir.Model.Period();
                ((Hl7.Fhir.Model.Period)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueQuantity":
                current.Value = new Hl7.Fhir.Model.Quantity();
                ((Hl7.Fhir.Model.Quantity)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueRange":
                current.Value = new Hl7.Fhir.Model.Range();
                ((Hl7.Fhir.Model.Range)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueRatio":
                current.Value = new Hl7.Fhir.Model.Ratio();
                ((Hl7.Fhir.Model.Ratio)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueReference":
                current.Value = new Hl7.Fhir.Model.ResourceReference();
                ((Hl7.Fhir.Model.ResourceReference)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueSampledData":
                current.Value = new Hl7.Fhir.Model.SampledData();
                ((Hl7.Fhir.Model.SampledData)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueSignature":
                current.Value = new Hl7.Fhir.Model.Signature();
                ((Hl7.Fhir.Model.Signature)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueTiming":
                current.Value = new Hl7.Fhir.Model.Timing();
                ((Hl7.Fhir.Model.Timing)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueContactDetail":
                current.Value = new Hl7.Fhir.Model.ContactDetail();
                ((Hl7.Fhir.Model.ContactDetail)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueContributor":
                current.Value = new Hl7.Fhir.Model.Contributor();
                ((Hl7.Fhir.Model.Contributor)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueDataRequirement":
                current.Value = new Hl7.Fhir.Model.DataRequirement();
                ((Hl7.Fhir.Model.DataRequirement)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueExpression":
                current.Value = new Hl7.Fhir.Model.Expression();
                ((Hl7.Fhir.Model.Expression)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueParameterDefinition":
                current.Value = new Hl7.Fhir.Model.ParameterDefinition();
                ((Hl7.Fhir.Model.ParameterDefinition)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueRelatedArtifact":
                current.Value = new Hl7.Fhir.Model.RelatedArtifact();
                ((Hl7.Fhir.Model.RelatedArtifact)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueTriggerDefinition":
                current.Value = new Hl7.Fhir.Model.TriggerDefinition();
                ((Hl7.Fhir.Model.TriggerDefinition)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueUsageContext":
                current.Value = new Hl7.Fhir.Model.UsageContext();
                ((Hl7.Fhir.Model.UsageContext)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueDosage":
                current.Value = new Hl7.Fhir.Model.Dosage();
                ((Hl7.Fhir.Model.Dosage)current.Value).DeserializeJson(ref reader, options);
                break;

            case "valueMeta":
                current.Value = new Hl7.Fhir.Model.Meta();
                ((Hl7.Fhir.Model.Meta)current.Value).DeserializeJson(ref reader, options);
                break;

            case "resource":
                current.Resource = JsonStreamResourceConverter.PolymorphicRead(ref reader, typeof(Resource), options);
                break;

            case "part":
                if ((reader.TokenType != JsonTokenType.StartArray) || (!reader.Read()))
                {
                    throw new JsonException($"ParameterComponent error reading 'part' expected StartArray, found {reader.TokenType}! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}");
                }

                current.Part = new List <Parameters.ParameterComponent>();

                while (reader.TokenType != JsonTokenType.EndArray)
                {
                    Hl7.Fhir.Model.Parameters.ParameterComponent v_Part = new Hl7.Fhir.Model.Parameters.ParameterComponent();
                    v_Part.DeserializeJson(ref reader, options);
                    current.Part.Add(v_Part);

                    if (!reader.Read())
                    {
                        throw new JsonException($"ParameterComponent error reading 'part' array, read failed! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}");
                    }
                    if (reader.TokenType == JsonTokenType.EndObject)
                    {
                        reader.Read();
                    }
                }

                if (current.Part.Count == 0)
                {
                    current.Part = null;
                }
                break;

            // Complex: parameter, Export: ParameterComponent, Base: BackboneElement
            default:
                ((Hl7.Fhir.Model.BackboneElement)current).DeserializeJsonProperty(ref reader, options, propertyName);
                break;
            }
        }
예제 #22
0
        public async Task GivenASearchParam_WhenUpdatingParam_ThenResourcesIndexedWithUpdatedParam()
        {
            var patientName = Guid.NewGuid().ToString().ComputeHash().Substring(28).ToLower();
            var patient     = new Patient {
                Name = new List <HumanName> {
                    new HumanName {
                        Family = patientName
                    }
                }
            };
            var searchParam = Samples.GetJsonSample <SearchParameter>("SearchParameter");

            // POST a new patient
            FhirResponse <Patient> expectedPatient = await Client.CreateAsync(patient);

            // POST a new Search parameter
            FhirResponse <SearchParameter> searchParamPosted = null;

            try
            {
                searchParamPosted = await Client.CreateAsync(searchParam);
            }
            catch (FhirException)
            {
                // if the SearchParameter exists, we should delete it and recreate it
                var searchParamBundle = await Client.SearchAsync(ResourceType.SearchParameter, $"url={searchParam.Url}");

                if (searchParamBundle.Resource?.Entry[0] != null && searchParamBundle.Resource?.Entry[0].Resource.ResourceType == ResourceType.SearchParameter)
                {
                    await DeleteSearchParameterAndVerify(searchParamBundle.Resource?.Entry[0].Resource as SearchParameter);

                    searchParamPosted = await Client.CreateAsync(searchParam);
                }
                else
                {
                    throw;
                }
            }

            // now update the new search parameter
            searchParamPosted.Resource.Name = "foo2";
            searchParamPosted.Resource.Url  = "http://hl7.org/fhir/SearchParameter/Patient-foo2";
            searchParamPosted.Resource.Code = "foo2";
            searchParamPosted = await Client.UpdateAsync(searchParamPosted.Resource);

            Uri reindexJobUri;
            FhirResponse <Parameters> reindexJobResult;

            try
            {
                // Reindex just a single patient, so we can try searching with a partially indexed search param
                (reindexJobResult, reindexJobUri) = await Client.PostReindexJobAsync(new Parameters(), $"Patient/{expectedPatient.Resource.Id}/");

                Parameters.ParameterComponent param = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == "foo2");

                Assert.Equal(patientName, param.Value.ToString());
            }
            catch (FhirException ex) when(ex.StatusCode == HttpStatusCode.BadRequest && ex.Message.Contains("not enabled"))
            {
                Skip.If(!_fixture.IsUsingInProcTestServer, "Reindex is not enabled on this server.");
                return;
            }

            // When job complete, search for resources using new parameter
            await ExecuteAndValidateBundle($"Patient?foo2:exact={patientName}", Tuple.Create("x-ms-use-partial-indices", "true"), expectedPatient.Resource);

            // Clean up new SearchParameter
            await DeleteSearchParameterAndVerify(searchParamPosted.Resource);
        }
        public void Test_DeleteHistoryIndexes()
        {
            FhirClient clientFhir = new FhirClient(StaticTestData.FhirEndpoint(), false);

            clientFhir.Timeout = 1000 * 720; // give the call a while to execute (particularly while debugging).

            string PatientOneResourceId   = Guid.NewGuid().ToString();
            string PatientOneMRNIdentifer = Guid.NewGuid().ToString();

            //Add a Patient resource by Create
            Patient PatientOne = new Patient();

            PatientOne.Id = PatientOneResourceId;
            PatientOne.Name.Add(HumanName.ForFamily("TestPatient").WithGiven("Test"));
            PatientOne.BirthDateElement = new Date("1979-09-30");
            PatientOne.Identifier.Add(new Identifier(StaticTestData.TestIdentiferSystem, PatientOneMRNIdentifer));
            PatientOne.Gender = AdministrativeGender.Unknown;

            Patient PatientResult = null;

            try
            {
                PatientResult = clientFhir.Update <Patient>(PatientOne);
            }
            catch (Exception Exec)
            {
                Assert.True(false, "Exception thrown on Patient resource Update: " + Exec.Message);
            }
            Assert.NotNull(PatientResult, "Resource create by Updated returned resource of null");

            PatientResult = null;

            //Update the patient again to ensure there are History indexes to delete
            try
            {
                PatientResult = clientFhir.Update <Patient>(PatientOne);
            }
            catch (Exception Exec)
            {
                Assert.True(false, "Exception thrown on Patient resource Update: " + Exec.Message);
            }
            Assert.NotNull(PatientResult, "Resource create by Updated returned resource of null");

            //------------------------------------------------------------------------------------
            // ------------ Base Operation, limited types by parameters --------------------------
            //------------------------------------------------------------------------------------

            //Now setup to use the base operation $delete-history-indexes
            //Parameter Resource
            Parameters ParametersIn = new Parameters();

            //ParametersIn.Id = Guid.NewGuid().ToString();
            ParametersIn.Parameter = new List <Parameters.ParameterComponent>();
            var ParamOne = new Parameters.ParameterComponent();

            ParametersIn.Parameter.Add(ParamOne);
            ParamOne.Name  = "ResourceType";
            ParamOne.Value = new FhirString(FHIRAllTypes.Patient.GetLiteral());

            Parameters ParametersResult = null;

            try
            {
                var ResourceResult = clientFhir.WholeSystemOperation(OperationName, ParametersIn);
                ParametersResult = ResourceResult as Parameters;
            }
            catch (Exception Exec)
            {
                Assert.True(false, $"Exception thrown on Operation call to ${OperationName}: " + Exec.Message);
            }
            Assert.NotNull(ParametersResult, "Resource create by Updated returned resource of null");
            Assert.NotNull(ParametersResult.Parameter, "ParametersResult.Parameter is null");
            Assert.AreEqual(ParametersResult.Parameter.Count(), 1, "ParametersResult.Parameter contains more than one parameter.");
            Assert.AreEqual(ParametersResult.Parameter[0].Name, $"{FHIRAllTypes.Patient.GetLiteral()}_TotalIndexesDeletedCount", "ParametersResult.Parameter.Name not as expected.");
            Assert.IsInstanceOf <FhirDecimal>(ParametersResult.Parameter[0].Value, "ParametersResult.Parameter.Value expected FhirDecimal.");
            Assert.Greater((ParametersResult.Parameter[0].Value as FhirDecimal).Value, 0, "ParametersResult.Parameter.Value expected to be greater than 0.");
            ParametersResult = null;


            //------------------------------------------------------------------------------------
            // ------------ Resource Base Operation ALL resource ResourceType = *----------------------------------------------
            //------------------------------------------------------------------------------------

            //Now setup to use the base operation $delete-history-indexes
            //Parameter Resource
            ParametersIn           = new Parameters();
            ParametersIn.Id        = Guid.NewGuid().ToString();
            ParametersIn.Parameter = new List <Parameters.ParameterComponent>();
            ParamOne = new Parameters.ParameterComponent();
            ParametersIn.Parameter.Add(ParamOne);
            ParamOne.Name  = "ResourceType";
            ParamOne.Value = new FhirString("*");

            ParametersResult = null;
            try
            {
                var ResourceResult = clientFhir.WholeSystemOperation(OperationName, ParametersIn);
                ParametersResult = ResourceResult as Parameters;
            }
            catch (Exception Exec)
            {
                Assert.True(false, $"Exception thrown on Operation call to ${OperationName}: " + Exec.Message);
            }
            Assert.NotNull(ParametersResult, "Resource create by Updated returned resource of null");
            Assert.NotNull(ParametersResult.Parameter, "ParametersResult.Parameter is null");
            Assert.AreEqual(ParametersResult.Parameter.Count(), ModelInfo.SupportedResources.Count, "ParametersResult.Parameter.Count Not equal to Supported resource total.");
            ParametersResult = null;

            //------------------------------------------------------------------------------------
            // ------------ Resource Type Operation ----------------------------------------------
            //------------------------------------------------------------------------------------

            //Update the patient again to ensure there are History indexes to delete
            PatientResult = null;
            try
            {
                PatientResult = clientFhir.Update <Patient>(PatientOne);
            }
            catch (Exception Exec)
            {
                Assert.True(false, "Exception thrown on Patient resource Update: " + Exec.Message);
            }
            Assert.NotNull(PatientResult, "Resource create by Updated returned resource of null");

            ParametersIn    = new Parameters();
            ParametersIn.Id = Guid.NewGuid().ToString();

            ParametersResult = null;
            try
            {
                var ResourceResult = clientFhir.TypeOperation <Patient>(OperationName, ParametersIn);
                ParametersResult = ResourceResult as Parameters;
            }
            catch (Exception Exec)
            {
                Assert.True(false, $"Exception thrown on Operation call to ${OperationName}: " + Exec.Message);
            }
            Assert.NotNull(ParametersResult, "Resource create by Updated returned resource of null");
            Assert.NotNull(ParametersResult.Parameter, "ParametersResult.Parameter is null");
            Assert.AreEqual(ParametersResult.Parameter.Count(), 1, "ParametersResult.Parameter contains more than one parameter.");
            Assert.AreEqual(ParametersResult.Parameter[0].Name, $"{FHIRAllTypes.Patient.GetLiteral()}_TotalIndexesDeletedCount", "ParametersResult.Parameter.Name not as expected.");
            Assert.IsInstanceOf <FhirDecimal>(ParametersResult.Parameter[0].Value, "ParametersResult.Parameter.Value expected FhirDecimal.");
            Assert.Greater((ParametersResult.Parameter[0].Value as FhirDecimal).Value, 0, "ParametersResult.Parameter.Value expected to be greater than 0.");

            //--- Clean Up ---------------------------------------------------------
            //Clean up by deleting all Test Patients
            SearchParams sp = new SearchParams().Where($"identifier={StaticTestData.TestIdentiferSystem}|");

            try
            {
                clientFhir.Delete("Patient", sp);
            }
            catch (Exception Exec)
            {
                Assert.True(false, "Exception thrown on conditional delete of resource Patient: " + Exec.Message);
            }
        }
예제 #24
0
        public async Task GivenASearchParameterWithMultipleBaseResourceTypes_WhenTargetingReindexJobToSameListOfResourceTypes_ThenSearchParametersMarkedFullyIndexed()
        {
            var randomName  = Guid.NewGuid().ToString().ComputeHash().Substring(0, 14).ToLower();
            var searchParam = Samples.GetJsonSample <SearchParameter>("SearchParameter-Resource-idfoo");

            searchParam.Name = searchParam.Name.Replace("foo", randomName);
            searchParam.Url  = searchParam.Url.Replace("foo", randomName);
            searchParam.Code = randomName + "Code";
            searchParam.Base = new List <ResourceType?>()
            {
                ResourceType.Appointment, ResourceType.Immunization
            };

            // POST a new appointment
            var appointment = Samples.GetJsonSample <Appointment>("Appointment");
            FhirResponse <Appointment> expectedAppointment = await Client.CreateAsync(appointment);

            // POST a second appointment to show it is filtered and not returned when using the new search parameter
            var appointment2 = Samples.GetJsonSample <Appointment>("Appointment");
            await Client.CreateAsync(appointment2);

            // POST a new Immunization
            var immunization = Samples.GetJsonSample <Immunization>("Immunization");
            FhirResponse <Immunization> expectedImmunization = await Client.CreateAsync(immunization);

            // POST a new Search parameter
            FhirResponse <SearchParameter> searchParamPosted = null;

            try
            {
                searchParamPosted = await Client.CreateAsync(searchParam);

                _output.WriteLine($"SearchParameter is posted {searchParam.Url}");

                Uri reindexJobUri;

                // Start a reindex job
                var reindexParameters = new Parameters();
                reindexParameters.Add("targetResourceTypes", new FhirString("Appointment,Immunization"));
                (_, reindexJobUri) = await Client.PostReindexJobAsync(reindexParameters);

                await WaitForReindexStatus(reindexJobUri, "Completed");

                FhirResponse <Parameters> reindexJobResult = await Client.CheckReindexAsync(reindexJobUri);

                Parameters.ParameterComponent searchParamListParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == "searchParams");
                Parameters.ParameterComponent targetResourcesParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.TargetResourceTypes);
                Parameters.ParameterComponent resourcesParam       = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.Resources);

                // output reindex job for debugging
                _output.WriteLine("ReindexJobDocument:");
                var serializer = new FhirJsonSerializer();
                _output.WriteLine(serializer.SerializeToString(reindexJobResult.Resource));

                Assert.Contains(searchParamPosted.Resource.Url, searchParamListParam?.Value?.ToString());
                Assert.Contains("Appointment", targetResourcesParam?.Value?.ToString());
                Assert.Contains("Appointment", resourcesParam?.Value?.ToString());
                Assert.Contains("Immunization", targetResourcesParam?.Value?.ToString());
                Assert.Contains("Immunization", resourcesParam?.Value?.ToString());

                _output.WriteLine($"Reindex job is completed, it should have reindexed the resources of type Appointment and Immunization only.");

                var floatParse = float.TryParse(
                    reindexJobResult.Resource.Parameter.FirstOrDefault(predicate => predicate.Name == "resourcesSuccessfullyReindexed").Value.ToString(),
                    out float resourcesReindexed);

                _output.WriteLine($"Reindex job is completed, {resourcesReindexed} resources Reindexed");

                Assert.True(floatParse);
                Assert.True(resourcesReindexed > 0.0);

                // When job complete, search for resources using new parameter
                // When there are multiple instances of the fhir-server running, it could take some time
                // for the search parameter/reindex updates to propogate to all instances. Hence we are
                // adding some retries below to account for that delay.
                int  retryCount = 0;
                bool success    = true;
                do
                {
                    success = true;
                    retryCount++;
                    try
                    {
                        await ExecuteAndValidateBundle(
                            $"Appointment?{searchParam.Code}={expectedAppointment.Resource.Id}",
                            expectedAppointment.Resource);

                        await ExecuteAndValidateBundle(
                            $"Immunization?{searchParam.Code}={expectedImmunization.Resource.Id}",
                            expectedImmunization.Resource);
                    }
                    catch (Exception ex)
                    {
                        _output.WriteLine($"Failed to validate bundle: {ex}");
                        success = false;
                        await Task.Delay(10000);
                    }
                }while (!success && retryCount < 3);

                Assert.True(success);
            }
            catch (FhirException ex) when(ex.StatusCode == HttpStatusCode.BadRequest && ex.Message.Contains("not enabled"))
            {
                _output.WriteLine($"Skipping because reindex is disabled.");
                Skip.If(!_fixture.IsUsingInProcTestServer, "Reindex is not enabled on this server.");
                return;
            }
            catch (Exception e)
            {
                _output.WriteLine($"Exception: {e.Message}");
                _output.WriteLine($"Stack Trace: {e.StackTrace}");
                throw;
            }
            finally
            {
                // Clean up new SearchParameter
                await DeleteSearchParameterAndVerify(searchParamPosted?.Resource);
            }
        }