Esempio n. 1
0
        /// <summary>
        /// Try to deserialize the full resource represented by the specified <see cref="ArtifactSummary"/>.
        /// </summary>
        /// <param name="info">An <see cref="ArtifactSummary"/> instance.</param>
        /// <typeparam name="T">The expected resource type.</typeparam>
        /// <returns>A new instance of type <typeparamref name="T"/>, or <c>null</c>.</returns>
        private static T getResourceFromScannedSource <T>(ArtifactSummary info)
            where T : Resource
        {
            // File path of the containing resource file (could be a Bundle)
            var path = info.Origin;

            using (var navStream = DefaultNavigatorStreamFactory.Create(path))
            {
                // TODO: Handle exceptions & null return values
                // e.g. file may have been deleted/renamed since last scan

                // Advance stream to the target resource (e.g. specific Bundle entry)
                if (navStream != null && navStream.Seek(info.Position))
                {
                    // Create navigator for the target resource
                    var nav = navStream.Current;
                    if (nav != null)
                    {
                        // Parse target resource from navigator
                        var parser = new BaseFhirParser();
                        var result = parser.Parse <T>(nav);
                        if (result != null)
                        {
                            // Add origin annotation
                            result.SetOrigin(info.Origin);
                            return(result);
                        }
                    }
                }

                return(null);
            }
        }
Esempio n. 2
0
        public void TestLoadResourceFromZipStream()
        {
            // Harvest summaries and load artifact straight from core ZIP archive

            // Use XmlNavigatorStream to navigate resources stored inside a zip file
            // ZipDeflateStream does not support seeking (forward-only stream)
            // Therefore this only works for the XmlNavigatorStream, as the ctor does NOT (need to) call Reset()
            // JsonNavigatorStream cannot support zip streams; ctor needs to call Reset after scanning resourceType

            ArtifactSummary corePatientSummary;
            var             corePatientUrl = ModelInfo.CanonicalUriForFhirCoreType(FHIRDefinedType.Patient);
            string          zipEntryName   = "profiles-resources.xml";

            // Generate summaries from core ZIP resource definitions (extract in memory)
            using (var archive = ZipFile.Open(ZipSource.SpecificationZipFileName, ZipArchiveMode.Read))
            {
                var entry = archive.Entries.FirstOrDefault(e => e.Name == zipEntryName);
                Assert.IsNotNull(entry);

                using (var entryStream = entry.Open())
                    using (var navStream = new XmlNavigatorStream(entryStream))
                    {
                        var summaries = ArtifactSummaryGenerator.Default.Generate(navStream);
                        Assert.IsNotNull(summaries);
                        corePatientSummary = summaries.FindConformanceResources(corePatientUrl).FirstOrDefault();
                    }
            }

            Assert.IsNotNull(corePatientSummary);
            Assert.AreEqual(ResourceType.StructureDefinition, corePatientSummary.ResourceType);
            Assert.AreEqual(corePatientUrl, corePatientSummary.GetConformanceCanonicalUrl());

            // Load core Patient resource from ZIP (extract in memory)
            using (var archive = ZipFile.Open(ZipSource.SpecificationZipFileName, ZipArchiveMode.Read))
            {
                var entry = archive.Entries.FirstOrDefault(e => e.Name == zipEntryName);
                using (var entryStream = entry.Open())
                    using (var navStream = new XmlNavigatorStream(entryStream))
                    {
                        var nav = navStream.Current;
                        if (nav != null)
                        {
                            // Parse target resource from navigator
                            var parser      = new BaseFhirParser();
                            var corePatient = parser.Parse <StructureDefinition>(nav);
                            Assert.IsNotNull(corePatient);
                            Assert.AreEqual(corePatientUrl, corePatient.Url);
                        }
                    }
            }
        }
Esempio n. 3
0
        /// <summary>Returns <c>null</c> if the specified <paramref name="summary"/> equals <c>null</c>.</summary>
        T loadResourceInternal <T>(ArtifactSummary summary) where T : Resource
        {
            if (summary == null)
            {
                return(null);
            }

            // File path of the containing resource file (could be a Bundle)
            var origin = summary.Origin;

            if (string.IsNullOrEmpty(origin))
            {
                throw Error.Argument($"Cannot load resource from summary. The {nameof(ArtifactSummary.Origin)} information is empty or missing.");
            }

            var pos = summary.Position;

            if (string.IsNullOrEmpty(pos))
            {
                throw Error.Argument($"Cannot load resource from summary. The {nameof(ArtifactSummary.Position)} information is empty or missing.");
            }

            T result = null;

            using (var navStream = DefaultNavigatorStreamFactory.Create(origin))
            {
                // Handle exceptions & null return values?
                // e.g. file may have been deleted/renamed since last scan

                // Advance stream to the target resource (e.g. specific Bundle entry)
                if (navStream != null && navStream.Seek(pos))
                {
                    // Create navigator for the target resource
                    var nav = navStream.Current;
                    if (nav != null)
                    {
                        // Parse target resource from navigator
                        var parser = new BaseFhirParser();
                        result = parser.Parse <T>(nav);
                        // Add origin annotation
                        result?.SetOrigin(origin);
                    }
                }
            }

            return(result);
        }
