예제 #1
0
        public async Task <IActionResult> ValidateById([FromRoute] string typeParameter, [FromRoute] string idParameter, [FromQuery] string profile)
        {
            Uri profileUri = GetProfile(profile);

            // Read resource from storage.
            RawResourceElement response = await _mediator.GetResourceAsync(new ResourceKey(typeParameter, idParameter), HttpContext.RequestAborted);

            // Convert it to fhir object.
            var resource = _resourceDeserializer.Deserialize(response);

            return(await RunValidationAsync(resource, profileUri));
        }
예제 #2
0
        public ResourceElement CreateSearchBundle(SearchResult result)
        {
            EnsureArg.IsNotNull(result, nameof(result));

            // Create the bundle from the result.
            var bundle = new Bundle();

            if (result != null)
            {
                IEnumerable <Bundle.EntryComponent> entries = result.Results.Select(r =>
                {
                    ResourceElement resource = _deserializer.Deserialize(r);

                    return(new Bundle.EntryComponent
                    {
                        FullUrlElement = new FhirUri(_urlResolver.ResolveResourceUrl(resource)),
                        Resource = resource.Instance.ToPoco <Resource>(),
                        Search = new Bundle.SearchComponent
                        {
                            // TODO: For now, everything returned is a match. We will need to
                            // distinct between match and include once we support it.
                            Mode = Bundle.SearchEntryMode.Match,
                        },
                    });
                });

                bundle.Entry.AddRange(entries);

                if (result.ContinuationToken != null)
                {
                    bundle.NextLink = _urlResolver.ResolveRouteUrl(
                        result.UnsupportedSearchParameters,
                        result.ContinuationToken);
                }
            }

            // Add the self link to indicate which search parameters were used.
            bundle.SelfLink = _urlResolver.ResolveRouteUrl(result.UnsupportedSearchParameters);

            bundle.Id    = _fhirRequestContextAccessor.FhirRequestContext.CorrelationId;
            bundle.Type  = Bundle.BundleType.Searchset;
            bundle.Total = result?.TotalCount;
            bundle.Meta  = new Meta
            {
                LastUpdated = Clock.UtcNow,
            };

            return(bundle.ToResourceElement());
        }
예제 #3
0
        public async Task <List <Tuple <string, string> > > GetGroupMembers(string groupId, DateTimeOffset groupMembershipTime, CancellationToken cancellationToken)
        {
            var groupResource = await _fhirDataStore.Value.GetAsync(new ResourceKey(KnownResourceTypes.Group, groupId), cancellationToken);

            if (groupResource == null)
            {
                throw new ResourceNotFoundException($"Group {groupId} was not found.");
            }

            var group         = _resourceDeserializer.Deserialize(groupResource);
            var groupContents = group.ToPoco <Group>().Member;

            var members = new List <Tuple <string, string> >();

            foreach (Group.MemberComponent member in groupContents)
            {
                var fhirGroupMembershipTime = new FhirDateTime(groupMembershipTime);
                if (
                    (member.Inactive == null ||
                     member.Inactive == false) &&
                    (member.Period?.EndElement == null ||
                     member.Period?.EndElement > fhirGroupMembershipTime) &&
                    (member.Period?.StartElement == null ||
                     member.Period?.StartElement < fhirGroupMembershipTime))
                {
                    var    element      = _referenceToElementResolver.Resolve(member.Entity.Reference);
                    string id           = (string)element.Children("id").First().Value;
                    string resourceType = element.InstanceType;

                    members.Add(Tuple.Create(id, resourceType));
                }
            }

            return(members);
        }
        private T GetResourceDefinition <T>(TagResourceReference resourceReference)
        {
            var tagResource = GetPageableResource(resourceReference).Resource;

            T result;

            byte[] resourceDefinitionData = tagResource.DefinitionData;
            ApplyResourceDefinitionFixups(tagResource, resourceDefinitionData);

            byte[] resourceRawData = GetResourceData(resourceReference);
            if (resourceRawData == null)
            {
                resourceRawData = new byte[0];
            }

            // deserialize the resource definition again
            using (var definitionDataStream = new MemoryStream(resourceDefinitionData))
                using (var definitionDataReader = new EndianReader(definitionDataStream, EndianFormat.LittleEndian))
                    using (var dataStream = new MemoryStream(resourceRawData))
                        using (var dataReader = new EndianReader(dataStream, EndianFormat.LittleEndian))
                        {
                            var context      = new ResourceDefinitionSerializationContext(dataReader, definitionDataReader, tagResource.DefinitionAddress.Type);
                            var deserializer = new ResourceDeserializer(Cache.Version);
                            // deserialize without access to the data
                            definitionDataReader.SeekTo(tagResource.DefinitionAddress.Offset);
                            result = deserializer.Deserialize <T>(context);
                        }
            return(result);
        }
