/// <inheritdoc/>
        public void Synchronize(FhirTransactionContext context, ImagingStudy.InstanceComponent instance)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(context.ChangeFeedEntry, nameof(context.ChangeFeedEntry));
            EnsureArg.IsNotNull(instance, nameof(instance));

            DicomDataset dataset = context.ChangeFeedEntry.Metadata;

            if (dataset == null)
            {
                return;
            }

            // Add sopclass to instance
            if (dataset.TryGetSingleValue(DicomTag.SOPClassUID, out string sopClassUid) &&
                !string.Equals(instance.SopClass?.Code, sopClassUid, StringComparison.Ordinal))
            {
                instance.SopClass = new Coding(null, sopClassUid);
            }

            // Add instancenumber to instance
            if (dataset.TryGetSingleValue(DicomTag.InstanceNumber, out int instanceNumber))
            {
                instance.Number = instanceNumber;
            }
        }
Ejemplo n.º 2
0
        public async Task SynchronizeSeriesPropertiesAsync(FhirTransactionContext context, ImagingStudy.SeriesComponent series, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(series, nameof(series));

            await _imagingStudySeriesPropertySynchronizer.SynchronizeAsync(context, series, cancellationToken);
        }
Ejemplo n.º 3
0
        public void SynchronizeSeriesProperties(FhirTransactionContext context, ImagingStudy.SeriesComponent series)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(series, nameof(series));

            _imagingStudySeriesPropertySynchronizer.Synchronize(context, series);
        }
        /// <inheritdoc/>
        public void Synchronize(FhirTransactionContext context, ImagingStudy.SeriesComponent series)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(context.ChangeFeedEntry, nameof(context.ChangeFeedEntry));
            EnsureArg.IsNotNull(series, nameof(series));

            DicomDataset dataset = context.ChangeFeedEntry.Metadata;

            if (dataset == null)
            {
                return;
            }

            // Add series number
            AddSeriesNumber(series, dataset);

            // Add description to series
            AddDescription(series, dataset);

            // Add modality to series
            AddModalityToSeries(series, dataset);

            // Add startedElement to series
            AddStartedElement(series, dataset, context.UtcDateTimeOffset);
        }
Ejemplo n.º 5
0
        public void SynchronizeStudyProperties(FhirTransactionContext context, ImagingStudy imagingStudy)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(imagingStudy, nameof(imagingStudy));

            _imagingStudyPropertySynchronizer.Synchronize(context, imagingStudy);
        }
Ejemplo n.º 6
0
        public async Task SynchronizeInstancePropertiesAsync(FhirTransactionContext context, ImagingStudy.InstanceComponent instance, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(instance, nameof(instance));

            await _imagingStudyInstancePropertySynchronizer.SynchronizeAsync(context, instance, cancellationToken);
        }