Esempio n. 4
0
        public FhirClient(HttpClient httpClient, ResourceFormat format)
        {
            HttpClient = httpClient;
            _format    = format;

            if (format == ResourceFormat.Json)
            {
                var jsonSerializer = new FhirJsonSerializer();

                _serializer = jsonSerializer;
                _serialize  = (resource, summary) => jsonSerializer.SerializeToString(resource, summary);

                var jsonParser = new FhirJsonParser();

                _parser      = jsonParser;
                _deserialize = jsonParser.Parse <Resource>;

                _contentType = ContentType.JSON_CONTENT_HEADER;
            }
            else if (format == ResourceFormat.Xml)
            {
                var xmlSerializer = new FhirXmlSerializer();

                _serializer = xmlSerializer;
                _serialize  = (resource, summary) => xmlSerializer.SerializeToString(resource, summary);

                var xmlParser = new FhirXmlParser();

                _parser      = xmlParser;
                _deserialize = xmlParser.Parse <Resource>;

                _contentType = ContentType.XML_CONTENT_HEADER;
            }
            else
            {
                throw new InvalidOperationException("Unsupported format.");
            }

            _mediaType = MediaTypeWithQualityHeaderValue.Parse(_contentType);
            SetupAuthenticationAsync(TestApplications.ServiceClient).GetAwaiter().GetResult();
        }
Esempio n. 5
0
        private async Task <HttpResponseMessage> Upsert(string resourceType, HttpStatusCode statusCode)
        {
            try
            {
                string raw = await Request.Content.ReadAsStringAsync();

                BaseFhirParser parser = null;
                if (IsContentTypeJSON)
                {
                    parser = jsonparser;
                }
                else if (IsContentTypeXML)
                {
                    parser = xmlparser;
                }
                else
                {
                    throw new Exception("Invalid Content-Type must be application/fhir+json or application/fhir+xml");
                }
                var          reader = IsContentTypeJSON ? FhirJsonParser.CreateFhirReader(raw) : FhirXmlParser.CreateFhirReader(raw, false);
                var          p      = (Resource)parser.Parse(reader, FhirHelper.ResourceTypeFromString(resourceType));
                ResourceType rt;
                Enum.TryParse(resourceType, out rt);
                if (p.ResourceType != rt)
                {
                    OperationOutcome oo = new OperationOutcome();
                    oo.Issue = new System.Collections.Generic.List <OperationOutcome.IssueComponent>();
                    OperationOutcome.IssueComponent ic = new OperationOutcome.IssueComponent();
                    ic.Severity    = OperationOutcome.IssueSeverity.Error;
                    ic.Code        = OperationOutcome.IssueType.Exception;
                    ic.Diagnostics = "Resource provide is not of type " + resourceType;
                    oo.Issue.Add(ic);
                    var respconf = this.Request.CreateResponse(HttpStatusCode.BadRequest);
                    respconf.Content = new StringContent(SerializeResponse(oo), Encoding.UTF8, CurrentAcceptType);
                    return(respconf);
                }
                //Store resource regardless of type
                p = await ProcessSingleResource(p, resourceType, IsMatchVersionId);

                var response = this.Request.CreateResponse(statusCode);
                response.Headers.Add("Location", Request.RequestUri.AbsoluteUri + "/" + p.Id);
                response.Headers.Add("ETag", "W/\"" + p.Meta.VersionId + "\"");
                //Extract and Save each Resource in bundle if it's a batch type
                if (p.ResourceType == ResourceType.Bundle && ((Bundle)p).Type == Bundle.BundleType.Batch)
                {
                    Bundle source  = (Bundle)p;
                    Bundle results = new Bundle();
                    results.Id    = Guid.NewGuid().ToString();
                    results.Type  = Bundle.BundleType.Searchset;
                    results.Total = source.Entry.Count();
                    results.Link  = new System.Collections.Generic.List <Bundle.LinkComponent>();
                    results.Link.Add(new Bundle.LinkComponent()
                    {
                        Url = Request.RequestUri.AbsoluteUri, Relation = "original"
                    });
                    results.Entry = new System.Collections.Generic.List <Bundle.EntryComponent>();
                    foreach (Bundle.EntryComponent ec in source.Entry)
                    {
                        var rslt = await ProcessSingleResource(ec.Resource, Enum.GetName(typeof(Hl7.Fhir.Model.ResourceType), ec.Resource.ResourceType));

                        results.Entry.Add(new Bundle.EntryComponent()
                        {
                            Resource = rslt
                        });
                    }
                }
                return(response);
            }
            catch (Exception e)
            {
                OperationOutcome oo = new OperationOutcome();
                oo.Issue = new System.Collections.Generic.List <OperationOutcome.IssueComponent>();
                OperationOutcome.IssueComponent ic = new OperationOutcome.IssueComponent();
                ic.Severity    = OperationOutcome.IssueSeverity.Error;
                ic.Code        = OperationOutcome.IssueType.Exception;
                ic.Diagnostics = e.Message;
                oo.Issue.Add(ic);
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest);
                response.Content = new StringContent(SerializeResponse(oo), Encoding.UTF8, CurrentAcceptType);
                return(response);
            }
        }
