/// <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); }
/// <summary> /// Deserialize JSON into a FHIR Bundle#Request /// </summary> public static void DeserializeJson(this Bundle.RequestComponent 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($"Bundle.RequestComponent >>> Bundle#Request.{propertyName}, depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } reader.Read(); current.DeserializeJsonProperty(ref reader, options, propertyName); } } throw new JsonException($"Bundle.RequestComponent: invalid state! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); }
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); }
public IRequestMeta Set(Bundle.RequestComponent RequestComponent) { this.PyroRequestUri = IPyroRequestUriFactory.CreateFhirRequestUri(); CreateAndParsePyroRequestUri(ConstructAbsoluteRequestUrl(RequestComponent.Url, this.PyroRequestUri.PrimaryRootUrlStore.Url)); this.RequestHeader = IRequestHeaderFactory.CreateRequestHeader().Parse(RequestComponent); this.SearchParameterGeneric = ISearchParameterGenericFactory.CreateDtoSearchParameterGeneric().Parse(this.PyroRequestUri.FhirRequestUri.Query); return(this); }
/// <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)); }
public FhirTransactionRequestEntry( FhirTransactionRequestMode requestMode, Bundle.RequestComponent request, IResourceId resourceId, Resource resource) { EnsureArg.EnumIsDefined(requestMode, nameof(requestMode)); RequestMode = requestMode; Request = request; ResourceId = resourceId; Resource = resource; }
private Bundle.RequestComponent GenerateRequestComponentForEntry(Bundle.EntryComponent Entry) { var RequestComponent = new Bundle.RequestComponent(); if (!string.IsNullOrWhiteSpace(Entry.Resource.Id)) { //Perform a PUT (Update) RequestComponent.Method = Bundle.HTTPVerb.PUT; RequestComponent.Url = $"{Entry.Resource.TypeName}/{Entry.Resource.Id}"; } else { //Perform a POST (Create) RequestComponent.Method = Bundle.HTTPVerb.POST; RequestComponent.Url = $"{Entry.Resource.TypeName}"; } return(RequestComponent); }
public IRequestHeader Parse(Bundle.RequestComponent RequestComponent) { if (!string.IsNullOrWhiteSpace(RequestComponent.IfNoneExist)) { this.IfNoneExist = RequestComponent.IfNoneExist; } if (RequestComponent.IfModifiedSince.HasValue) { var DateTime = new FhirDateTime(RequestComponent.IfModifiedSince.Value); this.IfModifiedSince = DateTime.Value; } if (!string.IsNullOrWhiteSpace(RequestComponent.IfNoneMatch)) { this.IfNoneMatch = ParseVersionHeader(RequestComponent.IfNoneMatch); } if (!string.IsNullOrWhiteSpace(RequestComponent.IfMatch)) { this.IfMatch = ParseVersionHeader(RequestComponent.IfMatch); } return(this); }
public Stream TerminzBatch() { string rv = string.Empty; string responseType = GetResponseType(); string fhirVersion = GetFhirVersion(); // get Bundle from the Request Stream string reqBody = string.Empty; UTF8Encoding enc = new UTF8Encoding(); Stream reqStream = OperationContext.Current.RequestContext.RequestMessage.GetBody <Stream>(); using (StreamReader reader = new StreamReader(reqStream, enc)) { reqBody = reader.ReadToEnd(); } string reqType = WebOperationContext.Current.IncomingRequest.ContentType.ToLower(); Resource fhirResource; if (reqType.Contains("json")) { FhirJsonParser fjp = new FhirJsonParser(); fhirResource = fjp.Parse <Resource>(reqBody); } else { FhirXmlParser fxp = new FhirXmlParser(); fhirResource = fxp.Parse <Resource>(reqBody); } if (fhirResource.ResourceType == ResourceType.Bundle) { Bundle fb = (Bundle)fhirResource; if (fb.Type == Bundle.BundleType.Batch) { Bundle responseBundle = new Bundle(); responseBundle.Id = Guid.NewGuid().ToString(); responseBundle.Type = Bundle.BundleType.BatchResponse; foreach (Bundle.EntryComponent comp in fb.Entry) { Bundle.RequestComponent rc = comp.Request; if (rc.Method == Bundle.HTTPVerb.GET) { if (rc.Url.IndexOf("$validate-code") > 0) { // extract and parse query string to get parameters int qsPos = rc.Url.IndexOf('?'); string querystring = (qsPos < rc.Url.Length - 1) ? rc.Url.Substring(qsPos + 1) : String.Empty; qParam = System.Web.HttpUtility.ParseQueryString(querystring); // extract resource (CodeSystem or ValueSet) ID string resourceID = string.Empty; string resourceName = resourceID.IndexOf("/ValueSet/") > 0 ? "ValueSet" : "CodeSystem"; try { resourceID = rc.Url.Remove(qsPos); int resNamePos = resourceID.IndexOf("/" + resourceName + "/"); resourceID = resourceID.Substring(resNamePos + 9).Replace("/", "").Replace("$validate-code", ""); } catch { } ServiceInterface appSi = new ServiceInterface(); responseBundle.AddResourceEntry(appSi.GetFhirResource(resourceName, resourceID, "$validate-code", qParam, fhirVersion), string.Empty); } else { responseBundle.AddResourceEntry(OperationOutcome.ForMessage("Unrecognised Operation in Request..." + rc.Url, OperationOutcome.IssueType.Unknown), string.Empty); } } else if (rc.Method == Bundle.HTTPVerb.POST) { if (rc.Url.IndexOf("$translate") > 0 && comp.Resource.ResourceType == ResourceType.Parameters) { // extract ConceptMap ID string cmID = string.Empty; try { cmID = rc.Url.Replace("ConceptMap/", "").Replace("$translate", "").Replace("/", ""); } catch { } // get parameters Parameters fParam = (Parameters)comp.Resource; SetQueryParameters(fParam); ServiceInterface appSi = new ServiceInterface(); responseBundle.AddResourceEntry(appSi.GetFhirResource("ConceptMap", cmID, "$translate", qParam, fhirVersion), string.Empty); } else { responseBundle.AddResourceEntry(OperationOutcome.ForMessage("Unrecognised Operation in Request..." + rc.Url, OperationOutcome.IssueType.Unknown), string.Empty); } } else { responseBundle.AddResourceEntry(OperationOutcome.ForMessage("Method Not Supported in Batch Mode '" + rc.Method.ToString() + "'", OperationOutcome.IssueType.NotSupported), string.Empty); } } fhirResource = responseBundle; } else { fhirResource = OperationOutcome.ForMessage("No module could be found to handle the bundle type '" + fb.TypeName + "'", OperationOutcome.IssueType.NotFound); } } else { fhirResource = OperationOutcome.ForMessage("No module could be found to handle the request '" + fhirResource.ResourceType.ToString() + "'", OperationOutcome.IssueType.NotFound); } if (fhirResource.ResourceType == ResourceType.OperationOutcome) { AddNarrativeToOperationOutcome(fhirResource); OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse; response.StatusCode = HttpStatusCode.BadRequest; // if wish for more granular response codes, need Issue Type //OperationOutcome oo = (OperationOutcome)fhirResource; //OperationOutcome.IssueType opOutcome = (OperationOutcome.IssueType)oo.Issue[0].Code; } // convert to stream to remove leading XML elements and json quotes rv = SerializeResponse(fhirResource, responseType, SummaryType.False); return(new System.IO.MemoryStream(UTF8Encoding.Default.GetBytes(rv))); }
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); }
/// <summary> /// Deserialize JSON into a FHIR Bundle#Request /// </summary> public static void DeserializeJsonProperty(this Bundle.RequestComponent current, ref Utf8JsonReader reader, JsonSerializerOptions options, string propertyName) { switch (propertyName) { case "method": if (reader.TokenType == JsonTokenType.Null) { current.MethodElement = new Code <Hl7.Fhir.Model.Bundle.HTTPVerb>(); reader.Skip(); } else { current.MethodElement = new Code <Hl7.Fhir.Model.Bundle.HTTPVerb>(Hl7.Fhir.Utility.EnumUtility.ParseLiteral <Hl7.Fhir.Model.Bundle.HTTPVerb>(reader.GetString())); } break; case "_method": if (current.MethodElement == null) { current.MethodElement = new Code <Hl7.Fhir.Model.Bundle.HTTPVerb>(); } ((Hl7.Fhir.Model.Element)current.MethodElement).DeserializeJson(ref reader, options); break; case "url": if (reader.TokenType == JsonTokenType.Null) { current.UrlElement = new FhirUri(); reader.Skip(); } else { current.UrlElement = new FhirUri(reader.GetString()); } break; case "_url": if (current.UrlElement == null) { current.UrlElement = new FhirUri(); } ((Hl7.Fhir.Model.Element)current.UrlElement).DeserializeJson(ref reader, options); break; case "ifNoneMatch": if (reader.TokenType == JsonTokenType.Null) { current.IfNoneMatchElement = new FhirString(); reader.Skip(); } else { current.IfNoneMatchElement = new FhirString(reader.GetString()); } break; case "_ifNoneMatch": if (current.IfNoneMatchElement == null) { current.IfNoneMatchElement = new FhirString(); } ((Hl7.Fhir.Model.Element)current.IfNoneMatchElement).DeserializeJson(ref reader, options); break; case "ifModifiedSince": if (reader.TokenType == JsonTokenType.Null) { current.IfModifiedSinceElement = new Instant(); reader.Skip(); } else { current.IfModifiedSinceElement = new Instant(DateTimeOffset.Parse(reader.GetString())); } break; case "_ifModifiedSince": if (current.IfModifiedSinceElement == null) { current.IfModifiedSinceElement = new Instant(); } ((Hl7.Fhir.Model.Element)current.IfModifiedSinceElement).DeserializeJson(ref reader, options); break; case "ifMatch": if (reader.TokenType == JsonTokenType.Null) { current.IfMatchElement = new FhirString(); reader.Skip(); } else { current.IfMatchElement = new FhirString(reader.GetString()); } break; case "_ifMatch": if (current.IfMatchElement == null) { current.IfMatchElement = new FhirString(); } ((Hl7.Fhir.Model.Element)current.IfMatchElement).DeserializeJson(ref reader, options); break; case "ifNoneExist": if (reader.TokenType == JsonTokenType.Null) { current.IfNoneExistElement = new FhirString(); reader.Skip(); } else { current.IfNoneExistElement = new FhirString(reader.GetString()); } break; case "_ifNoneExist": if (current.IfNoneExistElement == null) { current.IfNoneExistElement = new FhirString(); } ((Hl7.Fhir.Model.Element)current.IfNoneExistElement).DeserializeJson(ref reader, options); break; // Complex: request, Export: RequestComponent, Base: BackboneElement default: ((Hl7.Fhir.Model.BackboneElement)current).DeserializeJsonProperty(ref reader, options, propertyName); break; } }
/// <summary> /// Serialize a FHIR Bundle#Request into JSON /// </summary> public static void SerializeJson(this Bundle.RequestComponent current, Utf8JsonWriter writer, JsonSerializerOptions options, bool includeStartObject = true) { if (includeStartObject) { writer.WriteStartObject(); } // Component: Bundle#Request, Export: RequestComponent, Base: BackboneElement (BackboneElement) ((Hl7.Fhir.Model.BackboneElement)current).SerializeJson(writer, options, false); writer.WriteString("method", Hl7.Fhir.Utility.EnumUtility.GetLiteral(current.MethodElement.Value)); writer.WriteString("url", current.UrlElement.Value); if (current.IfNoneMatchElement != null) { if (!string.IsNullOrEmpty(current.IfNoneMatchElement.Value)) { writer.WriteString("ifNoneMatch", current.IfNoneMatchElement.Value); } if (current.IfNoneMatchElement.HasExtensions() || (!string.IsNullOrEmpty(current.IfNoneMatchElement.ElementId))) { JsonStreamUtilities.SerializeExtensionList(writer, options, "_ifNoneMatch", false, current.IfNoneMatchElement.Extension, current.IfNoneMatchElement.ElementId); } } if (current.IfModifiedSinceElement != null) { if (current.IfModifiedSinceElement.Value != null) { writer.WriteString("ifModifiedSince", ((DateTimeOffset)current.IfModifiedSinceElement.Value).ToString("yyyy-MM-dd'T'HH:mm:ss.FFFFFFFK", System.Globalization.CultureInfo.InvariantCulture)); } if (current.IfModifiedSinceElement.HasExtensions() || (!string.IsNullOrEmpty(current.IfModifiedSinceElement.ElementId))) { JsonStreamUtilities.SerializeExtensionList(writer, options, "_ifModifiedSince", false, current.IfModifiedSinceElement.Extension, current.IfModifiedSinceElement.ElementId); } } if (current.IfMatchElement != null) { if (!string.IsNullOrEmpty(current.IfMatchElement.Value)) { writer.WriteString("ifMatch", current.IfMatchElement.Value); } if (current.IfMatchElement.HasExtensions() || (!string.IsNullOrEmpty(current.IfMatchElement.ElementId))) { JsonStreamUtilities.SerializeExtensionList(writer, options, "_ifMatch", false, current.IfMatchElement.Extension, current.IfMatchElement.ElementId); } } if (current.IfNoneExistElement != null) { if (!string.IsNullOrEmpty(current.IfNoneExistElement.Value)) { writer.WriteString("ifNoneExist", current.IfNoneExistElement.Value); } if (current.IfNoneExistElement.HasExtensions() || (!string.IsNullOrEmpty(current.IfNoneExistElement.ElementId))) { JsonStreamUtilities.SerializeExtensionList(writer, options, "_ifNoneExist", false, current.IfNoneExistElement.Extension, current.IfNoneExistElement.ElementId); } } if (includeStartObject) { writer.WriteEndObject(); } }