/// <summary> /// Invoke the process message operation /// </summary> public Resource Invoke(Parameters parameters) { // Extract the parameters var contentParameter = parameters.Parameter.Find(o => o.Name == "content")?.Resource as Bundle; var asyncParameter = parameters.Parameter.Find(o => o.Name == "async")?.Value as FhirBoolean; if (contentParameter == null) { this.m_tracer.TraceError("Missing content parameter"); throw new ArgumentNullException(m_localizationService.GetString("error.type.ArgumentNullException")); } else if (asyncParameter?.Value.GetValueOrDefault() == true) { this.m_tracer.TraceError("Asynchronous messaging is not supported by this repository"); throw new InvalidOperationException(m_localizationService.GetString("error.type.NotSupportedException")); } // Message must have a message header var messageHeader = contentParameter.Entry.Find(o => o.Resource.TryDeriveResourceType(out ResourceType rt) && rt == ResourceType.MessageHeader)?.Resource as MessageHeader; if (messageHeader == null) { this.m_tracer.TraceError("Message bundle does not contain a MessageHeader"); throw new ArgumentException(m_localizationService.GetString("error.type.ArgumentNullException")); } // Determine the appropriate action handler if (messageHeader.Event is FhirUri eventUri) { var handler = ExtensionUtil.GetMessageOperationHandler(new Uri(eventUri.Value)); if (handler == null) { this.m_tracer.TraceError($"There is no message handler for event {eventUri}"); throw new NotSupportedException(m_localizationService.GetString("error.type.NotSupportedException")); } var retVal = new Bundle(); // Return for operation retVal.Meta = new Meta() { LastUpdated = DateTimeOffset.Now }; var uuid = Guid.NewGuid(); try { // HACK: The .EndsWith is a total hack - FHIR wants .FullUrl to be absolute, but many senders will send relative references which var opReturn = handler.Invoke(messageHeader, contentParameter.Entry.Where(o => messageHeader.Focus.Any(f => o.FullUrl == f.Reference || $"{o.Resource.TypeName}/{o.Resource.Id}" == f.Reference)).ToArray()); retVal.Entry.Add(new Bundle.EntryComponent() { FullUrl = $"urn:uuid:{uuid}", Resource = new MessageHeader() { Id = uuid.ToString(), Response = new MessageHeader.ResponseComponent() { Code = MessageHeader.ResponseType.Ok, Details = new ResourceReference($"urn:uuid:{opReturn.Id}") } } }); // HACK: Another hack - FullUrl is assumed to be a UUID because I'm not turning an id of XXX and trying to derive a fullUrl for something that is in a // bundle anyways retVal.Entry.Add(new Bundle.EntryComponent() { FullUrl = $"urn:uuid:{opReturn.Id}", Resource = opReturn }); } catch (Exception e) { var outcome = DataTypeConverter.CreateErrorResult(e); outcome.Id = Guid.NewGuid().ToString(); retVal.Entry.Add(new Bundle.EntryComponent() { FullUrl = $"urn:uuid:{uuid}", Resource = new MessageHeader() { Id = uuid.ToString(), Response = new MessageHeader.ResponseComponent() { Code = MessageHeader.ResponseType.FatalError, Details = new ResourceReference($"urn:uuid:{outcome.Id}") } } }); retVal.Entry.Add(new Bundle.EntryComponent() { FullUrl = $"urn:uuid:{outcome.Id}", Resource = outcome }); throw new FhirException((System.Net.HttpStatusCode)FhirErrorEndpointBehavior.ClassifyErrorCode(e), retVal, m_localizationService.GetString("error.type.FhirException"), e); } finally { retVal.Timestamp = DateTime.Now; retVal.Type = Bundle.BundleType.Message; } return(retVal); } else { this.m_tracer.TraceError("Currently message headers with EventCoding are not supported"); throw new InvalidOperationException(m_localizationService.GetString("error.type.NotSupportedException.userMessage")); } }