/// <summary> /// Searches a resource from the client registry datastore /// </summary> public Bundle SearchResource(string resourceType) { this.ThrowIfNotReady(); // Get the services from the service registry var auditService = ApplicationContext.Current.GetService(typeof(IAuditorService)) as IAuditorService; // Stuff for auditing and exception handling AuditData audit = null; List <IResultDetail> details = new List <IResultDetail>(); FhirQueryResult result = null; try { // Get query parameters var queryParameters = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters; var resourceProcessor = FhirResourceHandlerUtil.GetResourceHandler(resourceType); // Setup outgoing content WebOperationContext.Current.OutgoingRequest.Headers.Add("Last-Modified", DateTime.Now.ToString("ddd, dd MMM yyyy HH:mm:ss zzz")); if (resourceProcessor == null) // Unsupported resource { throw new FileNotFoundException(); } // TODO: Appropriately format response // Process incoming request result = resourceProcessor.Query(WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters); if (result == null || result.Outcome == ResultCode.Rejected) { throw new InvalidDataException("Message was rejected"); } else if (result.Outcome != ResultCode.Accepted) { throw new DataException("Query failed"); } audit = AuditUtil.CreateAuditData(result.Results); // Create the Atom feed return(MessageUtil.CreateBundle(result)); } catch (Exception e) { audit = AuditUtil.CreateAuditData(null); audit.Outcome = OutcomeIndicator.EpicFail; return(this.ErrorHelper(e, result, true) as Bundle); } finally { if (auditService != null) { auditService.SendAudit(audit); } } }
/// <summary> /// Get a resource's history /// </summary> public Bundle GetResourceInstanceHistory(string resourceType, string id, string mimeType) { this.ThrowIfNotReady(); FhirOperationResult readResult = null; try { readResult = this.PerformRead(resourceType, id, String.Empty); WebOperationContext.Current.OutgoingResponse.Headers.Remove("Content-Disposition"); return(MessageUtil.CreateBundle(readResult)); } catch (Exception e) { return(this.ErrorHelper(e, readResult, true) as Bundle); } }
/// <summary> /// Reads the complete history of the specified identifier /// </summary> public Bundle History(string id) { if (String.IsNullOrEmpty(id)) { this.m_traceSource.TraceError($"Argument {nameof(id)} null or empty"); throw new ArgumentNullException(this.m_localizationService.GetString("error.type.ArgumentNullException")); } Guid guidId = Guid.Empty; if (!Guid.TryParse(id, out guidId)) { throw new ArgumentException(this.m_localizationService.FormatString("error.type.ArgumentException", new { param = "id" })); } var result = this.Read(guidId, Guid.Empty); if (result == null) { throw new KeyNotFoundException(this.m_localizationService.GetString("error.type.KeyNotFoundException")); } // Results List <TModel> results = new List <TModel>() { result }; while ((result as IVersionedEntity)?.PreviousVersionKey.HasValue == true) { result = this.Read(guidId, (result as IVersionedEntity).PreviousVersionKey.Value); results.Add(result); } // FHIR Operation result var retVal = new FhirQueryResult(typeof(TFhirResource).Name) { Results = results.Select(this.MapToFhir).Select(o => new Bundle.EntryComponent() { Resource = o, Response = new Bundle.ResponseComponent() { Status = "200" } }).ToList() }; return(ExtensionUtil.ExecuteBeforeSendResponseBehavior(TypeRestfulInteraction.HistoryInstance, this.ResourceType, MessageUtil.CreateBundle(retVal, Bundle.BundleType.History)) as Bundle); }
/// <summary> /// Queries for a specified resource. /// </summary> /// <param name="parameters">The parameters.</param> /// <returns>Returns the FHIR query result containing the results of the query.</returns> /// <exception cref="System.ArgumentNullException">parameters</exception> public virtual Bundle Query(System.Collections.Specialized.NameValueCollection parameters) { if (parameters == null) { this.m_traceSource.TraceError($"Argument {nameof(parameters)} null or empty"); throw new ArgumentNullException(this.m_localizationService.GetString("error.type.ArgumentNullException")); } Core.Model.Query.NameValueCollection hdsiQuery = null; FhirQuery query = QueryRewriter.RewriteFhirQuery(typeof(TFhirResource), typeof(TModel), parameters, out hdsiQuery); // Do the query int totalResults = 0; var predicate = QueryExpressionParser.BuildLinqExpression <TModel>(hdsiQuery); var hdsiResults = this.Query(predicate, query.QueryId, query.Start, query.Quantity, out totalResults); var auth = AuthenticationContext.Current; // Return FHIR query result if (Environment.ProcessorCount > 4) { hdsiResults = hdsiResults.AsParallel().AsOrdered(); } var retVal = new FhirQueryResult(typeof(TFhirResource).Name) { Results = hdsiResults.Select(o => { using (AuthenticationContext.EnterContext(auth.Principal)) { return(new Bundle.EntryComponent() { Resource = this.MapToFhir(o), Search = new Bundle.SearchComponent() { Mode = Bundle.SearchEntryMode.Match } }); } }).ToList(), Query = query, TotalResults = totalResults }; this.ProcessIncludes(hdsiResults, parameters, retVal); return(ExtensionUtil.ExecuteBeforeSendResponseBehavior(TypeRestfulInteraction.SearchType, this.ResourceType, MessageUtil.CreateBundle(retVal, Bundle.BundleType.Searchset)) as Bundle); }
/// <summary> /// Throw an appropriate exception based on the caught exception /// </summary> private object ErrorHelper(Exception e, FhirOperationResult result, bool returnBundle) { if (result == null && returnBundle) { result = new FhirQueryResult() { Details = new List <IResultDetail>(), Query = new FhirQuery() { Start = 0, Quantity = 0 } } } ; else if (result == null) { result = new FhirOperationResult() { Details = new List <IResultDetail>() { new ResultDetail(ResultDetailType.Error, "No information available", e) } } } ; this.m_tracer.TraceEvent(TraceEventType.Error, 0, e.ToString()); result.Details.Add(new ResultDetail(ResultDetailType.Error, e.Message, e)); HttpStatusCode retCode = HttpStatusCode.OK; if (e is NotSupportedException) { retCode = System.Net.HttpStatusCode.MethodNotAllowed; } else if (e is NotImplementedException) { retCode = System.Net.HttpStatusCode.NotImplemented; } else if (e is InvalidDataException) { retCode = HttpStatusCode.BadRequest; } else if (e is FileLoadException) { retCode = System.Net.HttpStatusCode.Gone; } else if (e is FileNotFoundException || e is ArgumentException) { retCode = System.Net.HttpStatusCode.NotFound; } else if (e is ConstraintException) { retCode = (HttpStatusCode)422; } else { retCode = System.Net.HttpStatusCode.InternalServerError; } WebOperationContext.Current.OutgoingResponse.StatusCode = retCode; WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Xml; if (returnBundle) { throw new WebFaultException <Bundle>(MessageUtil.CreateBundle(result), retCode); } else { WebOperationContext.Current.OutgoingResponse.Headers.Add("Content-Disposition", "filename=\"error.xml\""); throw e; } //return MessageUtil.CreateOutcomeResource(result); }
/// <summary> /// Parameters /// </summary> public override Bundle Query(NameValueCollection parameters) { if (parameters == null) { this.m_tracer.TraceError(nameof(parameters)); throw new ArgumentNullException(nameof(parameters), this.m_localizationService.GetString("error.type.ArgumentNullException")); } Core.Model.Query.NameValueCollection hdsiQuery = null; var query = QueryRewriter.RewriteFhirQuery(typeof(Observation), typeof(Core.Model.Acts.Observation), parameters, out hdsiQuery); // Do the query var totalResults = 0; IEnumerable <Core.Model.Acts.Observation> hdsiResults = null; if (parameters["value-concept"] != null) { var predicate = QueryExpressionParser.BuildLinqExpression <CodedObservation>(hdsiQuery); hdsiResults = this.QueryEx(predicate, query.QueryId, query.Start, query.Quantity, out totalResults).OfType <Core.Model.Acts.Observation>(); } else if (parameters["value-quantity"] != null) { var predicate = QueryExpressionParser.BuildLinqExpression <QuantityObservation>(hdsiQuery); hdsiResults = this.QueryEx(predicate, query.QueryId, query.Start, query.Quantity, out totalResults).OfType <Core.Model.Acts.Observation>(); } else { var predicate = QueryExpressionParser.BuildLinqExpression <Core.Model.Acts.Observation>(hdsiQuery); hdsiResults = this.Query(predicate, query.QueryId, query.Start, query.Quantity, out totalResults); } // Return FHIR query result var retVal = new FhirQueryResult("Observation") { Results = hdsiResults.Select(this.MapToFhir).Select(o => new Bundle.EntryComponent { Resource = o, Search = new Bundle.SearchComponent { Mode = Bundle.SearchEntryMode.Match } }).ToList(), Query = query, TotalResults = totalResults }; base.ProcessIncludes(hdsiResults, parameters, retVal); return(ExtensionUtil.ExecuteBeforeSendResponseBehavior(TypeRestfulInteraction.SearchType, this.ResourceType, MessageUtil.CreateBundle(retVal, Bundle.BundleType.Searchset)) as Bundle); }