public PyroSearchParameters GetSearchParameters(string Compartment, string CompartmentId, string ResourceName)
        {
            //I need to check that Compartment and ResourceName are actual FHIR Resource Types, the two lines
            //below do that and throw Pyro Exception if they are not.
            FHIRAllTypes CompartmentType  = ResourceNameResolutionSupport.GetResourceFhirAllType(Compartment);
            FHIRAllTypes ResourceNameType = ResourceNameResolutionSupport.GetResourceFhirAllType(ResourceName);

            //Now to contruct the Container search parameters, these are cached from the database Conatiner Resource
            DtoServiceCompartmentResourceCached ServiceCompartmentResource = IServiceCompartmentCache.GetServiceCompartmentResourceForCompartmentCodeAndResource(Compartment, ResourceName);
            string ConatinerSerachString = string.Empty;

            if (ServiceCompartmentResource != null)
            {
                var CompartmentParamQuery = new List <string>();
                foreach (var CompartmentSearchParameter in ServiceCompartmentResource.ParamList)
                {
                    if (CompartmentSearchParameter.Param == "*")
                    {
                        // if the param="*" then all instances of this Resource Type are in the container and there are no
                        // actualy parameters that it needs to be restricted by. So the ConatinerSerachString remains as empty string.
                        break;
                    }
                    else
                    {
                        CompartmentParamQuery.Add($"{CompartmentSearchParameter.Param}:{Compartment}={CompartmentId}");
                    }
                }
                ConatinerSerachString = String.Join("&", CompartmentParamQuery.ToArray());
            }
            else
            {
                DtoServiceCompartmentCached ServiceCompartment = IServiceCompartmentCache.GetServiceCompartmentForCompartmentCode(Compartment);
                if (ServiceCompartment == null)
                {
                    string Message = $"No active {Compartment} Compartment exist in this server. Perhaps you could create one using a {FHIRAllTypes.CompartmentDefinition.GetLiteral()} resource and the resource instance ${Pyro.Common.Enum.FhirOperationEnum.OperationType.xSetCompartmentActive} Operation. " +
                                     $"For example: '[base]/{FHIRAllTypes.CompartmentDefinition.GetLiteral()}/[id]/${Pyro.Common.Enum.FhirOperationEnum.OperationType.xSetCompartmentActive}' ";
                    var OpOutcome = FhirOperationOutcomeSupport.Create(OperationOutcome.IssueSeverity.Fatal, OperationOutcome.IssueType.NotSupported, Message);
                    throw new PyroException(System.Net.HttpStatusCode.BadRequest, OpOutcome, Message);
                }
                else
                {
                    string Message   = $"The {Compartment} Compartment defined by the {FHIRAllTypes.CompartmentDefinition.GetLiteral()} with the resource id of '{ServiceCompartment.CompartmentDefinitionResourceId}' does not allow access to any {ResourceName} resource type instances.";
                    var    OpOutcome = FhirOperationOutcomeSupport.Create(OperationOutcome.IssueSeverity.Fatal, OperationOutcome.IssueType.NotSupported, Message);
                    throw new PyroException(System.Net.HttpStatusCode.BadRequest, OpOutcome, Message);
                }
            }

            ISearchParameterGeneric         ContainerSearchParameterGeneric = ISearchParameterGenericFactory.CreateDtoSearchParameterGeneric().Parse(ConatinerSerachString);
            ISearchParameterService         SearchService = ISearchParameterServiceFactory.CreateSearchParameterService();
            ISearchParametersServiceOutcome ContainerSearchParametersServiceOutcome = SearchService.ProcessSearchParameters(ContainerSearchParameterGeneric, SearchParameterService.SearchParameterServiceType.Resource, ResourceNameType, null);

            return(ContainerSearchParametersServiceOutcome.SearchParameters);
        }