예제 #5
0
        public void DeserializesHasManyRelationship()
        {
            var target = new ResourceDeserializer(_singleJson, typeof(Person));
            var result = target.Deserialize() as Person;

            var expectedFriend = _person.Friends.Single();
            var actualFriend   = result?.Friends.Single();

            Assert.Equal(expectedFriend.Identifier, actualFriend?.Identifier);
            Assert.Null(actualFriend?.FirstName);
            Assert.Null(actualFriend?.LastName);
            Assert.Equal(default(int?), actualFriend?.Age);
            Assert.Null(actualFriend?.Job);
            Assert.Null(actualFriend?.Friends);

            var expectedFamilyMembers = _person.FamilyMembers.ToArray();
            var actualFamilyMembers   = result?.FamilyMembers?.ToArray();

            Assert.NotNull(actualFamilyMembers);
            Assert.Equal(expectedFamilyMembers.Length, actualFamilyMembers.Length);
            expectedFamilyMembers.Zip(actualFamilyMembers, (expected, actual) =>
            {
                Assert.Equal(expected.Identifier, actual.Identifier);
                return(true);
            });
        }
예제 #6
0
        public void ValidatesTopLevelMemberExclusivity()
        {
            var content = FileAsJson("invalid-top-level.json");
            var target  = new ResourceDeserializer(content, typeof(Person));

            Assert.Throws <JsonApiException>(() => target.Deserialize());
        }
예제 #7
0
        public void ValidatesRootIsObject()
        {
            var content = FileAsJson("no-object-root.json");
            var target  = new ResourceDeserializer(content, typeof(Person));

            Assert.Throws <JsonApiException>(() => target.Deserialize());
        }
예제 #8
0
        public void ValidatesMutuallyExclusiveTopLevelMembers()
        {
            var content = FileAsJson("errors-and-data.json");
            var target  = new ResourceDeserializer(content, typeof(Person));

            Assert.Throws <JsonApiException>(() => target.Deserialize());
        }
예제 #9
0
        public void ValidatesNoIncludedWithoutData()
        {
            var content = FileAsJson("included-no-data.json");
            var target  = new ResourceDeserializer(content, typeof(Person));

            Assert.Throws <JsonApiException>(() => target.Deserialize());
        }
예제 #10
0
        public void ValidatesRequiredTopLevelMembers()
        {
            var content = FileAsJson("no-data-errors-meta.json");
            var target  = new ResourceDeserializer(content, typeof(Person));

            Assert.Throws <JsonApiException>(() => target.Deserialize());
        }
        public void GivenARawResourceOfUnknownType_WhenDeserializing_ThenANotSupportedExceptionIsThrown()
        {
            var raw     = new RawResource("{}", ResourceFormat.Unknown);
            var wrapper = new ResourceWrapper("id1", "version1", "Observation", raw, new ResourceRequest("http://fhir", HttpMethod.Post), Clock.UtcNow, false, null, null);

            Assert.Throws <NotSupportedException>(() => ResourceDeserializer.Deserialize(wrapper));
        }