Ejemplo n.º 7
0
        /// <inheritdoc/>
        public async Task SynchronizeAsync(FhirTransactionContext context, Patient patient, bool isNewPatient, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(patient, nameof(patient));

            DicomDataset dataset = context.ChangeFeedEntry.Metadata;

            foreach (IPatientPropertySynchronizer patientPropertySynchronizer in _patientPropertySynchronizers)
            {
                try
                {
                    patientPropertySynchronizer.Synchronize(dataset, patient, isNewPatient);
                }
                catch (DicomTagException ex)
                {
                    if (_dicomCastconfiguration.Features.IgnoreSyncOfInvalidTagValue)
                    {
                        await _exceptionStore.WriteExceptionAsync(
                            context.ChangeFeedEntry,
                            ex,
                            ErrorType.DicomValidationError,
                            cancellationToken);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
        }
Ejemplo n.º 8
0
        public static async Task SynchronizePropertiesAsync <T>(T component, FhirTransactionContext context, Action <T, FhirTransactionContext> synchronizeAction, bool requiredProperty, bool enforceAllFields, IExceptionStore exceptionStore, CancellationToken cancellationToken = default)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(synchronizeAction, nameof(synchronizeAction));
            EnsureArg.IsNotNull(exceptionStore, nameof(exceptionStore));

            try
            {
                synchronizeAction(component, context);
            }
            catch (DicomTagException ex)
            {
                if (!enforceAllFields && !requiredProperty)
                {
                    await exceptionStore.WriteExceptionAsync(
                        context.ChangeFeedEntry,
                        ex,
                        ErrorType.DicomValidationError,
                        cancellationToken);
                }
                else
                {
                    throw;
                }
            }
        }
Ejemplo n.º 9
0
        public async Task SynchronizeStudyPropertiesAsync(FhirTransactionContext context, ImagingStudy imagingStudy, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(imagingStudy, nameof(imagingStudy));

            await _imagingStudyPropertySynchronizer.SynchronizeAsync(context, imagingStudy, cancellationToken);
        }
Ejemplo n.º 10
0
        public void SynchronizeInstanceProperties(FhirTransactionContext context, ImagingStudy.InstanceComponent instance)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(instance, nameof(instance));

            _imagingStudyInstancePropertySynchronizer.Synchronize(context, instance);
        }
        public async Task <IEnumerable <FhirTransactionRequestEntry> > BuildAsync(FhirTransactionContext context, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(context.ChangeFeedEntry, nameof(context.ChangeFeedEntry));

            Identifier         identifier           = IdentifierUtility.CreateIdentifier(context.ChangeFeedEntry.StudyInstanceUid);
            List <Observation> matchingObservations = (await _fhirService.RetrieveObservationsAsync(identifier, cancellationToken)).ToList();

            // terminate early if no observation found
            if (matchingObservations.Count == 0)
            {
                return(null);
            }

            var requests = new List <FhirTransactionRequestEntry>();

            foreach (Observation observation in matchingObservations)
            {
                Bundle.RequestComponent request = new Bundle.RequestComponent()
                {
                    Method = Bundle.HTTPVerb.DELETE,
                    Url    = $"{ResourceType.Observation.GetLiteral()}/{observation.Id}"
                };

                requests.Add(new FhirTransactionRequestEntry(
                                 FhirTransactionRequestMode.Delete,
                                 request,
                                 observation.ToServerResourceId(),
                                 observation));
            }

            return(requests);
        }
Ejemplo n.º 12
0
        /// <inheritdoc/>
        public async Task PrepareRequestAsync(FhirTransactionContext context, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(context, nameof(context));

            DicomDataset dataset = context.ChangeFeedEntry.Metadata;

            if (dataset == null)
            {
                return;
            }

            if (!dataset.TryGetSingleValue(DicomTag.PatientID, out string patientId))
            {
                throw new MissingRequiredDicomTagException(nameof(DicomTag.PatientID));
            }

            var patientIdentifier = new Identifier(string.Empty, patientId);

            FhirTransactionRequestMode requestMode = FhirTransactionRequestMode.None;

            Patient existingPatient = await _fhirService.RetrievePatientAsync(patientIdentifier, cancellationToken);

            Patient patient = (Patient)existingPatient?.DeepCopy();

            if (existingPatient == null)
            {
                patient = new Patient();

                patient.Identifier.Add(patientIdentifier);

                requestMode = FhirTransactionRequestMode.Create;
            }

            _patientSynchronizer.Synchronize(dataset, patient);

            if (requestMode == FhirTransactionRequestMode.None &&
                !existingPatient.IsExactly(patient))
            {
                requestMode = FhirTransactionRequestMode.Update;
            }

            Bundle.RequestComponent request = requestMode switch
            {
                FhirTransactionRequestMode.Create => GenerateCreateRequest(patientIdentifier),
                FhirTransactionRequestMode.Update => GenerateUpdateRequest(patient),
                _ => null
            };

            IResourceId resourceId = requestMode switch
            {
                FhirTransactionRequestMode.Create => new ClientResourceId(),
                _ => existingPatient.ToServerResourceId(),
            };

            context.Request.Patient = new FhirTransactionRequestEntry(
                requestMode,
                request,
                resourceId,
                patient);
        }
        /// <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);
            }