Пример #2
0
        private string ResolveRelativeUriPart(string RequestRelativePath)
        {
            if (RequestRelativePath == string.Empty)
            {
                return(string.Empty);
            }

            string Remainder  = string.Empty;
            var    SplitParts = RequestRelativePath.Split('?')[0].Split('/');

            foreach (string Segment in SplitParts)
            {
                if (Segment.StartsWith("$"))
                {
                    //It is a base operation
                    this.OperationType = FhirOperationEnum.OperationScope.Base;
                    this.OperationName = Segment.TrimStart('$');
                    return(RequestRelativePath.Substring(this.OperationName.Count() + 1, RequestRelativePath.Count() - (this.OperationName.Count() + 1)));
                }
                else if (Segment.StartsWith("#"))
                {
                    //It is a contained referance with out a resource name e.g (#123456) and not (Patient/#123456)
                    this.IsContained        = true;
                    this.IsRelativeToServer = false;
                    this.ResourceId         = Segment.TrimStart('#');
                    return(RequestRelativePath.Substring(this.ResourceId.Count() + 1, RequestRelativePath.Count() - (this.ResourceId.Count() + 1)));
                }
                else if (Segment.ToLower() == _MetadataName)
                {
                    //This is a metadata request
                    this.IsMetaData = true;
                    Remainder       = RequestRelativePath.Substring(_MetadataName.Count(), RequestRelativePath.Count() - _MetadataName.Count());
                    return(RemoveStartsWithSlash(Remainder));
                }
                else if (SplitParts.Count() > 1 || this.OriginalString.Contains('/'))
                {
                    //This is a Resource referance where Patient/123456
                    this.ResourseName = Segment;
                    this.ResourceType = ResourceNameResolutionSupport.GetResourceType(this.ResourseName);
                    Remainder         = RequestRelativePath.Substring(this.ResourseName.Count(), RequestRelativePath.Count() - this.ResourseName.Count());
                    return(RemoveStartsWithSlash(Remainder));
                }
                else if (SplitParts.Count() == 1)
                {
                    return(Segment);
                }
            }
            ParseErrorMessage = $"The URI has no Resource or metadata or $Operation or #Contained segment. Found invalid segment: {RequestRelativePath} in URL {this.OriginalString}";
            ErrorInParseing   = true;
            return(string.Empty);
        }
Пример #3
0
        private string ResolveResourceIdPart(string value)
        {
            string Remainder = value;

            if (value == string.Empty)
            {
                return(value);
            }
            else
            {
                var Split = value.Split('/');
                foreach (string Segment in Split)
                {
                    if (this.ResourceId == null)
                    {
                        //Resource Id
                        if (Segment.StartsWith("#"))
                        {
                            //Contained Resource #Id
                            this.IsContained        = true;
                            this.IsRelativeToServer = false;
                            this.ResourceId         = Segment.TrimStart('#');
                            Remainder = RemoveStartsWithSlash(Remainder.Substring(this.ResourceId.Count() + 1, Remainder.Count() - (this.ResourceId.Count() + 1)));
                        }
                        else if (Segment.ToLower() == _SearchFormDataName)
                        {
                            //Search Form Data
                            this.IsFormDataSearch = true;
                            Remainder             = RemoveStartsWithSlash(Remainder.Substring(_SearchFormDataName.Count(), Remainder.Count() - _SearchFormDataName.Count()));
                            //Must not be anything after _search, the search parameters are in the body.
                            break;
                        }
                        else if (!this.IsOperation && Segment.StartsWith("$"))
                        {
                            //A Resource $operation e.g (base/Patient/$operation)
                            this.OperationType = FhirOperationEnum.OperationScope.Resource;
                            this.OperationName = Segment.TrimStart('$');
                            Remainder          = RemoveStartsWithSlash(Remainder.Substring(this.OperationName.Count() + 1, Remainder.Count() - (this.OperationName.Count() + 1)));
                            return(Remainder);
                        }
                        else
                        {
                            //Normal Resource Id
                            this.ResourceId = Segment;
                            Remainder       = RemoveStartsWithSlash(Remainder.Substring(this.ResourceId.Count(), Remainder.Count() - this.ResourceId.Count()));
                        }
                    }
                    else
                    {
                        if (!this.IsOperation && this.ResourceId != null && Segment.StartsWith("$"))
                        {
                            //A Resource Instance $operation e.g (base/Patient/10/$operation)
                            this.OperationType = FhirOperationEnum.OperationScope.Instance;
                            this.OperationName = Segment.TrimStart('$');
                            Remainder          = RemoveStartsWithSlash(Remainder.Substring(this.OperationName.Count() + 1, Remainder.Count() - (this.OperationName.Count() + 1)));
                            return(Remainder);
                        }
                        else if (Segment.ToLower() == _HistoryName)
                        {
                            //History segment e.g (_history)
                            //Is this case iterate over loop again to see is we have a Resource VersionId
                            this.IsHistoryReferance = true;
                            Remainder = RemoveStartsWithSlash(Remainder.Substring(_HistoryName.Count(), Remainder.Count() - _HistoryName.Count()));
                        }
                        else if (this.IsHistoryReferance)
                        {
                            //History version id
                            this.VersionId = Segment;
                            Remainder      = RemoveStartsWithSlash(Remainder.Substring(this.VersionId.Count(), Remainder.Count() - this.VersionId.Count()));
                            return(Remainder);
                        }
                        else if (IsResourceTypeString(Segment))
                        {
                            //Is this a Compartment reference e.g ([base]/Patient/[id]/Condition?code:in=http://hspc.org/ValueSet/acute-concerns)
                            //where 'Patient' is the compartment and 'Condition' is the resource.
                            this.CompartmentalisedResourseName = Segment;
                            this.CompartmentalisedResourseType = ResourceNameResolutionSupport.GetResourceType(this.ResourseName);
                            this.IsCompartment = true;
                            Remainder          = RemoveStartsWithSlash(Remainder.Substring(this.CompartmentalisedResourseName.Count(), Remainder.Count() - this.CompartmentalisedResourseName.Count()));
                            return(Remainder);
                        }
                    }
                }
                return(Remainder);
            }
        }