예제 #12
0
        /// <summary>
        /// For each result in a batch of resources this will extract new search params
        /// Then compare those to the old values to determine if an update is needed
        /// Needed updates will be committed in a batch
        /// </summary>
        /// <param name="results">The resource batch to process</param>
        /// <param name="resourceTypeSearchParameterHashMap">Map of resource type to current hash value of the search parameters for that resource type</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>A Task</returns>
        public async Task ProcessSearchResultsAsync(SearchResult results, IReadOnlyDictionary <string, string> resourceTypeSearchParameterHashMap, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(results, nameof(results));
            EnsureArg.IsNotNull(resourceTypeSearchParameterHashMap, nameof(resourceTypeSearchParameterHashMap));

            var updateSearchIndices = new List <ResourceWrapper>();

            foreach (var entry in results.Results)
            {
                if (!resourceTypeSearchParameterHashMap.TryGetValue(entry.Resource.ResourceTypeName, out string searchParamHash))
                {
                    searchParamHash = string.Empty;
                }

                entry.Resource.SearchParameterHash = searchParamHash;
                var resourceElement = _deserializer.Deserialize(entry.Resource);
                var newIndices      = _searchIndexer.Extract(resourceElement);

                // TODO: If it reasonable to do so, we can compare
                // old and new search indices to avoid unnecessarily updating search indices
                // when not changes have been made.
                entry.Resource.UpdateSearchIndices(newIndices);
                updateSearchIndices.Add(entry.Resource);

                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }
            }

            using (IScoped <IFhirDataStore> store = _fhirDataStoreFactory())
            {
                await store.Value.UpdateSearchParameterIndicesBatchAsync(updateSearchIndices, cancellationToken);
            }
        }
예제 #13
0
        /// <summary>
        /// For each result in a batch of resources this will extract new search params
        /// Then compare those to the old values to determine if an update is needed
        /// Needed updates will be committed in a batch
        /// </summary>
        /// <param name="results">The resource batch to process</param>
        /// <param name="searchParamHash">the current hash value of the search parameters</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>A Task</returns>
        public async Task ProcessSearchResultsAsync(SearchResult results, string searchParamHash, CancellationToken cancellationToken)
        {
            var updateHashValueOnly = new List <ResourceWrapper>();
            var updateSearchIndices = new List <ResourceWrapper>();

            foreach (var entry in results.Results)
            {
                entry.Resource.SearchParameterHash = searchParamHash;
                var resourceElement = _deserializer.Deserialize(entry.Resource);
                var newIndices      = _searchIndexer.Extract(resourceElement);
                var newIndicesHash  = new HashSet <SearchIndexEntry>(newIndices);
                var prevIndicesHash = new HashSet <SearchIndexEntry>(entry.Resource.SearchIndices);

                if (newIndicesHash.SetEquals(prevIndicesHash))
                {
                    updateHashValueOnly.Add(entry.Resource);
                }
                else
                {
                    entry.Resource.UpdateSearchIndices(newIndices);
                    updateSearchIndices.Add(entry.Resource);
                }
            }

            using (IScoped <IFhirDataStore> store = _fhirDataStoreFactory())
            {
                await store.Value.UpdateSearchParameterHashBatchAsync(updateHashValueOnly, cancellationToken);

                await store.Value.UpdateSearchParameterIndicesBatchAsync(updateSearchIndices, cancellationToken);
            }
        }