Esempio n. 6
0
        private async Task <HttpResponseMessage> Upsert(string resourceType, string headerid = null)
        {
            try
            {
                string raw = await Request.Content.ReadAsStringAsync();

                BaseFhirParser parser = null;
                if (IsContentTypeJSON)
                {
                    parser = jsonparser;
                }
                else if (IsContentTypeXML)
                {
                    parser = xmlparser;
                }
                else
                {
                    throw new Exception("Invalid Content-Type must be application/fhir+json or application/fhir+xml");
                }
                var reader = IsContentTypeJSON ? FhirJsonParser.CreateFhirReader(raw) : FhirXmlParser.CreateFhirReader(raw, false);
                var p      = (Resource)parser.Parse(reader, FhirHelper.ResourceTypeFromString(resourceType));
                if (p.ResourceType != FhirHelper.GetResourceType(FhirHelper.ValidateResourceType(resourceType)))
                {
                    OperationOutcome oo = new OperationOutcome();
                    oo.Issue = new System.Collections.Generic.List <OperationOutcome.IssueComponent>();
                    OperationOutcome.IssueComponent ic = new OperationOutcome.IssueComponent();
                    ic.Severity    = OperationOutcome.IssueSeverity.Error;
                    ic.Code        = OperationOutcome.IssueType.Exception;
                    ic.Diagnostics = "Resource provided is not of type " + resourceType;
                    oo.Issue.Add(ic);
                    var respconf = this.Request.CreateResponse(HttpStatusCode.BadRequest);
                    respconf.Content = new StringContent(SerializeResponse(oo), Encoding.UTF8);
                    respconf.Content.Headers.LastModified = DateTimeOffset.Now;
                    respconf.Headers.TryAddWithoutValidation("Accept", CurrentAcceptType);
                    respconf.Content.Headers.TryAddWithoutValidation("Content-Type", IsAccceptTypeJSON ? FHIRCONTENTTYPEJSON : FHIRCONTENTTYPEXML);
                    return(respconf);
                }
                if (String.IsNullOrEmpty(p.Id) && headerid != null)
                {
                    p.Id = headerid;
                }
                //Store resource regardless of type
                var dbresp = await ProcessSingleResource(p, resourceType, IsMatchVersionId);

                p = dbresp.Resource;
                var response = this.Request.CreateResponse(dbresp.Response == 1 ? HttpStatusCode.Created : HttpStatusCode.OK);
                response.Content = new StringContent("", Encoding.UTF8);
                response.Content.Headers.LastModified = p.Meta.LastUpdated;
                response.Headers.Add("Location", Request.RequestUri.AbsoluteUri + (headerid == null ? "/" + p.Id :""));
                response.Headers.Add("ETag", "W/\"" + p.Meta.VersionId + "\"");

                //Extract and Save each Resource in bundle if it's a batch type
                if (p.ResourceType == ResourceType.Bundle && (((Bundle)p).Type == Bundle.BundleType.Batch || ((Bundle)p).Type == Bundle.BundleType.Message))
                {
                    Bundle source = (Bundle)p;

                    /*Bundle results = new Bundle();
                     * results.Id = Guid.NewGuid().ToString();
                     * results.Type = Bundle.BundleType.Searchset;
                     * results.Total = source.Entry.Count();
                     * results.Link = new System.Collections.Generic.List<Bundle.LinkComponent>();
                     * results.Link.Add(new Bundle.LinkComponent() { Url = Request.RequestUri.AbsoluteUri, Relation = "original" });
                     * results.Entry = new System.Collections.Generic.List<Bundle.EntryComponent>();*/
                    foreach (Bundle.EntryComponent ec in source.Entry)
                    {
                        var rslt = await ProcessSingleResource(ec.Resource, Enum.GetName(typeof(Hl7.Fhir.Model.ResourceType), ec.Resource.ResourceType));

                        //results.Entry.Add(new Bundle.EntryComponent() { Resource = rslt.Resource, FullUrl = FhirHelper.GetFullURL(Request, rslt.Resource) });
                    }
                }
                return(response);
            }
            catch (Exception e)
            {
                OperationOutcome oo = new OperationOutcome();
                oo.Issue = new System.Collections.Generic.List <OperationOutcome.IssueComponent>();
                OperationOutcome.IssueComponent ic = new OperationOutcome.IssueComponent();
                ic.Severity    = OperationOutcome.IssueSeverity.Error;
                ic.Code        = OperationOutcome.IssueType.Exception;
                ic.Diagnostics = e.Message;
                oo.Issue.Add(ic);
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest);
                response.Headers.TryAddWithoutValidation("Accept", CurrentAcceptType);
                response.Content = new StringContent(SerializeResponse(oo), Encoding.UTF8);
                response.Content.Headers.TryAddWithoutValidation("Content-Type", IsAccceptTypeJSON ? FHIRCONTENTTYPEJSON : FHIRCONTENTTYPEXML);
                response.Content.Headers.LastModified = DateTimeOffset.Now;
                return(response);
            }
        }