Пример #4
0
        private string ResolveRelativeUriPart(string RequestRelativePath)
        {
            if (RequestRelativePath == string.Empty)
            {
                return(string.Empty);
            }

            string Remainder  = string.Empty;
            var    SplitParts = RequestRelativePath.Split('?')[0].Split('/');

            foreach (string Segment in SplitParts)
            {
                if (Segment.StartsWith("$"))
                {
                    //It is a base operation
                    this.OperationType = FhirOperationEnum.OperationScope.Base;
                    this.OperationName = Segment.TrimStart('$');
                    return(RequestRelativePath.Substring(this.OperationName.Count() + 1, RequestRelativePath.Count() - (this.OperationName.Count() + 1)));
                }
                else if (Segment.StartsWith("#"))
                {
                    //It is a contained referance with out a resource name e.g (#123456) and not (Patient/#123456)
                    this.IsContained        = true;
                    this.IsRelativeToServer = false;
                    this.ResourceId         = Segment.TrimStart('#');
                    return(RequestRelativePath.Substring(this.ResourceId.Count() + 1, RequestRelativePath.Count() - (this.ResourceId.Count() + 1)));
                }
                else if (Segment.ToLower() == _MetadataName)
                {
                    //This is a metadata request
                    this.IsMetaData = true;
                    Remainder       = RequestRelativePath.Substring(_MetadataName.Count(), RequestRelativePath.Count() - _MetadataName.Count());
                    return(RemoveStartsWithSlash(Remainder));
                }
                else
                {
                    //This is a Resource referance
                    this.ResourseName = Segment;
                    this.ResourceType = ResourceNameResolutionSupport.GetResourceType(this.ResourseName);
                    Remainder         = RequestRelativePath.Substring(this.ResourseName.Count(), RequestRelativePath.Count() - this.ResourseName.Count());
                    return(RemoveStartsWithSlash(Remainder));

                    //Changed this to above which only calls 'ResourceNameResolutionSupport.GetResourceType'
                    //which will throw an exception if not a Resource type, that exception also
                    //provides detailed user info about the failure.

                    //if (IsResourceTypeString(Segment))
                    //{
                    //  this.ResourseName = Segment;
                    //  this.ResourceType = ResourceNameResolutionSupport.GetResourceType(this.ResourseName);
                    //  Remainder = RequestRelativePath.Substring(this.ResourseName.Count(), RequestRelativePath.Count() - this.ResourseName.Count());
                    //  return RemoveStartsWithSlash(Remainder);
                    //}
                    //else
                    //{
                    //  ParseErrorMessage = $"The URI has no Resource or metadata or $Operation or #Contained or Compartment segment or does not begin with http:// or https://. Found invalid segment: {Segment} in URL: {this.OriginalString}";
                    //  ErrorInParseing = true;
                    //  return string.Empty;
                    //}
                }
            }
            ParseErrorMessage = $"The URI has no Resource or metadata or $Operation or #Contained segment. Found invalid segment: {RequestRelativePath} in URL {this.OriginalString}";
            ErrorInParseing   = true;
            return(string.Empty);
        }