Ejemplo n.º 14
0
        private void AddImagingStudyEndpoint(ImagingStudy imagingStudy, FhirTransactionContext context)
        {
            var endpointReference = context.Request.Endpoint.ResourceId.ToResourceReference();

            if (!imagingStudy.Endpoint.Any(endpoint => endpointReference.IsExactly(endpoint)))
            {
                imagingStudy.Endpoint.Add(endpointReference);
            }
        }
        /// <inheritdoc/>
        public async Task <FhirTransactionRequestEntry> BuildAsync(FhirTransactionContext context, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(context.ChangeFeedEntry, nameof(context.ChangeFeedEntry));
            EnsureArg.IsNotNull(context.Request, nameof(context.Request));

            IResourceId patientId = context.Request.Patient.ResourceId;

            ChangeFeedEntry changeFeedEntry = context.ChangeFeedEntry;

            Identifier imagingStudyIdentifier = ImagingStudyIdentifierUtility.CreateIdentifier(changeFeedEntry.StudyInstanceUid);

            ImagingStudy existingImagingStudy = await _fhirService.RetrieveImagingStudyAsync(imagingStudyIdentifier, cancellationToken);

            ImagingStudy imagingStudy = (ImagingStudy)existingImagingStudy?.DeepCopy();

            FhirTransactionRequestMode requestMode = FhirTransactionRequestMode.None;

            if (existingImagingStudy == null)
            {
                imagingStudy = new ImagingStudy()
                {
                    Status  = ImagingStudy.ImagingStudyStatus.Available,
                    Subject = patientId.ToResourceReference(),
                };

                imagingStudy.Identifier.Add(imagingStudyIdentifier);
                requestMode = FhirTransactionRequestMode.Create;
            }

            SynchronizeImagingStudyProperties(context, imagingStudy);

            if (requestMode != FhirTransactionRequestMode.Create &&
                !existingImagingStudy.IsExactly(imagingStudy))
            {
                requestMode = FhirTransactionRequestMode.Update;
            }

            Bundle.RequestComponent request = requestMode switch
            {
                FhirTransactionRequestMode.Create => ImagingStudyPipelineHelper.GenerateCreateRequest(imagingStudyIdentifier),
                FhirTransactionRequestMode.Update => ImagingStudyPipelineHelper.GenerateUpdateRequest(imagingStudy),
                _ => null,
            };

            IResourceId resourceId = requestMode switch
            {
                FhirTransactionRequestMode.Create => new ClientResourceId(),
                _ => existingImagingStudy.ToServerResourceId(),
            };

            return(new FhirTransactionRequestEntry(
                       requestMode,
                       request,
                       resourceId,
                       imagingStudy));
        }
        /// <inheritdoc/>
        public async Task <FhirTransactionRequestEntry> BuildAsync(FhirTransactionContext context, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(context.ChangeFeedEntry, nameof(context.ChangeFeedEntry));

            ChangeFeedEntry changeFeedEntry = context.ChangeFeedEntry;

            Identifier   imagingStudyIdentifier = ImagingStudyIdentifierUtility.CreateIdentifier(changeFeedEntry.StudyInstanceUid);
            ImagingStudy imagingStudy           = await _fhirService.RetrieveImagingStudyAsync(imagingStudyIdentifier, cancellationToken);

            // Returns null if imagingStudy does not exists for given studyInstanceUid
            if (imagingStudy == null)
            {
                return(null);
            }

            string imagingStudySource = imagingStudy.Meta.Source;

            ImagingStudy.SeriesComponent   series   = ImagingStudyPipelineHelper.GetSeriesWithinAStudy(changeFeedEntry.SeriesInstanceUid, imagingStudy.Series);
            ImagingStudy.InstanceComponent instance = ImagingStudyPipelineHelper.GetInstanceWithinASeries(changeFeedEntry.SopInstanceUid, series);

            // Return null if the given instance is not present in ImagingStudy
            if (instance == null)
            {
                return(null);
            }

            // Removes instance from series collection
            series.Instance.Remove(instance);

            // Removes series from ImagingStudy if its instance collection is empty
            if (series.Instance.Count == 0)
            {
                imagingStudy.Series.Remove(series);
            }

            if (imagingStudy.Series.Count == 0 && _dicomWebEndpoint.Equals(imagingStudySource, System.StringComparison.Ordinal))
            {
                return(new FhirTransactionRequestEntry(
                           FhirTransactionRequestMode.Delete,
                           ImagingStudyPipelineHelper.GenerateDeleteRequest(imagingStudy),
                           imagingStudy.ToServerResourceId(),
                           imagingStudy));
            }

            return(new FhirTransactionRequestEntry(
                       FhirTransactionRequestMode.Update,
                       ImagingStudyPipelineHelper.GenerateUpdateRequest(imagingStudy),
                       imagingStudy.ToServerResourceId(),
                       imagingStudy));
        }
Ejemplo n.º 17
0
 public void ProcessResponse(FhirTransactionContext context)
 {
     using (LogProcessingResponseDelegate(_logger, _pipelineStepName))
     {
         try
         {
             _fhirTransactionPipelineStep.ProcessResponse(context);
         }
         catch (Exception ex)
         {
             LogExceptionDelegate(_logger, ex);
             throw;
         }
     }
 }