예제 #14
0
        public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            EnsureArg.IsNotNull(selectedEncoding, nameof(selectedEncoding));

            context.HttpContext.AllowSynchronousIO();

            Resource resourceObject = null;

            if (typeof(RawResourceElement).IsAssignableFrom(context.ObjectType))
            {
                resourceObject = _deserializer.Deserialize(context.Object as RawResourceElement).ToPoco <Resource>();
            }
            else if (typeof(Hl7.Fhir.Model.Bundle).IsAssignableFrom(context.ObjectType))
            {
                // Need to set Resource property for resources in entries
                var bundle = context.Object as Hl7.Fhir.Model.Bundle;

                foreach (var entry in bundle.Entry.Where(x => x is RawBundleEntryComponent))
                {
                    var rawResource = entry as RawBundleEntryComponent;
                    entry.Resource = _deserializer.Deserialize(rawResource.ResourceElement).ToPoco <Resource>();
                }

                resourceObject = bundle;
            }
            else
            {
                resourceObject = (Resource)context.Object;
            }

            HttpResponse response = context.HttpContext.Response;

            using (TextWriter textWriter = context.WriterFactory(response.Body, selectedEncoding))
                using (var writer = new XmlTextWriter(textWriter))
                {
                    if (context.HttpContext.GetPrettyOrDefault())
                    {
                        writer.Formatting = Formatting.Indented;
                    }

                    _fhirXmlSerializer.Serialize(resourceObject, writer, context.HttpContext.GetSummaryTypeOrDefault(), elements: context.HttpContext.GetElementsOrDefault());
                }

            return(Task.CompletedTask);
        }
예제 #15
0
        public ResourceElement CreateSearchBundle(SearchResult result)
        {
            return(CreateBundle(result, Bundle.BundleType.Searchset, r =>
            {
                ResourceElement resource = _deserializer.Deserialize(r.Resource);

                return new Bundle.EntryComponent
                {
                    FullUrlElement = new FhirUri(_urlResolver.ResolveResourceUrl(resource)),
                    Resource = resource.Instance.ToPoco <Resource>(),
                    Search = new Bundle.SearchComponent
                    {
                        Mode = r.SearchEntryMode == SearchEntryMode.Match ? Bundle.SearchEntryMode.Match : Bundle.SearchEntryMode.Include,
                    },
                };
            }));
        }
예제 #16
0
        /// <summary>
        /// Converts json into an object of a specified type
        /// </summary>
        /// <param name="object">Json to convert</param>
        /// <param name="type">Type to convert to</param>
        /// <param name="config">The configuration to be used for deserialization</param>
        /// <returns>Json converted into the specified type of object</returns>
        public object Deserialize(JToken @object, Type type, JsonApiConfiguration config = null)
        {
            if (config == null)
            {
                config = new JsonApiConfiguration();
            }

            var target = new ResourceDeserializer(@object, type, config.PropertyNameConverter);
            return target.Deserialize();
        }
예제 #17
0
        public void DeserializesBelongsToRelationships()
        {
            var target = new ResourceDeserializer(_singleJson, typeof(Person));
            var result = target.Deserialize() as Person;
            var job    = result?.Job;

            Assert.Equal(_person.Job.Id, job?.Id);
            Assert.Null(job?.Name);
            Assert.Equal(0, job?.NumberOfEmployees);
        }
예제 #18
0
        public void DeserializesAttributes()
        {
            var target = new ResourceDeserializer(_singleJson, typeof(Person));
            var result = target.Deserialize() as Person;

            Assert.Equal(_person.Identifier, result?.Identifier);
            Assert.Equal(_person.FirstName, result?.FirstName);
            Assert.Equal(_person.LastName, result?.LastName);
            Assert.Equal(_person.Age, result?.Age);
        }
예제 #19
0
        public void DeserializesBelongsToRelationshipsWithNullData()
        {
            var person = JToken.Parse("{'data': {'relationships': {'job': {data: null}}}}");
            var target = new ResourceDeserializer(person, typeof(Person));
            var result = target.Deserialize() as Person;

            var job = result?.Job;

            Assert.Null(job);
        }
