Esempio n. 1
0
        public async Task <BundleModel> GetSearchBundleModel(IList <ResourceStore> ResourceStoreList, Bug.Common.Enums.FhirVersion fhirVersion)
        {
            var IServiceBaseUrl = await IServiceBaseUrlCache.GetPrimaryAsync(fhirVersion);

            //Construct the History Bundle
            var BundleModel = new BundleModel(BundleType.Searchset)
            {
                Total = ResourceStoreList.Count
            };

            BundleModel.Entry = new List <BundleModel.EntryComponent>();
            foreach (var ResourceStore in ResourceStoreList)
            {
                var entry = new BundleModel.EntryComponent
                {
                    FullUrl = new Uri($"{IServiceBaseUrl.Url}/{ResourceStore.ResourceId}")
                };
                BundleModel.Entry.Add(entry);
                if (ResourceStore.ResourceBlob is object)
                {
                    entry.Resource = IFhirResourceParseJsonService.ParseJson(ResourceStore.FhirVersionId, IGZipper.Decompress(ResourceStore.ResourceBlob));
                }
            }
            return(BundleModel);
        }
        public async Task <List <Expression <Func <IndexReference, bool> > > > ReferenceIndex(SearchQueryReference SearchQueryReference)
        {
            //var ResourceStorePredicate = LinqKit.PredicateBuilder.New<ResourceStore>(true);
            var ResultList = new List <Expression <Func <IndexReference, bool> > >();

            //Improved Query when searching for ResourceIds for the same ResourceType and search parameter yet different ResourceIds.
            //It creates a SQL 'IN' cause instead of many 'OR' statements and should be more efficient.
            //Heavily used in chain searching where we traverse many References.
            //The 'Type' modifier is already resolved when the search parameter is parsed, so the SearchValue.FhirRequestUri.ResourseName is the correct Resource name at this stage
            if (SearchQueryReference.ValueList.Count > 1 && SearchQueryReference.ValueList.TrueForAll(x =>
                                                                                                      !x.IsMissing &&
                                                                                                      x.FhirUri !.IsRelativeToServer &&
                                                                                                      x.FhirUri.ResourseName == SearchQueryReference.ValueList[0].FhirUri !.ResourseName &&
                                                                                                      string.IsNullOrWhiteSpace(x.FhirUri.VersionId)))
            {
                Common.Interfaces.DomainModel.IServiceBaseUrl PrimaryServiceBaseUrl = await IServiceBaseUrlCache.GetPrimaryAsync(SearchQueryReference.FhirVersionId);

                var      QuickIndexReferencePredicate = LinqKit.PredicateBuilder.New <IndexReference>(true);
                string[] ReferenceFhirIdArray         = SearchQueryReference.ValueList.Select(x => x.FhirUri !.ResourceId).ToArray();
                QuickIndexReferencePredicate = QuickIndexReferencePredicate.And(IsSearchParameterId(SearchQueryReference.Id));
                QuickIndexReferencePredicate = QuickIndexReferencePredicate.And(EqualTo_ByKey_Many_ResourceIds(PrimaryServiceBaseUrl.Id,
                                                                                                               SearchQueryReference.ValueList[0].FhirUri !.ResourseName,
                                                                                                               ReferenceFhirIdArray,
                                                                                                               SearchQueryReference.ValueList[0].FhirUri !.VersionId));
                ResultList.Add(QuickIndexReferencePredicate);
                //ResourceStorePredicate = ResourceStorePredicate.Or(AnyIndex(QuickIndexReferencePredicate));
                return(ResultList);
            }

            foreach (SearchQueryReferenceValue ReferenceValue in SearchQueryReference.ValueList)
            {
                var IndexReferencePredicate = LinqKit.PredicateBuilder.New <IndexReference>(true);
                IndexReferencePredicate = IndexReferencePredicate.And(IsSearchParameterId(SearchQueryReference.Id));

                if (!SearchQueryReference.Modifier.HasValue)
                {
                    if (ReferenceValue.FhirUri is object)
                    {
                        if (ReferenceValue.FhirUri.IsRelativeToServer)
                        {
                            Common.Interfaces.DomainModel.IServiceBaseUrl PrimaryServiceBaseUrl = await IServiceBaseUrlCache.GetPrimaryAsync(SearchQueryReference.FhirVersionId);

                            IndexReferencePredicate = IndexReferencePredicate.And(EqualTo_ByKey(PrimaryServiceBaseUrl.Id, ReferenceValue.FhirUri.ResourseName, ReferenceValue.FhirUri.ResourceId, ReferenceValue.FhirUri.VersionId));
                            ResultList.Add(IndexReferencePredicate);
                            //ResourceStorePredicate = ResourceStorePredicate.Or(AnyIndex(IndexReferencePredicate));
                        }
                        else
                        {
                            IndexReferencePredicate = IndexReferencePredicate.And(EqualTo_ByUrlString(ReferenceValue.FhirUri.PrimaryServiceRootRemote !.OriginalString, ReferenceValue.FhirUri.ResourseName, ReferenceValue.FhirUri.ResourceId, ReferenceValue.FhirUri.VersionId));
                            ResultList.Add(IndexReferencePredicate);
                            //ResourceStorePredicate = ResourceStorePredicate.Or(AnyIndex(IndexReferencePredicate));
                        }
                    }
                    else
                    {
                        throw new ArgumentNullException(nameof(ReferenceValue.FhirUri));
                    }
                }
                else
                {
                    var ArrayOfSupportedModifiers = Common.FhirTools.SearchQuery.SearchQuerySupport.GetModifiersForSearchType(SearchQueryReference.SearchParamTypeId);
                    if (ArrayOfSupportedModifiers.Contains(SearchQueryReference.Modifier.Value))
                    {
                        switch (SearchQueryReference.Modifier.Value)
                        {
                        case SearchModifierCode.Missing:
                            IndexReferencePredicate = IndexReferencePredicate.And(IsNotSearchParameterId(SearchQueryReference.Id));
                            ResultList.Add(IndexReferencePredicate);
                            //ResourceStorePredicate = ResourceStorePredicate.Or(AnyIndexEquals(IndexReferencePredicate, !ReferenceValue.IsMissing));
                            break;

                        default:
                            throw new ApplicationException($"Internal Server Error: The search query modifier: {SearchQueryReference.Modifier.Value.GetCode()} has been added to the supported list for {SearchQueryReference.SearchParamTypeId.GetCode()} search parameter queries and yet no database predicate has been provided.");
                        }
                    }
                    else
                    {
                        throw new ApplicationException($"Internal Server Error: The search query modifier: {SearchQueryReference.Modifier.Value.GetCode()} is not supported for search parameter types of {SearchQueryReference.SearchParamTypeId.GetCode()}.");
                    }
                }
            }
            return(ResultList);
        }