Ejemplo n.º 18
0
        /// <inheritdoc/>
        public async Task PrepareRequestAsync(FhirTransactionContext context, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(context, nameof(context));

            ChangeFeedEntry changeFeedEntry = context.ChangeFeedEntry;

            context.Request.ImagingStudy = changeFeedEntry.Action switch
            {
                ChangeFeedAction.Create => await _imagingStudyUpsertHandler.BuildAsync(context, cancellationToken),
                ChangeFeedAction.Delete => await _imagingStudyDeleteHandler.BuildAsync(context, cancellationToken),
                _ => throw new NotSupportedException(
                          string.Format(
                              CultureInfo.InvariantCulture,
                              DicomCastCoreResource.NotSupportedChangeFeedAction,
                              changeFeedEntry.Action)),
            };
        }
        public static void SetDateTimeOffSet(FhirTransactionContext context)
        {
            DicomDataset metadata = context.ChangeFeedEntry.Metadata;

            if (metadata != null &&
                metadata.TryGetSingleValue(DicomTag.TimezoneOffsetFromUTC, out string utcOffsetInString))
            {
                try
                {
                    context.UtcDateTimeOffset = DateTimeOffset.ParseExact(utcOffsetInString, FhirTransactionConstants.UtcTimezoneOffsetFormat, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces).Offset;
                }
                catch (FormatException)
                {
                    throw new InvalidDicomTagValueException(nameof(DicomTag.TimezoneOffsetFromUTC), utcOffsetInString);
                }
            }
        }
Ejemplo n.º 20
0
        public async Task <IEnumerable <FhirTransactionRequestEntry> > BuildAsync(FhirTransactionContext context, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(context?.ChangeFeedEntry, nameof(context.ChangeFeedEntry));
            EnsureArg.IsNotNull(context.Request, nameof(context.Request));

            IResourceId     patientId       = context.Request.Patient.ResourceId;
            IResourceId     imagingStudyId  = context.Request.ImagingStudy.ResourceId;
            ChangeFeedEntry changeFeedEntry = context.ChangeFeedEntry;

            Identifier identifier = IdentifierUtility.CreateIdentifier(changeFeedEntry.StudyInstanceUid);

            IReadOnlyCollection <Observation> observations = _observationParser.Parse(changeFeedEntry.Metadata, patientId.ToResourceReference(), imagingStudyId.ToResourceReference(), identifier);

            if (observations.Count == 0)
            {
                return(Enumerable.Empty <FhirTransactionRequestEntry>());
            }

            Identifier imagingStudyIdentifier = imagingStudyId.ToResourceReference().Identifier;
            IEnumerable <Observation> existingDoseSummariesAsync = imagingStudyIdentifier != null
                ? await _fhirService
                                                                   .RetrieveObservationsAsync(
                imagingStudyId.ToResourceReference().Identifier,
                cancellationToken)
                : new List <Observation>();

            // TODO: Figure out a way to match existing observations with newly created ones.

            List <FhirTransactionRequestEntry> fhirRequests = new List <FhirTransactionRequestEntry>();

            foreach (var observation in observations)
            {
                fhirRequests.Add(new FhirTransactionRequestEntry(
                                     FhirTransactionRequestMode.Create,
                                     new Bundle.RequestComponent()
                {
                    Method = Bundle.HTTPVerb.POST,
                    Url    = ResourceType.Observation.GetLiteral()
                },
                                     new ClientResourceId(),
                                     observation));
            }

            return(fhirRequests);
        }
Ejemplo n.º 21
0
        /// <inheritdoc/>
        public void ProcessResponse(FhirTransactionContext context)
        {
            // If the Patient does not exist, we will use conditional create to create the resource
            // to avoid duplicated resource being created. However, if the resource with the identifier
            // was created externally between the retrieve and create, conditional create will return 200
            // and might not contain the changes so we will need to try again.
            if (context.Request.Patient?.RequestMode == FhirTransactionRequestMode.Create)
            {
                FhirTransactionResponseEntry patient = context.Response.Patient;

                HttpStatusCode statusCode = patient.Response.Annotation <HttpStatusCode>();

                if (statusCode == HttpStatusCode.OK)
                {
                    throw new ResourceConflictException();
                }
            }
        }
        public async Task PrepareRequestAsync(FhirTransactionContext context, CancellationToken cancellationToken = default)
        {
            EnsureArg.IsNotNull(context, nameof(context));

            if (_dicomCastConfiguration.Features.GenerateObservations)
            {
                ChangeFeedEntry changeFeedEntry = context.ChangeFeedEntry;
                context.Request.Observation = changeFeedEntry.Action switch
                {
                    ChangeFeedAction.Create => await _observationUpsertHandler.BuildAsync(context, cancellationToken),
                    ChangeFeedAction.Delete => await _observationDeleteHandler.BuildAsync(context, cancellationToken),
                    _ => throw new NotSupportedException(
                              string.Format(
                                  CultureInfo.InvariantCulture,
                                  DicomCastCoreResource.NotSupportedChangeFeedAction,
                                  changeFeedEntry.Action))
                };
            }
        }