예제 #20
0
        public ResourceElement CreateSearchBundle(SearchResult result)
        {
            return(CreateBundle(result, Bundle.BundleType.Searchset, r =>
            {
                ResourceElement resource = _deserializer.Deserialize(r);

                return new Bundle.EntryComponent
                {
                    FullUrlElement = new FhirUri(_urlResolver.ResolveResourceUrl(resource)),
                    Resource = resource.Instance.ToPoco <Resource>(),
                    Search = new Bundle.SearchComponent
                    {
                        // TODO: For now, everything returned is a match. We will need to
                        // distinct between match and include once we support it.
                        Mode = Bundle.SearchEntryMode.Match,
                    },
                };
            }));
        }
예제 #21
0
        public void DeserializesEnumerables()
        {
            var target = new ResourceDeserializer(_collectionJson, typeof(Person[]));
            var result = target.Deserialize() as Person[];

            Assert.Equal(_people.Length, result?.Length);
            for (var i = 0; i < _people.Length; i++)
            {
                Assert.Equal(_people[i].Identifier, result?[i].Identifier);
            }
        }
예제 #22
0
        public void DeserializesWithoutId()
        {
            (_singleJson["data"] as JObject)?.Property("id").Remove();
            var target = new ResourceDeserializer(_singleJson, typeof(Person));
            var result = target.Deserialize() as Person;

            Assert.Equal(null, result?.Identifier);
            Assert.Equal(_person.FirstName, result?.FirstName);
            Assert.Equal(_person.LastName, result?.LastName);
            Assert.Equal(_person.Age, result?.Age);
        }
        public void GivenARawResource_WhenDeserializingFromJson_ThenTheObjectIsReturned()
        {
            var observation = Samples.GetDefaultObservation();

            observation.Id = "id1";
            var wrapper = new ResourceWrapper(observation, _rawResourceFactory.Create(observation), new ResourceRequest("http://fhir", HttpMethod.Post), false, null, null);

            var newObject = ResourceDeserializer.Deserialize(wrapper);

            Assert.Equal(observation.Id, newObject.Id);
            Assert.Equal(observation.VersionId, newObject.VersionId);
        }
예제 #24
0
        public Bundle CreateHistoryBundle(IEnumerable <Tuple <string, string> > unsupportedSearchParams, SearchResult result)
        {
            // Create the bundle from the result.
            var bundle = new Bundle();

            if (result != null)
            {
                IEnumerable <Bundle.EntryComponent> entries = result.Results.Select(r =>
                {
                    Resource resource = ResourceDeserializer.Deserialize(r);
                    var hasVerb       = Enum.TryParse(r.Request?.Method, true, out Bundle.HTTPVerb httpVerb);

                    return(new Bundle.EntryComponent
                    {
                        FullUrlElement = new FhirUri(_urlResolver.ResolveResourceUrl(resource, true)),
                        Resource = resource,
                        Request = new Bundle.RequestComponent
                        {
                            Method = hasVerb ? (Bundle.HTTPVerb?)httpVerb: null,
                            Url = r.Request?.Url?.ToString(),
                        },
                        Response = new Bundle.ResponseComponent
                        {
                            LastModified = r.LastModified,
                            Etag = WeakETag.FromVersionId(r.Version).ToString(),
                        },
                    });
                });

                bundle.Entry.AddRange(entries);

                if (result.ContinuationToken != null)
                {
                    bundle.NextLink = _urlResolver.ResolveRouteUrl(
                        _fhirRequestContextAccessor.FhirRequestContext.RouteName,
                        unsupportedSearchParams,
                        result.ContinuationToken);
                }
            }

            // Add the self link to indicate which search parameters were used.
            bundle.SelfLink = _urlResolver.ResolveRouteUrl(_fhirRequestContextAccessor.FhirRequestContext.RouteName, unsupportedSearchParams);

            bundle.Id    = _fhirRequestContextAccessor.FhirRequestContext.CorrelationId;
            bundle.Type  = Bundle.BundleType.History;
            bundle.Total = result?.TotalCount;
            bundle.Meta  = new Meta
            {
                LastUpdated = Clock.UtcNow,
            };

            return(bundle);
        }