Пример #5
0
        private List <DtoResource> GetIncludes(List <SearchParameterInclude> IncludeList, List <DtoResource> CurrentScourceResourceList, HashSet <string> CacheResourceIDsAlreadyCollected)
        {
            var ReturnResourceList = new List <DtoResource>();

            if (IncludeList == null || IncludeList.Count == 0)
            {
                return(ReturnResourceList);
            }

            if (CurrentScourceResourceList == null || CurrentScourceResourceList.Count == 0)
            {
                return(ReturnResourceList);
            }

            foreach (var Resource in CurrentScourceResourceList)
            {
                //Now process each include
                foreach (var include in IncludeList)
                {
                    if (Resource.ResourceType.Value == include.SourceResourceType)
                    {
                        IResourceRepository = IRepositorySwitcher.GetRepository(Resource.ResourceType.Value);

                        //We only want to get the include target Resources
                        if (include.SearchParameterTargetResourceType.HasValue)
                        {
                            //Get the Search parameter Ids where the search parameter target list can contain the include's Resource target type
                            int[] IdArray = include.SearchParameterList.Where(z => z.TargetResourceTypeList.Any(c => c.ResourceType.GetLiteral() == include.SearchParameterTargetResourceType.Value.GetLiteral())).Select(x => x.Id).ToArray();
                            //Now only get the FhirId of the resources that have Search Index References that have these include target resource
                            string[] FhirIdList = IResourceRepository.GetResourceFhirIdByResourceIdAndIndexReferance(Resource.Id, IdArray, include.SearchParameterTargetResourceType.Value.GetLiteral());
                            //Set the repository to the include's target resource in order to get the include resources
                            IResourceRepository = IRepositorySwitcher.GetRepository(include.SearchParameterTargetResourceType.Value);
                            //Get each as long as it is not already gotten based on CacheResourceIDsAlreadyCollected list
                            foreach (string FhirId in FhirIdList)
                            {
                                AddIncludeResourceInstanceForIncludes(ReturnResourceList, CacheResourceIDsAlreadyCollected, FhirId);
                            }
                        }
                        else
                        {
                            //There is no include target so try and get all
                            foreach (var IncludeItemSearchParameter in include.SearchParameterList)
                            {
                                foreach (var SearchParameterResourceTarget in IncludeItemSearchParameter.TargetResourceTypeList)
                                {
                                    //Switch source resource repository to get reference FhirIds
                                    IResourceRepository = IRepositorySwitcher.GetRepository(Resource.ResourceType.Value);
                                    string[] FhirIdList = IResourceRepository.GetResourceFhirIdByResourceIdAndIndexReferance(Resource.Id, new int[] { IncludeItemSearchParameter.Id }, SearchParameterResourceTarget.ResourceType.GetLiteral());
                                    if (FhirIdList.Count() > 0)
                                    {
                                        //Switch to SearchParameterResourceTarget resource repository to get the include resource if found
                                        IResourceRepository = IRepositorySwitcher.GetRepository(ResourceNameResolutionSupport.GetResourceFhirAllType(SearchParameterResourceTarget.ResourceType));
                                        foreach (string FhirId in FhirIdList)
                                        {
                                            //Don't source the same resource again from the Database if we already have it
                                            AddIncludeResourceInstanceForIncludes(ReturnResourceList, CacheResourceIDsAlreadyCollected, FhirId);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(ReturnResourceList);
        }
Пример #6
0
        private List <DtoResource> GetRevIncludes(List <SearchParameterInclude> RevIncludeList, List <DtoResource> CurrentScourceResourceList, HashSet <string> CacheResourceIDsAlreadyCollected)
        {
            var ReturnResourceList = new List <DtoResource>();

            if (RevIncludeList == null || RevIncludeList.Count == 0)
            {
                return(ReturnResourceList);
            }

            if (CurrentScourceResourceList == null || CurrentScourceResourceList.Count == 0)
            {
                return(ReturnResourceList);
            }

            foreach (var Resource in CurrentScourceResourceList)
            {
                //Now process each include
                foreach (var RevInclude in RevIncludeList)
                {
                    PyroSearchParameters SearchParameters = new PyroSearchParameters();
                    SearchParameters.SearchParametersList = new List <ISearchParameterBase>();

                    //Does the include have a target Resource type
                    if (RevInclude.SearchParameterTargetResourceType.HasValue)
                    {
                        //Is the target Resource type of the include == to the current Resource we are targeting
                        if (Resource.ResourceType.Value == RevInclude.SearchParameterTargetResourceType.Value)
                        {
                            IResourceRepository = IRepositorySwitcher.GetRepository(RevInclude.SourceResourceType);
                            foreach (DtoServiceSearchParameterLight p in RevInclude.SearchParameterList)
                            {
                                //Check the current search Parameter has a Target == to the Resource we are targeting
                                if (p.TargetResourceTypeList.Any(x => x.ResourceType.GetLiteral() == Resource.ResourceType.Value.GetLiteral()))
                                {
                                    //Construct the search parameter string
                                    var ParameterString = new Tuple <string, string>(p.Name, $"{RevInclude.SearchParameterTargetResourceType.GetLiteral()}/{Resource.FhirId}");
                                    ISearchParameterBase SearchParam = ISearchParameterFactory.CreateSearchParameter(p, ParameterString);
                                    SearchParameters.SearchParametersList.Clear();
                                    SearchParameters.SearchParametersList.Add(SearchParam);
                                    //Get from the database and only add if we don't already have it
                                    AddIncludeResourceInstanceForRevIncludes(ReturnResourceList, CacheResourceIDsAlreadyCollected, SearchParameters);
                                }
                            }
                        }
                    }
                    else
                    {
                        foreach (DtoServiceSearchParameterLight p in RevInclude.SearchParameterList)
                        {
                            if (p.TargetResourceTypeList.Any(x => x.ResourceType.GetLiteral() == Resource.ResourceType.Value.GetLiteral()))
                            {
                                IResourceRepository = IRepositorySwitcher.GetRepository(ResourceNameResolutionSupport.GetResourceFhirAllType(p.Resource));
                                //Construct the search parameter string
                                var ParameterString = new Tuple <string, string>(p.Name, $"{Resource.ResourceType.Value.GetLiteral()}/{Resource.FhirId}");
                                ISearchParameterBase SearchParam = ISearchParameterFactory.CreateSearchParameter(p, ParameterString);
                                SearchParameters.SearchParametersList.Clear();
                                SearchParameters.SearchParametersList.Add(SearchParam);
                                //Get from the database and only add if we don't already have it
                                AddIncludeResourceInstanceForRevIncludes(ReturnResourceList, CacheResourceIDsAlreadyCollected, SearchParameters);
                            }
                        }
                    }
                }
            }
            return(ReturnResourceList);
        }
Пример #7
0
        public bool ResolveChain(ISearchParameterReferance SearchParameterReferance)
        {
            bool ChainTargetFound = true;

            if (!SearchParameterReferance.IsChained)
            {
                throw new Exception("Server Error: SearchParameterReferance.IsChained must be true for ChainSearchingService.");
            }

            IEnumerable <string> FhirIdList = null;
            //Work through each chain parameter in reverse
            bool PrimarySearchPerfomed = false;

            for (int i = SearchParameterReferance.ChainedSearchParameterList.Count - 1; i >= 0; i--)
            {
                ISearchParameterBase SearchParameterBase = SearchParameterReferance.ChainedSearchParameterList[i];
                //When the Chained parameter is a parameter for all resource types we need to switch the TypeModifierResource given for the
                //previous chain parameter or the root parameter
                //for example 'Observation?subject:Patient._id=FCC-PAT-0001'
                //Here the _id is an all Resource type search parameter so it's SearchParameterBase.Resource = Resource, we need here to refer to the
                //given SearchParameterReferance.TypeModifierResource as seen in the search string ':Patient'
                //Another example is 'DiagnosticReport?result:Observation.subject:Patient._id=FCC-PAT-00001' where the need to get the previous TypeModifierResource
                //from the list of chain parameters or the root parameter when i = 0.
                //so for this last example we need ':Patient' for the '_id' and ':Observation' for the 'subject'
                string ResourceRequiredForRepository = string.Empty;
                if (i > 0)
                {
                    ResourceRequiredForRepository = ResolveResourceTypeFromSearchParameterResourceModifier(SearchParameterBase.Resource, SearchParameterReferance.ChainedSearchParameterList[i - 1].TypeModifierResource);
                }
                else
                {
                    ResourceRequiredForRepository = ResolveResourceTypeFromSearchParameterResourceModifier(SearchParameterBase.Resource, SearchParameterReferance.TypeModifierResource);
                }

                if (!PrimarySearchPerfomed)
                {
                    IResourceRepository = IRepositorySwitcher.GetRepository(ResourceNameResolutionSupport.GetResourceFhirAllType(ResourceRequiredForRepository));
                    PyroSearchParameters SearchParameters = new PyroSearchParameters();
                    SearchParameters.SearchParametersList = new List <ISearchParameterBase>()
                    {
                        SearchParameterBase
                    };
                    FhirIdList            = IResourceRepository.GetResourceFhirIdBySearchNoPaging(SearchParameters);
                    PrimarySearchPerfomed = true;
                    if (FhirIdList.Count() == 0)
                    {
                        ChainTargetFound = false;
                        break;
                    }
                }
                else
                {
                    IResourceRepository = IRepositorySwitcher.GetRepository(ResourceNameResolutionSupport.GetResourceFhirAllType(ResourceRequiredForRepository));
                    string ReferenceResourceTargetName = string.Empty;
                    if (string.IsNullOrWhiteSpace(SearchParameterBase.TypeModifierResource))
                    {
                        ReferenceResourceTargetName = SearchParameterBase.TargetResourceTypeList[0].ResourceType.GetLiteral();
                    }
                    else
                    {
                        ReferenceResourceTargetName = SearchParameterBase.TypeModifierResource;
                    }
                    FhirIdList = IResourceRepository.GetResourceFhirIdByReferanceIndex(FhirIdList, ReferenceResourceTargetName, SearchParameterBase.Id);
                    if (FhirIdList.Count() == 0)
                    {
                        ChainTargetFound = false;
                        break;
                    }
                }
            }

            if (ChainTargetFound)
            {
                //We use the resource type from the first in the list which was the last above because we Reversed the list in the for each loop above.
                string ResourceType = ResolveResourceTypeFromSearchParameterResourceModifier(SearchParameterReferance.ChainedSearchParameterList[0].Resource, SearchParameterReferance.TypeModifierResource);
                SetSearchParameterValueList(FhirIdList, ResourceType, SearchParameterReferance);
            }
            return(ChainTargetFound);
        }
Пример #8
0
 /// <summary>
 /// Primarily used for Create & Update actions where a Resource is given in the API call
 /// Previous resource version can be sccourced from the database by version if required
 /// </summary>
 /// <param name="CrudOperationType"></param>
 /// <param name="Resource"></param>
 public ITriggerOutcome Trigger(RestEnum.CrudOperationType CrudOperationType, TriggerRaisedType TriggerRaised, Resource Resource)
 {
     return(ProcessTrigger(CrudOperationType, TriggerRaised, Resource.Id, ResourceNameResolutionSupport.GetResourceFhirAllType(Resource.ResourceType), Resource));
 }