Ejemplo n.º 23
0
        private async Task AddSeriesToImagingStudyAsync(FhirTransactionContext context, ImagingStudy imagingStudy, CancellationToken cancellationToken)
        {
            ChangeFeedEntry changeFeedEntry = context.ChangeFeedEntry;

            List <ImagingStudy.SeriesComponent> existingSeriesCollection = imagingStudy.Series;

            ImagingStudy.InstanceComponent instance = new ImagingStudy.InstanceComponent()
            {
                Uid = changeFeedEntry.SopInstanceUid,
            };

            // Checks if the given series already exists within a study
            ImagingStudy.SeriesComponent series = ImagingStudyPipelineHelper.GetSeriesWithinAStudy(changeFeedEntry.SeriesInstanceUid, existingSeriesCollection);

            if (series == null)
            {
                series = new ImagingStudy.SeriesComponent()
                {
                    Uid = changeFeedEntry.SeriesInstanceUid,
                };

                series.Instance.Add(instance);
                imagingStudy.Series.Add(series);
            }
            else
            {
                ImagingStudy.InstanceComponent existingInstance = ImagingStudyPipelineHelper.GetInstanceWithinASeries(changeFeedEntry.SopInstanceUid, series);

                if (existingInstance == null)
                {
                    series.Instance.Add(instance);
                }
                else
                {
                    instance = existingInstance;
                }
            }

            await _imagingStudySynchronizer.SynchronizeSeriesPropertiesAsync(context, series, cancellationToken);

            await _imagingStudySynchronizer.SynchronizeInstancePropertiesAsync(context, instance, cancellationToken);
        }
Ejemplo n.º 24
0
 public async Task PrepareRequestAsync(FhirTransactionContext context, CancellationToken cancellationToken)
 {
     using (LogPreparingRequestDelegate(_logger, _pipelineStepName))
     {
         try
         {
             await _fhirTransactionPipelineStep.PrepareRequestAsync(context, cancellationToken);
         }
         catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested)
         {
             // Cancel requested.
             throw;
         }
         catch (Exception ex)
         {
             LogExceptionDelegate(_logger, ex);
             throw;
         }
     }
 }
Ejemplo n.º 25
0
        /// <inheritdoc/>
        public void ProcessResponse(FhirTransactionContext context)
        {
            EnsureArg.IsNotNull(context, nameof(context));

            // If the ImagingStudy does not exist, we will use conditional create to create the resource
            // to avoid duplicated resource being created. However, if the resource with the identifier
            // was created externally between the retrieve and create, conditional create will return 200
            // and might not contain the changes so we will need to try again.
            if (context.Request.ImagingStudy?.RequestMode == FhirTransactionRequestMode.Create)
            {
                FhirTransactionResponseEntry imagingStudy = context.Response.ImagingStudy;

                HttpStatusCode statusCode = imagingStudy.Response.Annotation <HttpStatusCode>();

                if (statusCode == HttpStatusCode.OK)
                {
                    throw new ResourceConflictException();
                }
            }
        }
Ejemplo n.º 26
0
        /// <inheritdoc/>
        public void Synchronize(FhirTransactionContext context, ImagingStudy imagingStudy)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(imagingStudy, nameof(imagingStudy));
            EnsureArg.IsNotNull(context.Request.Endpoint, nameof(context.Request.Endpoint));
            EnsureArg.IsNotNull(context.ChangeFeedEntry, nameof(context.ChangeFeedEntry));

            DicomDataset dataset = context.ChangeFeedEntry.Metadata;

            if (dataset == null)
            {
                return;
            }

            ImagingStudyPipelineHelper.SetDateTimeOffSet(context);

            AddStartedElement(imagingStudy, dataset, context.UtcDateTimeOffset);
            AddImagingStudyEndpoint(imagingStudy, context);
            AddModality(imagingStudy, dataset);
            AddNote(imagingStudy, dataset);
        }
