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); }
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); }
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); } }
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); }
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); }
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); }
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); }
/// <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)); }