/// <inheritdoc/>
        public async Task ProcessAsync(ChangeFeedEntry changeFeedEntry, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(changeFeedEntry, nameof(changeFeedEntry));

            // Create a context used throughout this process.
            var context = new FhirTransactionContext(changeFeedEntry);

            // Prepare all required objects for the transaction.
            foreach (IFhirTransactionPipelineStep pipeline in _fhirTransactionPipelines)
            {
                await pipeline.PrepareRequestAsync(context, cancellationToken);
            }

            // Check to see if any resource needs to be created/updated.
            var bundle = new Bundle()
            {
                Type = Bundle.BundleType.Transaction,
            };

            var usedPropertyAccessors = new List <FhirTransactionRequestResponsePropertyAccessor>(_requestResponsePropertyAccessors.Count);

            foreach (FhirTransactionRequestResponsePropertyAccessor propertyAccessor in _requestResponsePropertyAccessors)
            {
                FhirTransactionRequestEntry requestEntry = propertyAccessor.RequestEntryGetter(context.Request);

                if (requestEntry == null || requestEntry.RequestMode == FhirTransactionRequestMode.None)
                {
                    // No associated request, skip it.
                    continue;
                }

                // There is a associated request, add to the list so it gets processed.
                usedPropertyAccessors.Add(propertyAccessor);
                bundle.Entry.Add(CreateRequestBundleEntryComponent(requestEntry));
            }

            if (!bundle.Entry.Any())
            {
                // Nothing to update.
                return;
            }

            // Execute the transaction.
            Bundle responseBundle = await _fhirTransactionExecutor.ExecuteTransactionAsync(bundle, cancellationToken);

            // Process the response.
            for (int i = 0; i < usedPropertyAccessors.Count; i++)
            {
                FhirTransactionResponseEntry responseEntry = CreateResponseEntry(responseBundle.Entry[i]);

                usedPropertyAccessors[i].ResponseEntrySetter(context.Response, responseEntry);
            }

            // Execute any additional checks of the response.
            foreach (IFhirTransactionPipelineStep pipeline in _fhirTransactionPipelines)
            {
                pipeline.ProcessResponse(context);
            }
Exemplo n.º 2
0
        public async Task GivenAResourceToProcess_WhenProcessed_ThenTransactionShouldBeExecuted(FhirTransactionRequestMode requestMode)
        {
            // Setup the pipeline step to simulate creating/updating patient.
            var patientRequest = new FhirTransactionRequestEntry(
                requestMode,
                new Bundle.RequestComponent(),
                new ClientResourceId(),
                new Patient());

            var pipelineStep = new MockFhirTransactionPipelineStep()
            {
                OnPrepareRequestAsyncCalled = (context, cancellationToken) =>
                {
                    context.Request.Patient = patientRequest;

                    Assert.Equal(DefaultCancellationToken, cancellationToken);
                },
            };

            _fhirTransactionPipelineSteps.Add(pipelineStep);

            // Setup the transaction executor to return response.
            var responseBundle = new Bundle();

            var responseEntry = new Bundle.EntryComponent()
            {
                Response = new Bundle.ResponseComponent(),
                Resource = new Patient(),
            };

            responseBundle.Entry.Add(responseEntry);

            _fhirTransactionExecutor.ExecuteTransactionAsync(
                Arg.Any <Bundle>(),
                DefaultCancellationToken)
            .Returns(call =>
            {
                // Make sure the request bundle is correct.
                Bundle requestBundle = call.ArgAt <Bundle>(0);

                Assert.NotNull(requestBundle);
                Assert.Equal(Bundle.BundleType.Transaction, requestBundle.Type);

                Assert.Collection(
                    requestBundle.Entry,
                    entry =>
                {
                    Assert.Equal(patientRequest.ResourceId.ToString(), entry.FullUrl);
                    Assert.Equal(patientRequest.Request, entry.Request);
                    Assert.Equal(patientRequest.Resource, entry.Resource);
                });

                return(responseBundle);
            });

            // Process
            await _fhirTransactionPipeline.ProcessAsync(ChangeFeedGenerator.Generate(), DefaultCancellationToken);

            // The response should have been processed.
            Assert.NotNull(_capturedFhirTransactionContext);

            FhirTransactionResponseEntry patientResponse = _capturedFhirTransactionContext.Response.Patient;

            Assert.NotNull(patientResponse);
            Assert.Equal(responseEntry.Response, patientResponse.Response);
            Assert.Equal(responseEntry.Resource, patientResponse.Resource);
        }
        /// <inheritdoc/>
        public async Task ProcessAsync(ChangeFeedEntry changeFeedEntry, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(changeFeedEntry, nameof(changeFeedEntry));

            // Create a context used throughout this process.
            var context = new FhirTransactionContext(changeFeedEntry);

            // Prepare all required objects for the transaction.
            foreach (IFhirTransactionPipelineStep pipeline in _fhirTransactionPipelines)
            {
                await pipeline.PrepareRequestAsync(context, cancellationToken);
            }

            // Check to see if any resource needs to be created/updated.
            var bundle = new Bundle()
            {
                Type = Bundle.BundleType.Transaction,
            };

            var usedPropertyAccessors = new List <(FhirTransactionRequestResponsePropertyAccessor Accessor, int Count)>(_requestResponsePropertyAccessors.Count);

            foreach (FhirTransactionRequestResponsePropertyAccessor propertyAccessor in _requestResponsePropertyAccessors)
            {
                List <FhirTransactionRequestEntry> requestEntries = propertyAccessor.RequestEntryGetter(context.Request)?.ToList();

                if (requestEntries == null || requestEntries.Count == 0)
                {
                    continue;
                }

                int useCount = 0;
                foreach (FhirTransactionRequestEntry requestEntry in requestEntries)
                {
                    if (requestEntry == null || requestEntry.RequestMode == FhirTransactionRequestMode.None)
                    {
                        // No associated request, skip it.
                        continue;
                    }

                    // There is a associated request, add to the list so it gets processed.
                    bundle.Entry.Add(CreateRequestBundleEntryComponent(requestEntry));
                    useCount++;
                }

                usedPropertyAccessors.Add((propertyAccessor, useCount));
            }

            if (bundle.Entry.Count == 0)
            {
                // Nothing to update.
                return;
            }

            // Execute the transaction.
            Bundle responseBundle = await _fhirTransactionExecutor.ExecuteTransactionAsync(bundle, cancellationToken);

            // Process the response.
            int processedResponseItems = 0;

            foreach ((FhirTransactionRequestResponsePropertyAccessor accessor, int count) in
                     usedPropertyAccessors.Where(x => x.Count > 0))
            {
                var responseEntries = new List <FhirTransactionResponseEntry>();
                for (int j = 0; j < count; j++)
                {
                    FhirTransactionResponseEntry responseEntry = CreateResponseEntry(responseBundle.Entry[processedResponseItems + j]);
                    responseEntries.Add(responseEntry);
                }

                processedResponseItems += count;
                accessor.ResponseEntrySetter(context.Response, responseEntries);
            }

            // Execute any additional checks of the response.
            foreach (IFhirTransactionPipelineStep pipeline in _fhirTransactionPipelines)
            {
                pipeline.ProcessResponse(context);
            }