Ejemplo n.º 27
0
 public static async Task SynchronizePropertiesAsync <T>(T component, FhirTransactionContext context, Action <T, FhirTransactionContext> synchronizeAction, bool requiredProperty, bool partialValidation, IExceptionStore exceptionStore, CancellationToken cancellationToken = default)
 {
     try
     {
         synchronizeAction(component, context);
     }
     catch (DicomTagException ex)
     {
         if (partialValidation && !requiredProperty)
         {
             await exceptionStore.WriteExceptionAsync(
                 context.ChangeFeedEntry,
                 ex,
                 ErrorType.DicomValidationError,
                 cancellationToken);
         }
         else
         {
             throw;
         }
     }
 }
        public void ProcessResponse(FhirTransactionContext context)
        {
            EnsureArg.IsNotNull(context, nameof(context));

            if (_dicomCastConfiguration.Features.GenerateObservations)
            {
                if (context.Response?.Observation == null)
                {
                    return;
                }

                foreach (FhirTransactionResponseEntry observation in context.Response.Observation)
                {
                    HttpStatusCode statusCode = observation.Response.Annotation <HttpStatusCode>();

                    // We are only currently doing POSTs/DELETEs which should result in a 201 or 204
                    if (statusCode != HttpStatusCode.Created && statusCode != HttpStatusCode.NoContent)
                    {
                        throw new ResourceConflictException();
                    }
                }
            }
        }
Ejemplo n.º 29
0
        public async Task PrepareRequestAsync(FhirTransactionContext context, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(context, nameof(context));

            string queryParameter = $"name={FhirTransactionConstants.EndpointName}&connection-type={FhirTransactionConstants.EndpointConnectionTypeSystem}|{FhirTransactionConstants.EndpointConnectionTypeCode}";

            Endpoint endpoint = await _fhirService.RetrieveEndpointAsync(queryParameter, cancellationToken);

            FhirTransactionRequestMode requestMode = FhirTransactionRequestMode.None;

            if (endpoint == null)
            {
                endpoint = new Endpoint()
                {
                    Name           = FhirTransactionConstants.EndpointName,
                    Status         = Endpoint.EndpointStatus.Active,
                    ConnectionType = new Coding()
                    {
                        System = FhirTransactionConstants.EndpointConnectionTypeSystem,
                        Code   = FhirTransactionConstants.EndpointConnectionTypeCode,
                    },
                    Address     = _dicomWebEndpoint,
                    PayloadType = new List <CodeableConcept>
                    {
                        new CodeableConcept(string.Empty, string.Empty, FhirTransactionConstants.EndpointPayloadTypeText),
                    },
                    PayloadMimeType = new string[]
                    {
                        FhirTransactionConstants.DicomMimeType,
                    },
                };

                requestMode = FhirTransactionRequestMode.Create;
            }
            else
            {
                // Make sure the address matches.
                if (!string.Equals(endpoint.Address, _dicomWebEndpoint, StringComparison.Ordinal))
                {
                    // We have found an endpoint with matching name and connection-type but the address does not match.
                    throw new FhirResourceValidationException(DicomCastCoreResource.MismatchEndpointAddress);
                }
            }

            Bundle.RequestComponent request = requestMode switch
            {
                FhirTransactionRequestMode.Create => new Bundle.RequestComponent()
                {
                    Method      = Bundle.HTTPVerb.POST,
                    IfNoneExist = queryParameter,
                    Url         = ResourceType.Endpoint.GetLiteral(),
                },
                _ => null,
            };

            IResourceId resourceId = requestMode switch
            {
                FhirTransactionRequestMode.Create => new ClientResourceId(),
                _ => endpoint.ToServerResourceId(),
            };

            context.Request.Endpoint = new FhirTransactionRequestEntry(
                requestMode,
                request,
                resourceId,
                endpoint);
        }
Ejemplo n.º 30
0
        private async Task SynchronizeImagingStudyPropertiesAsync(FhirTransactionContext context, ImagingStudy imagingStudy, CancellationToken cancellationToken)
        {
            await _imagingStudySynchronizer.SynchronizeStudyPropertiesAsync(context, imagingStudy, cancellationToken);

            await AddSeriesToImagingStudyAsync(context, imagingStudy, cancellationToken);
        }