예제 #25
0
        public void DeserializesHasManyRelationship()
        {
            var target = new ResourceDeserializer(_singleJson, typeof(Person));
            var result = target.Deserialize() as Person;

            var expected = _person.Friends.Single();
            var actual   = result?.Friends.Single();

            Assert.Equal(expected.Identifier, actual?.Identifier);
            Assert.Null(actual?.FirstName);
            Assert.Null(actual?.LastName);
            Assert.Equal(default(int?), actual?.Age);
            Assert.Null(actual?.Job);
            Assert.Null(actual?.Friends);
        }
예제 #26
0
        public void DeserializesCamelCase()
        {
            var camelCasePropertyNameConverter = new CamelCasePropertyNameConverter();

            var singleSerializer = new ResourceSerializer(
                _person, new PersonResource(), new Uri("http://example.com/people/1"),
                new DefaultUrlPathBuilder(), null, null, camelCasePropertyNameConverter);

            var singleJson = JToken.Parse(singleSerializer.Serialize().ToString());

            var target = new ResourceDeserializer(singleJson, typeof(Person), camelCasePropertyNameConverter);
            var result = target.Deserialize() as Person;

            Assert.Equal(_person.FirstName, result?.FirstName);
            Assert.Equal(_person.LastName, result?.LastName);
        }
        public async Task <SearchResourceResponse> Handle(SearchResourceRequest request, CancellationToken cancellationToken, RequestHandlerDelegate <SearchResourceResponse> next)
        {
            EnsureArg.IsNotNull(request, nameof(request));

            Tuple <string, string> listParameter = request.Queries
                                                   .FirstOrDefault(x => string.Equals(x.Item1, KnownQueryParameterNames.List, StringComparison.OrdinalIgnoreCase));

            // if _list was not requested, or _list was requested with invalid value, continue...
            if ((listParameter == null) || string.IsNullOrWhiteSpace(listParameter.Item2))
            {
                return(await next());
            }

            ResourceWrapper listWrapper =
                await _dataStore.Value.GetAsync(new ResourceKey <Hl7.Fhir.Model.List>(listParameter.Item2), cancellationToken);

            // wanted list was not found
            if (listWrapper == null)
            {
                return(CreateEmptySearchResponse(request));
            }

            ResourceElement list = _deserializer.Deserialize(listWrapper);
            IEnumerable <ReferenceSearchValue> references = list.ToPoco <Hl7.Fhir.Model.List>()
                                                            .Entry
                                                            .Where(x => x.Deleted != true)
                                                            .Select(x => _referenceSearchValueParser.Parse(x.Item.Reference))
                                                            .Where(x => string.IsNullOrWhiteSpace(request.ResourceType) ||
                                                                   string.Equals(request.ResourceType, x.ResourceType, StringComparison.Ordinal))
                                                            .ToArray();

            // the requested resource was not found in the list
            if (!references.Any())
            {
                return(CreateEmptySearchResponse(request));
            }

            // Remove the 'list' params from the queries, to be later replaced with specific ids of resources
            IEnumerable <Tuple <string, string> > query = request.Queries.Except(new[] { listParameter });

            query           = query.Concat(new[] { Tuple.Create(KnownQueryParameterNames.Id, string.Join(",", references.Select(x => x.ResourceId))) });
            request.Queries = query.ToArray();
            return(await next());
        }