Esempio n. 3
0
        public async Task <ReferentialIntegrityOutcome> CheckOnCommit(Common.Enums.FhirVersion fhirVersion, List <Bug.Common.Dto.Indexing.IndexReference> IndexReferenceList)
        {
            var Outcome = new ReferentialIntegrityOutcome();

            List <string> ErrorMessageList      = new List <string>();
            var           PrimaryServiceBaseUrl = await IServiceBaseUrlCache.GetPrimaryAsync(fhirVersion);

            foreach (var Index in IndexReferenceList.Where(x => x.ServiceBaseUrlId == PrimaryServiceBaseUrl.Id))
            {
                if (!Index.ServiceBaseUrlId.HasValue)
                {
                    throw new ArgumentNullException(nameof(Index.ServiceBaseUrlId));
                }
                if (!Index.ResourceTypeId.HasValue)
                {
                    throw new ArgumentNullException(nameof(Index.ResourceTypeId));
                }
                if (string.IsNullOrWhiteSpace(Index.ResourceId))
                {
                    throw new ArgumentNullException(nameof(Index.ResourceId));
                }

                string Ref = $"{Index.ResourceTypeId.GetCode()}/{Index.ResourceId}";
                if (!string.IsNullOrWhiteSpace(Index.VersionId))
                {
                    Ref += $"/_history/{Index.VersionId}";
                }
                else if (!string.IsNullOrWhiteSpace(Index.CanonicalVersionId))
                {
                    Ref += $"|{Index.CanonicalVersionId}";
                }

                bool HasIntegerVersionError = false;
                int? IntegerVersionId       = null;

                if (!string.IsNullOrWhiteSpace(Index.VersionId))
                {
                    if (!int.TryParse(Index.VersionId, out int IntegerVersionIdTest))
                    {
                        HasIntegerVersionError = true;
                        ErrorMessageList.Add($"The submitted resource contained a resource reference relative to this server which has a resource version part that is not an integer. All resources in this server must have an integer version therefore this resource reference must be invalid. The reference found was: {Ref} .");
                    }
                    else
                    {
                        IntegerVersionId = IntegerVersionIdTest;
                    }
                }

                if (IEnforceResourceReferentialIntegrity.EnforceRelativeResourceReferentialIntegrity && !HasIntegerVersionError)
                {
                    if (!await IResourceStoreRepository.ReferentialIntegrityCheckAsync(fhirVersion, Index.ResourceTypeId.Value, Index.ResourceId, IntegerVersionId))
                    {
                        ErrorMessageList.Add($"Enforce relative resource referential integrity is turned on for this server. The submitted resource contained a resource reference of: {Ref} which does not exist in the server.");
                    }
                }
            }
            if (ErrorMessageList.Count > 0)
            //Remove duplicates with Distinct() because the same reference can be reported twice
            //or more as it can have many search parameters pointing to the same reference
            {
                Outcome.IsError      = true;
                Outcome.FhirResource = IOperationOutcomeSupport.GetError(fhirVersion, ErrorMessageList.Distinct().ToArray());
            }

            return(Outcome);
        }
Esempio n. 4
0
        public async Task AddLocationAsync(Dictionary <string, StringValues> Headers, FhirVersion fhirVersion, string scheme, string resourceId, int versionId)
        {
            var ServiceBaseUrl = await IServiceBaseUrlCache.GetPrimaryAsync(fhirVersion);

            Headers.Add(HeaderNames.Location, $"{scheme}://{ServiceBaseUrl.Url}/{resourceId}/_history/{versionId.ToString()}");
        }