예제 #28
0
        public async Task <PatchResourceResponse> Handle(PatchResourceRequest message, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(message, nameof(message));

            if (await AuthorizationService.CheckAccess(DataActions.Write, cancellationToken) != DataActions.Write)
            {
                throw new UnauthorizedFhirActionException();
            }

            var key = message.ResourceKey;

            if (!string.IsNullOrEmpty(key.VersionId))
            {
                throw new MethodNotAllowedException(Core.Resources.DeleteVersionNotAllowed);
            }

            ResourceWrapper currentDoc = await FhirDataStore.GetAsync(key, cancellationToken);

            if (currentDoc == null)
            {
                throw new ResourceNotFoundException(string.Format(Core.Resources.ResourceNotFoundById, key.ResourceType, key.Id));
            }

            ResourceElement resource         = _resourceDeserializer.Deserialize(currentDoc);
            Resource        resourceInstance = resource.Instance.ToPoco <Resource>();

            message.PatchDocument.ApplyTo(resourceInstance);

            ResourceWrapper resourceWrapper = CreateResourceWrapper(resourceInstance, deleted: false, keepMeta: true);
            bool            keepHistory     = await ConformanceProvider.Value.CanKeepHistory(currentDoc.ResourceTypeName, cancellationToken);

            UpsertOutcome result = await FhirDataStore.UpsertAsync(
                resourceWrapper,
                weakETag : message.WeakETag,
                allowCreate : false,
                keepHistory : keepHistory,
                cancellationToken : cancellationToken);

            resourceInstance.VersionId = result.Wrapper.Version;

            return(new PatchResourceResponse(new SaveOutcome(new RawResourceElement(result.Wrapper), result.OutcomeType)));
        }
예제 #29
0
        public async Task <GetResourceResponse> Handle(GetResourceRequest message, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(message, nameof(message));

            if (await AuthorizationService.CheckAccess(DataActions.Read) != DataActions.Read)
            {
                throw new UnauthorizedFhirActionException();
            }

            var key = message.ResourceKey;

            var currentDoc = await FhirDataStore.GetAsync(key, cancellationToken);

            if (currentDoc == null)
            {
                if (string.IsNullOrEmpty(key.VersionId))
                {
                    throw new ResourceNotFoundException(string.Format(Core.Resources.ResourceNotFoundById, key.ResourceType, key.Id));
                }
                else
                {
                    throw new ResourceNotFoundException(string.Format(Core.Resources.ResourceNotFoundByIdAndVersion, key.ResourceType, key.Id, key.VersionId));
                }
            }

            if (currentDoc.IsHistory &&
                ConformanceProvider != null &&
                await ConformanceProvider.Value.CanReadHistory(key.ResourceType, cancellationToken) == false)
            {
                throw new MethodNotAllowedException(string.Format(Core.Resources.ReadHistoryDisabled, key.ResourceType));
            }

            if (currentDoc.IsDeleted)
            {
                // As per FHIR Spec if the resource was marked as deleted on that version or the latest is marked as deleted then
                // we need to return a resource gone message.
                throw new ResourceGoneException(new ResourceKey(currentDoc.ResourceTypeName, currentDoc.ResourceId, currentDoc.Version));
            }

            return(new GetResourceResponse(_deserializer.Deserialize(currentDoc)));
        }
예제 #30
0
        public void GivenAResource_WhenCreatingAResourceWrapper_ThenMetaPropertiesAreCorrect()
        {
            var observation = Samples.GetDefaultObservation();

            observation.Id           = "id1";
            observation.VersionId    = "version1";
            observation.Meta.Profile = new List <string> {
                "test"
            };

            var lastModified = new DateTimeOffset(2017, 1, 1, 1, 1, 1, TimeSpan.Zero);

            using (Mock.Property(() => Clock.UtcNowFunc, () => lastModified))
            {
                var wrapper  = new ResourceWrapper(observation, _rawResourceFactory.Create(observation), new ResourceRequest("http://fhir", HttpMethod.Post), false, null, null, null);
                var resource = ResourceDeserializer.Deserialize(wrapper);

                Assert.Equal(observation.VersionId, resource.Meta.VersionId);
                Assert.Equal(lastModified, resource.Meta.LastUpdated);
                Assert.Equal("test", resource.Meta.Profile.First());
            }
        }