private void AddIncludeResourceInstanceForIncludes(List <DtoResource> IncludeResourceList, HashSet <string> CacheResourceIDsAlreadyCollected, string FhirId) { //Don't source the same resource again from the Database if we already have it if (!CacheResourceIDsAlreadyCollected.Contains($"{IResourceRepository.RepositoryResourceType.GetLiteral()}-{FhirId}")) { IDatabaseOperationOutcome DatabaseOperationOutcomeIncludes = null; //Here we need to add compartment search, if we have a Compartment and id if (!string.IsNullOrWhiteSpace(this._Compartment) && !string.IsNullOrWhiteSpace(this._CompartmentId)) { //Here we need create a search parameter for _id={FhirId) var IdSearchParameter = ServiceSearchParameterFactory.BaseResourceSearchParameters().SingleOrDefault(x => x.Name == "_id"); var IdParameterString = new Tuple <string, string>(IdSearchParameter.Name, FhirId); ISearchParameterBase SearchParam = ISearchParameterFactory.CreateSearchParameter(IdSearchParameter, IdParameterString); PyroSearchParameters FhirIdSearchParameter = new PyroSearchParameters(); FhirIdSearchParameter.SearchParametersList = new List <ISearchParameterBase>(); FhirIdSearchParameter.SearchParametersList.Add(SearchParam); //And now the Compartmnet Search parameters PyroSearchParameters CompartmentSearchParameter = ICompartmentSearchParameterService.GetSearchParameters(this._Compartment, this._CompartmentId, IResourceRepository.RepositoryResourceType.GetLiteral()); DatabaseOperationOutcomeIncludes = IResourceRepository.GetResourceByCompartmentSearch(CompartmentSearchParameter, FhirIdSearchParameter, true); } else { DatabaseOperationOutcomeIncludes = IResourceRepository.GetResourceByFhirID(FhirId, true, false); } var DtoIncludeResourceList = new List <DtoIncludeResource>(); DatabaseOperationOutcomeIncludes.ReturnedResourceList.ForEach(x => DtoIncludeResourceList.Add(new DtoIncludeResource(x))); IncludeResourceList.AddRange(DtoIncludeResourceList); CacheResourceIDsAlreadyCollected.Add($"{IResourceRepository.RepositoryResourceType.GetLiteral()}-{FhirId}"); } }
private bool ParseModifierType(ISearchParameterBase SearchParameter, string value) { var SearchModifierTypeDic = FhirSearchEnum.GetSearchModifierTypeDictionary(); string ValueCaseCorrectly = StringSupport.ToLowerFast(value); if (SearchModifierTypeDic.ContainsKey(ValueCaseCorrectly)) { SearchParameter.Modifier = SearchModifierTypeDic[ValueCaseCorrectly]; return(true); } else { string TypedResourceName = value; if (value.Contains(".")) { char[] delimiters = { '.' }; TypedResourceName = value.Split(delimiters)[0].Trim(); } Type ResourceType = ModelInfo.GetTypeForFhirType(TypedResourceName); if (ResourceType != null && ModelInfo.IsKnownResource(ResourceType)) { SearchParameter.TypeModifierResource = TypedResourceName; SearchParameter.Modifier = Hl7.Fhir.Model.SearchParameter.SearchModifierCode.Type; return(true); } return(false); } }
public static IList <string> GetSearchParameterTargetResourceList(ISearchParameterBase oSearchParameterBase) { IList <string> Result = new List <string>(); foreach (var Res in oSearchParameterBase.TargetResourceTypeList) { Result.Add(Res.ResourceType.GetLiteral()); } return(Result); }
private UnspportedSearchParameter InitaliseUnspportedParamerter(ISearchParameterBase oInboundSearchParameter, UnspportedSearchParameter DtoUnspportedSearchParameter) { if (DtoUnspportedSearchParameter == null) { DtoUnspportedSearchParameter = new UnspportedSearchParameter(); } if (string.IsNullOrWhiteSpace(DtoUnspportedSearchParameter.RawParameter)) { DtoUnspportedSearchParameter.RawParameter = $"{oInboundSearchParameter.RawValue}"; } return(DtoUnspportedSearchParameter); }
private void NormalSearchProcessing(Tuple <string, string> Parameter) { _DtoSupportedSearchParametersList = GetSupportedSearchParameters(_SearchParameterServiceType, _OperationClass, _ResourceType); DtoServiceSearchParameterLight oSupportedSearchParameter; //Remove modifiers var SearchParameterNameString = Parameter.Item1.Split(SearchParams.SEARCH_MODIFIERSEPARATOR)[0].Trim(); oSupportedSearchParameter = _DtoSupportedSearchParametersList.SingleOrDefault(x => x.Name == SearchParameterNameString); if (oSupportedSearchParameter != null) { ISearchParameterBase oSearchParameter = ISearchParameterFactory.CreateSearchParameter(oSupportedSearchParameter, Parameter); var UnspportedSearchParameterList = new List <UnspportedSearchParameter>(); if (ValidateSearchParameterSupported(oSupportedSearchParameter, oSearchParameter, UnspportedSearchParameterList)) { if (!IsSingularSearchParameter(oSearchParameter, _SearchParametersServiceOutcome)) { _SearchParametersServiceOutcome.SearchParameters.SearchParametersList.Add(oSearchParameter); } } else { var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}', the whole parameter was : '{DtoUnspportedSearchParameter.RawParameter}'."; DtoUnspportedSearchParameter.ReasonMessage += $"Additional information: "; foreach (var UnspportedSearchParameter in UnspportedSearchParameterList) { DtoUnspportedSearchParameter.ReasonMessage += UnspportedSearchParameter.ReasonMessage; } _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); } } else { var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}', the whole parameter was : '{DtoUnspportedSearchParameter.RawParameter}'"; _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); } }
private bool ParseModifier(string Name, ISearchParameterBase oSearchParameter) { if (Name.Contains(_ParameterNameModifierDilimeter)) { return(ParseModifierType(oSearchParameter, Name.Split(_ParameterNameModifierDilimeter)[1])); } else { oSearchParameter.Modifier = null; oSearchParameter.TypeModifierResource = null; return(true); } }
public ISearchParameterBase CreateSearchParameter(DtoServiceSearchParameterLight DtoSupportedSearchParametersResource, Tuple <string, string> Parameter, bool IsChainedReferance = false) { ISearchParameterBase oSearchParameter = InitalizeSearchParameter(DtoSupportedSearchParametersResource.Type); string ParameterName = Parameter.Item1; string ParameterValue = Parameter.Item2; oSearchParameter.Id = DtoSupportedSearchParametersResource.Id; oSearchParameter.Resource = DtoSupportedSearchParametersResource.Resource; oSearchParameter.Name = DtoSupportedSearchParametersResource.Name; oSearchParameter.TargetResourceTypeList = DtoSupportedSearchParametersResource.TargetResourceTypeList; if (IsChainedReferance) { oSearchParameter.RawValue = ParameterName + SearchParams.SEARCH_CHAINSEPARATOR; } else { oSearchParameter.RawValue = ParameterName + _ParameterNameParameterValueDilimeter + ParameterValue; } _RawSearchParameterAndValueString = oSearchParameter.RawValue; if (!ParseModifier(ParameterName, oSearchParameter)) { oSearchParameter.IsValid = false; oSearchParameter.InvalidMessage = $"Unable to parse the given search parameter's Modifier: {ParameterName}', "; } if (oSearchParameter.Type == SearchParamType.Reference) { (oSearchParameter as SearchParameterReferance).AllowedReferanceResourceList = ServiceSearchParameterFactory.GetSearchParameterTargetResourceList(oSearchParameter); (oSearchParameter as SearchParameterReferance).IsChained = IsChainedReferance; } if (oSearchParameter.Modifier == SearchParameter.SearchModifierCode.Type) { if (!oSearchParameter.TryParseValue($"{oSearchParameter.TypeModifierResource}/{ParameterValue}")) { oSearchParameter.IsValid = false; } } else { if (!oSearchParameter.TryParseValue(ParameterValue)) { oSearchParameter.IsValid = false; } } return(oSearchParameter); }
private string RecursiveChainScoped(ISearchParameterBase ParentChain, List <ISmartScope> ScopeList, SmartEnum.Action SmartAction) { IEnumerable <ISmartScope> FoundScopesList = ScopeList.Where(x => x.Resource.GetLiteral() == ParentChain.Resource && (x.Action == SmartAction || x.Action == SmartEnum.Action.All)); if (FoundScopesList.Count() > 0) { if (ParentChain.ChainedSearchParameter != null) { //Test the next search parameter return(RecursiveChainScoped(ParentChain.ChainedSearchParameter, ScopeList, SmartAction)); } else { //If the scopes are fine and allowed then we return empty string as suscess return(string.Empty); } } else { //If we are unable to find a scope for a given resource type we return the Resource name for error reporting. return(ParentChain.Resource); } }
private bool IsSingularSearchParameter(ISearchParameterBase oSearchParameter, ISearchParametersServiceOutcome _SearchParametersServiceOutcome) { if (oSearchParameter.Name == "page") { if (oSearchParameter is SearchParameterNumber) { var PageSearchParameter = oSearchParameter as SearchParameterNumber; _SearchParametersServiceOutcome.SearchParameters.RequiredPageNumber = Convert.ToInt32(PageSearchParameter.ValueList[0].Value); return(true); } } if (oSearchParameter.Name == Hl7.Fhir.Rest.HttpUtil.RESTPARAM_FORMAT) { if (oSearchParameter is SearchParameterString) { var FormatSearchParameter = oSearchParameter as SearchParameterString; _SearchParametersServiceOutcome.SearchParameters.Format = FormatSearchParameter.ValueList[0].Value.Trim(); return(true); } } if (oSearchParameter.Name == Hl7.Fhir.Rest.SearchParams.SEARCH_PARAM_SUMMARY) { if (oSearchParameter is SearchParameterToken FormatSearchParameter) { var SummaryDic = Common.Enum.FhirSearchEnum.GetSummaryTypeDictionary(); if (SummaryDic.ContainsKey(FormatSearchParameter.ValueList[0].Code.Trim())) { _SearchParametersServiceOutcome.SearchParameters.SummaryType = SummaryDic[FormatSearchParameter.ValueList[0].Code.Trim()]; } } return(true); } return(false); }
private void ChainSearchProcessing(Tuple <string, string> Parameter) { _DtoSupportedSearchParametersList = GetSupportedSearchParameters(_SearchParameterServiceType, _OperationClass, _ResourceType); ISearchParameterBase ParentChainSearchParameter = null; ISearchParameterBase PreviousChainSearchParameter = null; string[] ChaimedParameterSplit = Parameter.Item1.Split(SearchParams.SEARCH_CHAINSEPARATOR); bool ErrorInSearchParameterProcessing = false; for (int i = 0; i < ChaimedParameterSplit.Length; i++) { DtoServiceSearchParameterLight oSupportedSearchParameter = null; string ParameterName = Parameter.Item1.Split(SearchParams.SEARCH_CHAINSEPARATOR)[i]; string ParameterValue = string.Empty; //There is no valid Value for a chained reference parameter unless it is the last in a series //of chains, so don't set it. //Only set the last parameter if (i == ChaimedParameterSplit.Count() - 1) { ParameterValue = Parameter.Item2; } var SingleChainedParameter = new Tuple <string, string>(ParameterName, ParameterValue); string ParameterNameNoModifier = ParameterName; string ParameterModifierTypedResource = string.Empty; //Check for and deal with modifiers e.g 'Patient' in th example: subject:Patient.family=millar if (ParameterName.Contains(SearchParams.SEARCH_MODIFIERSEPARATOR)) { string[] ParameterModifierSplit = ParameterName.Split(SearchParams.SEARCH_MODIFIERSEPARATOR); ParameterNameNoModifier = ParameterModifierSplit[0].Trim(); if (ParameterModifierSplit.Length > 1) { Type ModifierResourceType = ModelInfo.GetTypeForFhirType(ParameterModifierSplit[1].Trim()); if (ModifierResourceType != null && ModelInfo.IsKnownResource(ModifierResourceType)) { ParameterModifierTypedResource = ParameterModifierSplit[1].Trim(); } } } if (PreviousChainSearchParameter == null) { oSupportedSearchParameter = _DtoSupportedSearchParametersList.SingleOrDefault(x => x.Name == ParameterNameNoModifier); } else { if (string.IsNullOrWhiteSpace(PreviousChainSearchParameter.TypeModifierResource)) { if (PreviousChainSearchParameter.TargetResourceTypeList != null) { if (PreviousChainSearchParameter.TargetResourceTypeList.Count == 1) { List <DtoServiceSearchParameterLight> _DtoSupportedSearchParametersListForTarget = GetSupportedSearchParameters(_SearchParameterServiceType, _OperationClass, PreviousChainSearchParameter.TargetResourceTypeList[0].ResourceType.GetLiteral()); DtoServiceSearchParameterLight oSupportedSearchParameterForTarget = _DtoSupportedSearchParametersListForTarget.SingleOrDefault(x => x.Name == ParameterNameNoModifier); PreviousChainSearchParameter.TypeModifierResource = oSupportedSearchParameterForTarget.Resource; oSupportedSearchParameter = oSupportedSearchParameterForTarget; } else { List <DtoServiceSearchParameterLight> oMultiChainedSupportedSearchParameter = new List <DtoServiceSearchParameterLight>(); foreach (var TargetResourceType in PreviousChainSearchParameter.TargetResourceTypeList) { FHIRAllTypes TargetResource = Tools.ResourceNameResolutionSupport.GetResourceFhirAllType(TargetResourceType.ResourceType); List <DtoServiceSearchParameterLight> _DtoSupportedSearchParametersListForTarget = GetSupportedSearchParameters(SearchParameterServiceType.Resource, null, TargetResource); DtoServiceSearchParameterLight oSupportedSearchParameterForTarget = _DtoSupportedSearchParametersListForTarget.SingleOrDefault(x => x.Name == ParameterNameNoModifier); if (oSupportedSearchParameterForTarget != null) { oMultiChainedSupportedSearchParameter.Add(oSupportedSearchParameterForTarget); } } if (oMultiChainedSupportedSearchParameter.Count() == 1) { PreviousChainSearchParameter.TypeModifierResource = oMultiChainedSupportedSearchParameter[0].Resource; oSupportedSearchParameter = oMultiChainedSupportedSearchParameter[0]; } else { //Need to do work here!! //oSupportedSearchParameter this needs to be set but we now have many! //the many is the list in oMultiChainedSupportedSearchParameter //PreviousChainSearchParameter.Modifier = SearchParameter.SearchModifierCode.Type; //PreviousChainSearchParameter.TypeModifierResource = oMultiChainedSupportedSearchParameter[0].Resource; string RefResources = string.Empty; oMultiChainedSupportedSearchParameter.ForEach(x => RefResources += ", " + x.Resource); //var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); //DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } string Message = string.Empty; Message = $"The chained search parameter '{Parameter.Item1}' is ambiguous. "; Message += $"Additional information: "; Message += $"The search parameter '{oMultiChainedSupportedSearchParameter[0].Name}' can referance the following resource types ({RefResources.TrimStart(',').Trim()}). "; Message += $"To correct this you must prefix the search parameter with a Type modifier, for example: '{PreviousChainSearchParameter.Name}:{oMultiChainedSupportedSearchParameter[0].Resource}.{oMultiChainedSupportedSearchParameter[0].Name}' "; Message += $"If the '{oMultiChainedSupportedSearchParameter[0].Resource}' resource was the intended referance for the search parameter '{oMultiChainedSupportedSearchParameter[0].Name}'."; if (_SearchParametersServiceOutcome.FhirOperationOutcome == null) { _SearchParametersServiceOutcome.FhirOperationOutcome = Common.Tools.FhirOperationOutcomeSupport.Create(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Processing, Message); } else { Common.Tools.FhirOperationOutcomeSupport.Append(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Processing, Message, _SearchParametersServiceOutcome.FhirOperationOutcome); } _SearchParametersServiceOutcome.HttpStatusCode = System.Net.HttpStatusCode.BadRequest; ErrorInSearchParameterProcessing = true; } } } else { //Error that we have no target resource list on the previous parameter, must have not been a references type? var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The search parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}'. "; DtoUnspportedSearchParameter.ReasonMessage += $"Additional information: "; DtoUnspportedSearchParameter.ReasonMessage += $"This search parameter was a chained search parameter. The part that was not recognised was '{PreviousChainSearchParameter.Name}.{ParameterName}'"; _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); ErrorInSearchParameterProcessing = true; break; } } else if (CheckModifierTypeResourceValidForSearchParameter(PreviousChainSearchParameter.TypeModifierResource, PreviousChainSearchParameter.TargetResourceTypeList)) { _DtoSupportedSearchParametersList = GetSupportedSearchParameters(_SearchParameterServiceType, _OperationClass, PreviousChainSearchParameter.TypeModifierResource); oSupportedSearchParameter = _DtoSupportedSearchParametersList.SingleOrDefault(x => x.Name == ParameterNameNoModifier); if (oSupportedSearchParameter.Resource == FHIRAllTypes.Resource.GetLiteral()) { oSupportedSearchParameter.Resource = PreviousChainSearchParameter.TypeModifierResource; } PreviousChainSearchParameter.TypeModifierResource = oSupportedSearchParameter.Resource; } else { //The modifier target resource provided is not valid for the previous reference, e.g subject:DiagnosticReport.family=millar var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The search parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}'. "; DtoUnspportedSearchParameter.ReasonMessage += $"Additional information: "; DtoUnspportedSearchParameter.ReasonMessage += $"This search parameter was a chained search parameter. The part that was not recognised was '{PreviousChainSearchParameter.Name}.{ParameterName}', The search parameter modifier given '{PreviousChainSearchParameter.TypeModifierResource}' is not valid for the search parameter {PreviousChainSearchParameter.Name}. "; _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); ErrorInSearchParameterProcessing = true; break; } } _DtoSupportedSearchParametersList.Clear(); if (oSupportedSearchParameter != null) { ISearchParameterBase oSearchParameter = null; if (i >= ChaimedParameterSplit.Length - 1) { oSearchParameter = ISearchParameterFactory.CreateSearchParameter(oSupportedSearchParameter, SingleChainedParameter, false); } else { oSearchParameter = ISearchParameterFactory.CreateSearchParameter(oSupportedSearchParameter, SingleChainedParameter, true); } var UnspportedSearchParameterList = new List <UnspportedSearchParameter>(); if (ValidateSearchParameterSupported(oSupportedSearchParameter, oSearchParameter, UnspportedSearchParameterList)) { if (!IsSingularSearchParameter(oSearchParameter, _SearchParametersServiceOutcome)) { ISearchParameterBase Temp = oSearchParameter.CloneDeep() as ISearchParameterBase; if (ParentChainSearchParameter == null) { ParentChainSearchParameter = Temp; } else { if (ParentChainSearchParameter.ChainedSearchParameter == null) { ParentChainSearchParameter.ChainedSearchParameter = Temp; } PreviousChainSearchParameter.ChainedSearchParameter = Temp; } PreviousChainSearchParameter = Temp; if (i != ChaimedParameterSplit.Count() - 1) { PreviousChainSearchParameter.Modifier = SearchParameter.SearchModifierCode.Type; } } } else { var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}', the whole parameter was : '{DtoUnspportedSearchParameter.RawParameter}'. "; DtoUnspportedSearchParameter.ReasonMessage += $"Additional information: "; foreach (var UnspportedSearchParameter in UnspportedSearchParameterList) { DtoUnspportedSearchParameter.ReasonMessage += UnspportedSearchParameter.ReasonMessage; } _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); ErrorInSearchParameterProcessing = true; break; } } else { var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The search parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}', the whole parameter was : '{DtoUnspportedSearchParameter.RawParameter}'. "; DtoUnspportedSearchParameter.ReasonMessage += $"Additional information: "; DtoUnspportedSearchParameter.ReasonMessage += $"This search parameter was a chained search parameter. The part that was not recognised was '{ParameterNameNoModifier}'"; _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); ErrorInSearchParameterProcessing = true; break; } } if (!ErrorInSearchParameterProcessing) { _SearchParametersServiceOutcome.SearchParameters.SearchParametersList.Add(ParentChainSearchParameter); } }
public ISearchParameterBase CreateSearchParameter(DtoServiceSearchParameterLight DtoSupportedSearchParametersResource, Tuple <string, string> Parameter, bool IsChainedReferance = false) { ISearchParameterBase oSearchParameter = InitalizeSearchParameter(DtoSupportedSearchParametersResource.Type); string ParameterName = Parameter.Item1; string ParameterValue = Parameter.Item2; oSearchParameter.Id = DtoSupportedSearchParametersResource.Id; oSearchParameter.Resource = DtoSupportedSearchParametersResource.Resource; oSearchParameter.Name = DtoSupportedSearchParametersResource.Name; oSearchParameter.TargetResourceTypeList = DtoSupportedSearchParametersResource.TargetResourceTypeList; oSearchParameter.CompositeList = DtoSupportedSearchParametersResource.CompositeList; if (IsChainedReferance) { oSearchParameter.RawValue = ParameterName + SearchParams.SEARCH_CHAINSEPARATOR; } else { oSearchParameter.RawValue = ParameterName + _ParameterNameParameterValueDilimeter + ParameterValue; } _RawSearchParameterAndValueString = oSearchParameter.RawValue; if (!ParseModifier(ParameterName, oSearchParameter)) { oSearchParameter.IsValid = false; oSearchParameter.InvalidMessage = $"Unable to parse the given search parameter's Modifier: {ParameterName}', "; } if (oSearchParameter.Type == SearchParamType.Reference) { (oSearchParameter as SearchParameterReferance).AllowedReferanceResourceList = ServiceSearchParameterFactory.GetSearchParameterTargetResourceList(oSearchParameter); (oSearchParameter as SearchParameterReferance).IsChained = IsChainedReferance; } if (oSearchParameter.Modifier == SearchParameter.SearchModifierCode.Type) { if (!oSearchParameter.TryParseValue($"{oSearchParameter.TypeModifierResource}/{ParameterValue}")) { oSearchParameter.IsValid = false; } } else if (DtoSupportedSearchParametersResource.Type == SearchParamType.Composite) { var SearchParameterComposite = oSearchParameter as SearchParameterComposite; List <ISearchParameterBase> SearchParameterBaseList = new List <ISearchParameterBase>(); var SearchListForResource = IServiceSearchParameterCache.GetSearchParameterForResource(DtoSupportedSearchParametersResource.Resource); //Note we OrderBy SequentialOrder as they must be processed in this specific order foreach (DtoServiceSearchParameterComposite Composite in DtoSupportedSearchParametersResource.CompositeList.OrderBy(x => x.SequentialOrder)) { DtoServiceSearchParameterLight CompositeSearchParamter = SearchListForResource.SingleOrDefault(x => x.Id == Composite.ChildServiceSearchParameterId); if (CompositeSearchParamter != null) { ISearchParameterBase CompositeSubSearchParameter = InitalizeSearchParameter(CompositeSearchParamter.Type); CompositeSubSearchParameter.Id = CompositeSearchParamter.Id; CompositeSubSearchParameter.Resource = CompositeSearchParamter.Resource; CompositeSubSearchParameter.Name = CompositeSearchParamter.Name; CompositeSubSearchParameter.TargetResourceTypeList = CompositeSearchParamter.TargetResourceTypeList; CompositeSubSearchParameter.CompositeList = CompositeSearchParamter.CompositeList; SearchParameterBaseList.Add(CompositeSubSearchParameter); } else { //This should not ever happen, but have message in case it does. We should never have a Composite //search parameter loaded like this as on load it is checked, but you never know! string Message = $"Unable to locate one of the SearchParameters referenced in a Composite SearchParametrer type. " + $"The Composite SearchParametrer name was '{DtoSupportedSearchParametersResource.Name}' for the resource type '{DtoSupportedSearchParametersResource.Resource}'. " + $"This SearchParamter references another SearchParamter with the Canonical Url of {Composite.Url}. " + $"This SearchParamter can not be located in the FHIR Server. This is most likely a server error that will require investigation to resolve"; var OpOut = Common.Tools.FhirOperationOutcomeSupport.Create(OperationOutcome.IssueSeverity.Fatal, OperationOutcome.IssueType.Informational, Message); throw new Common.Exceptions.PyroException(System.Net.HttpStatusCode.InternalServerError, OpOut, Message); } } if (!SearchParameterComposite.TryParseCompositeValue(SearchParameterBaseList, ParameterValue)) { oSearchParameter.IsValid = false; } } else { if (!oSearchParameter.TryParseValue(ParameterValue)) { oSearchParameter.IsValid = false; } } return(oSearchParameter); }
private void ChainSearchProcessing(Tuple <string, string> Parameter) { _DtoSupportedSearchParametersList = GetSupportedSearchParameters(_SearchParameterServiceType, _OperationClass, _ResourceType); ISearchParameterBase ParentChainSearchParameter = null; ISearchParameterBase PreviousChainSearchParameter = null; string[] ChaimedParameterSplit = Parameter.Item1.Split(SearchParams.SEARCH_CHAINSEPARATOR); bool ErrorInSearchParameterProcessing = false; for (int i = 0; i < ChaimedParameterSplit.Length; i++) { string ParameterName = Parameter.Item1.Split(SearchParams.SEARCH_CHAINSEPARATOR)[i]; string ParameterValue = string.Empty; //There is no valid Value for a chained reference parameter unless it is the last in a series of chains, so don't set it. //Only set the last parameter if (i == ChaimedParameterSplit.Count() - 1) { ParameterValue = Parameter.Item2; } var SingleChainedParameter = new Tuple <string, string>(ParameterName, ParameterValue); string ParameterNameNoModifier = ParameterName; string ParameterModifierTypedResource = string.Empty; //Check for a deal with modifiers e.g subject:Patient.family=millar if (ParameterName.Contains(SearchParams.SEARCH_MODIFIERSEPARATOR)) { string[] ParameterModifierSplit = ParameterName.Split(SearchParams.SEARCH_MODIFIERSEPARATOR); ParameterNameNoModifier = ParameterModifierSplit[0].Trim(); if (ParameterModifierSplit.Length > 1) { Type ModifierResourceType = ModelInfo.GetTypeForFhirType(ParameterModifierSplit[1].Trim()); if (ModifierResourceType != null && ModelInfo.IsKnownResource(ModifierResourceType)) { ParameterModifierTypedResource = ParameterModifierSplit[1].Trim(); } } } if (PreviousChainSearchParameter != null) { if (string.IsNullOrWhiteSpace(PreviousChainSearchParameter.TypeModifierResource)) { if (PreviousChainSearchParameter.TargetResourceTypeList != null) { if (PreviousChainSearchParameter.TargetResourceTypeList.Count == 1) { _DtoSupportedSearchParametersList = GetSupportedSearchParameters(_SearchParameterServiceType, _OperationClass, PreviousChainSearchParameter.TargetResourceTypeList[0].ResourceType.GetLiteral()); } else { //There is more than on target on the previous and yet the user has not given a modifier type to select one of them. var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The search parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}'. "; DtoUnspportedSearchParameter.ReasonMessage += $"Additional information: "; DtoUnspportedSearchParameter.ReasonMessage += $"This search parameter was a chained search parameter. The part that was not recognised was '{PreviousChainSearchParameter.Name}.{ParameterName}' because the reference search parameter '{PreviousChainSearchParameter.Name}' can resolve to more than one target resource type. In this case you must specify the Resource type required using a search parameter Modifier. For example '{PreviousChainSearchParameter.Name}:{PreviousChainSearchParameter.TargetResourceTypeList[0].ResourceType.GetLiteral()}.{ParameterName}'."; _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); ErrorInSearchParameterProcessing = true; break; } } else { //Error that we have no target resource list on the previous parameter, must have not been a references type? var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The search parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}'. "; DtoUnspportedSearchParameter.ReasonMessage += $"Additional information: "; DtoUnspportedSearchParameter.ReasonMessage += $"This search parameter was a chained search parameter. The part that was not recognised was '{PreviousChainSearchParameter.Name}.{ParameterName}'"; _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); ErrorInSearchParameterProcessing = true; break; } } else if (CheckModifierTypeResourceValidForSearchParameter(PreviousChainSearchParameter.TypeModifierResource, PreviousChainSearchParameter.TargetResourceTypeList)) { _DtoSupportedSearchParametersList = GetSupportedSearchParameters(_SearchParameterServiceType, _OperationClass, PreviousChainSearchParameter.TypeModifierResource); } else { //The modifier target resource provided is not valid for the previous reference, e.g subject:DiagnosticReport.family=millar var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The search parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}'. "; DtoUnspportedSearchParameter.ReasonMessage += $"Additional information: "; DtoUnspportedSearchParameter.ReasonMessage += $"This search parameter was a chained search parameter. The part that was not recognised was '{PreviousChainSearchParameter.Name}.{ParameterName}', The search parameter modifier given '{PreviousChainSearchParameter.TypeModifierResource}' is not valid for the search parameter {PreviousChainSearchParameter.Name}. "; _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); ErrorInSearchParameterProcessing = true; break; } } DtoServiceSearchParameterLight oSupportedSearchParameter = _DtoSupportedSearchParametersList.SingleOrDefault(x => x.Name == ParameterNameNoModifier); if (oSupportedSearchParameter != null) { ISearchParameterBase oSearchParameter = null; if (i >= ChaimedParameterSplit.Length - 1) { oSearchParameter = ISearchParameterFactory.CreateSearchParameter(oSupportedSearchParameter, SingleChainedParameter, false); } else { oSearchParameter = ISearchParameterFactory.CreateSearchParameter(oSupportedSearchParameter, SingleChainedParameter, true); } var UnspportedSearchParameterList = new List <UnspportedSearchParameter>(); if (ValidateSearchParameterSupported(oSupportedSearchParameter, oSearchParameter, UnspportedSearchParameterList)) { if (!IsSingularSearchParameter(oSearchParameter, _SearchParametersServiceOutcome)) { if (ParentChainSearchParameter == null) { ParentChainSearchParameter = oSearchParameter.CloneDeep() as ISearchParameterBase; } else { ParentChainSearchParameter.ChainedSearchParameterList.Add(oSearchParameter.CloneDeep() as ISearchParameterBase); } PreviousChainSearchParameter = oSearchParameter.CloneDeep() as ISearchParameterBase; } } else { var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}', the whole parameter was : '{DtoUnspportedSearchParameter.RawParameter}'. "; DtoUnspportedSearchParameter.ReasonMessage += $"Additional information: "; foreach (var UnspportedSearchParameter in UnspportedSearchParameterList) { DtoUnspportedSearchParameter.ReasonMessage += UnspportedSearchParameter.ReasonMessage; } _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); ErrorInSearchParameterProcessing = true; break; } } else { var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The search parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}', the whole parameter was : '{DtoUnspportedSearchParameter.RawParameter}'. "; DtoUnspportedSearchParameter.ReasonMessage += $"Additional information: "; DtoUnspportedSearchParameter.ReasonMessage += $"This search parameter was a chained search parameter. The part that was not recognised was '{ParameterNameNoModifier}'"; _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); ErrorInSearchParameterProcessing = true; break; } } if (!ErrorInSearchParameterProcessing) { _SearchParametersServiceOutcome.SearchParameters.SearchParametersList.Add(ParentChainSearchParameter); } }
private void SetSearchParameterValueList(IEnumerable <string> FhirIdList, string ReferanceResourceName, ISearchParameterBase SearchParameterBase) { if (SearchParameterBase is SearchParameterReferance Referance) { Referance.ValueList = new List <SearchParameterReferanceValue>(); //This adds each FhirId as an 'OR' for the search. foreach (string FhirId in FhirIdList) { var FhirUri = IPyroFhirUriFactory.CreateFhirRequestUri(); if (FhirUri.Parse($"{ReferanceResourceName}/{FhirId}")) { Referance.ValueList.Add(new SearchParameterReferanceValue() { FhirRequestUri = FhirUri, IsMissing = false }); } else { throw new Exception($"Server Error: can not parse server constructed FHIR URI of '{Referance.ChainedSearchParameterList[0].Resource}/{FhirId}'"); } } } else { throw new Exception($"Server Error: Cannot cast Chained search parameter as expected to SearchParameterReferance, type was {SearchParameterBase.GetType().ToString()}"); } }
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); }
private bool ValidateSearchParameterSupported(DtoServiceSearchParameterLight oSupported, ISearchParameterBase oInboundSearchParameter, IList <UnspportedSearchParameter> UnspportedSearchParameterList) { UnspportedSearchParameter DtoUnspportedSearchParameter = null; if (!oInboundSearchParameter.IsValid) { DtoUnspportedSearchParameter = InitaliseUnspportedParamerter(oInboundSearchParameter, DtoUnspportedSearchParameter); DtoUnspportedSearchParameter.ReasonMessage = DtoUnspportedSearchParameter.ReasonMessage + oInboundSearchParameter.InvalidMessage + ", "; } if (oInboundSearchParameter.Modifier.HasValue) { IList <SearchParameter.SearchModifierCode> oSupportedModifierList = Common.Tools.SearchParameterTools.GetModifiersForSearchType(oInboundSearchParameter.Type); if (!oSupportedModifierList.Contains(oInboundSearchParameter.Modifier.Value)) { DtoUnspportedSearchParameter = InitaliseUnspportedParamerter(oInboundSearchParameter, DtoUnspportedSearchParameter); DtoUnspportedSearchParameter.ReasonMessage = DtoUnspportedSearchParameter.ReasonMessage + $"The parameter's modifier: '{oInboundSearchParameter.Modifier.ToString()}' is not supported by this server for the resource type '{oInboundSearchParameter.Resource.ToString()}', the whole parameter was : '{DtoUnspportedSearchParameter.RawParameter}', "; } //I feel we already do this when parseing the Referance Paramerter //if (oInboundSearchParameter.Modifier == SearchParameter.SearchModifierCode.Type) //{ // if (!ServiceSearchParameterFactory.GetSearchParameterTargetResourceList(oInboundSearchParameter).Contains(oInboundSearchParameter.TypeModifierResource)) // { // DtoUnspportedSearchParameter = InitaliseUnspportedParamerter(oInboundSearchParameter, DtoUnspportedSearchParameter); // DtoUnspportedSearchParameter.ReasonMessage = DtoUnspportedSearchParameter.ReasonMessage + $"The search parameter modifier was expected to be a Fhir resource type that is supported for this search parameter. The Resource given was: {oInboundSearchParameter.TypeModifierResource} which is not supported for the search parameter '{oInboundSearchParameter.Name}.', "; // } //} } if (!oInboundSearchParameter.ValidatePrefixes(oSupported)) { DtoUnspportedSearchParameter = InitaliseUnspportedParamerter(oInboundSearchParameter, DtoUnspportedSearchParameter); string PreFixListString = string.Empty; Common.Tools.SearchParameterTools.GetPrefixListForSearchType(oSupported.Type).ForEach(x => PreFixListString = PreFixListString + "," + x); if (PreFixListString == string.Empty) { PreFixListString = "(none)"; } else { PreFixListString = $"({PreFixListString})"; } DtoUnspportedSearchParameter.ReasonMessage = DtoUnspportedSearchParameter.ReasonMessage + $"The one or more of the search parameter prefixes are not supported by this server against resource type of :'{oInboundSearchParameter.Resource.ToString()}', the whole parameter given was : '{DtoUnspportedSearchParameter.RawParameter}'. The prefixes that are supported are: {PreFixListString}, "; } //I feel we already do this when parseing the Referance Paramerter //if (oInboundSearchParameter.TypeModifierResource != null) //{ // if (!ServiceSearchParameterFactory.GetSearchParameterTargetResourceList(oInboundSearchParameter).Contains(oInboundSearchParameter.TypeModifierResource)) // { // DtoUnspportedSearchParameter = InitaliseUnspportedParamerter(oInboundSearchParameter, DtoUnspportedSearchParameter); // DtoUnspportedSearchParameter.ReasonMessage = DtoUnspportedSearchParameter.ReasonMessage + String.Format("Unsupported search, the Resource type given as the Modifier is not supported. Resource type: '{0}' in parameter '{1}'., ", oInboundSearchParameter.TypeModifierResource.ToString(), oInboundSearchParameter.RawValue); // } //} if (DtoUnspportedSearchParameter != null) { UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); return(false); } else { UnspportedSearchParameterList.Clear(); return(true); } }
private void NormalSearchProcessing(Tuple <string, string> Parameter) { _DtoSupportedSearchParametersList = GetSupportedSearchParameters(_SearchParameterServiceType, _OperationClass, _ResourceType); DtoServiceSearchParameterLight oSupportedSearchParameter; //Remove modifiers var SearchParameterNameString = Parameter.Item1.Split(SearchParams.SEARCH_MODIFIERSEPARATOR)[0].Trim(); oSupportedSearchParameter = _DtoSupportedSearchParametersList.SingleOrDefault(x => x.Name == SearchParameterNameString); if (oSupportedSearchParameter != null) { ISearchParameterBase oSearchParameter = ISearchParameterFactory.CreateSearchParameter(oSupportedSearchParameter, Parameter); if (oSearchParameter is SearchParameterReferance SearchParameterReferance) { foreach (var x in SearchParameterReferance.ValueList) { if (x.FhirRequestUri != null && string.IsNullOrWhiteSpace(x.FhirRequestUri.ResourseName)) { //After parsing the search parameter of type reference thewre is no Resource Type for the reference //e.g no Patient is the example 'Patient/123456' string RefResources = string.Empty; SearchParameterReferance.TargetResourceTypeList.ForEach(v => RefResources += ", " + v.ResourceType.GetLiteral()); string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } string Message = string.Empty; Message = $"The search parameter '{Parameter.Item1}' is ambiguous. "; Message += $"Additional information: "; Message += $"The search parameter '{SearchParameterReferance.Name}' can referance the following resource types ({RefResources.TrimStart(',').Trim()}). "; Message += $"To correct this you must prefix the search parameter with a Type modifier, for example: '{SearchParameterReferance.Name}={SearchParameterReferance.TargetResourceTypeList[0].ResourceType.GetLiteral()}/{x.FhirRequestUri.ResourceId}' "; Message += $"or: '{SearchParameterReferance.Name}:{SearchParameterReferance.TargetResourceTypeList[0].ResourceType.GetLiteral()}={x.FhirRequestUri.ResourceId}' "; Message += $"If the '{SearchParameterReferance.TargetResourceTypeList[0].ResourceType.GetLiteral()}' resource was the intended referance for the search parameter '{SearchParameterReferance.Name}'."; if (_SearchParametersServiceOutcome.FhirOperationOutcome == null) { _SearchParametersServiceOutcome.FhirOperationOutcome = Common.Tools.FhirOperationOutcomeSupport.Create(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Processing, Message); } else { Common.Tools.FhirOperationOutcomeSupport.Append(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Processing, Message, _SearchParametersServiceOutcome.FhirOperationOutcome); } _SearchParametersServiceOutcome.HttpStatusCode = System.Net.HttpStatusCode.BadRequest; } } } var UnspportedSearchParameterList = new List <UnspportedSearchParameter>(); if (ValidateSearchParameterSupported(oSupportedSearchParameter, oSearchParameter, UnspportedSearchParameterList)) { if (!IsSingularSearchParameter(oSearchParameter, _SearchParametersServiceOutcome)) { _SearchParametersServiceOutcome.SearchParameters.SearchParametersList.Add(oSearchParameter); } } else { var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The search parameter '{Parameter.Item1}' for the resource type '{ResourceName}', was unable to be processed as expected, the whole parameter was : '{DtoUnspportedSearchParameter.RawParameter}'."; DtoUnspportedSearchParameter.ReasonMessage += $"Additional information: "; foreach (var UnspportedSearchParameter in UnspportedSearchParameterList) { DtoUnspportedSearchParameter.ReasonMessage += UnspportedSearchParameter.ReasonMessage; } _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); } } else { var DtoUnspportedSearchParameter = new UnspportedSearchParameter(); DtoUnspportedSearchParameter.RawParameter = $"{Parameter.Item1}={Parameter.Item2}"; string ResourceName = string.Empty; if (_ResourceType.HasValue) { ResourceName = _ResourceType.Value.ToString(); } DtoUnspportedSearchParameter.ReasonMessage = $"The parameter '{Parameter.Item1}' is not supported by this server for the resource type '{ResourceName}', the whole parameter was : '{DtoUnspportedSearchParameter.RawParameter}'"; _SearchParametersServiceOutcome.SearchParameters.UnspportedSearchParameterList.Add(DtoUnspportedSearchParameter); } }
//Old Method for chaining, not in use public ISearchParameterBase CreateSearchParameter_OLD(DtoServiceSearchParameterLight DtoSupportedSearchParametersResource, Tuple <string, string> Parameter) { ISearchParameterBase oSearchParameter = InitalizeSearchParameter(DtoSupportedSearchParametersResource.Type); string ParameterName = Parameter.Item1; string ParameterValue = Parameter.Item2; oSearchParameter.Id = DtoSupportedSearchParametersResource.Id; oSearchParameter.Resource = DtoSupportedSearchParametersResource.Resource; oSearchParameter.Name = DtoSupportedSearchParametersResource.Name; oSearchParameter.TargetResourceTypeList = DtoSupportedSearchParametersResource.TargetResourceTypeList; oSearchParameter.RawValue = ParameterName + _ParameterNameParameterValueDilimeter + ParameterValue; _RawSearchParameterAndValueString = oSearchParameter.RawValue; if (!ParseModifier(ParameterName, oSearchParameter)) { oSearchParameter.IsValid = false; oSearchParameter.InvalidMessage = $"Unable to parse the given search parameter's Modifier: {ParameterName}', "; } if (ParameterName.Contains(Hl7.Fhir.Rest.SearchParams.SEARCH_CHAINSEPARATOR)) { //This is a resourceReferance with a Chained parameter, resolve that chained parameter to a search parameter here (is a recursive call). var SearchParameterGeneric = ISearchParameterGenericFactory.CreateDtoSearchParameterGeneric(); SearchParameterGeneric.ParameterList = new List <Tuple <string, string> >(); var x = ParameterName.Substring(ParameterName.IndexOf(Hl7.Fhir.Rest.SearchParams.SEARCH_CHAINSEPARATOR) + 1, (ParameterName.Length - ParameterName.IndexOf(Hl7.Fhir.Rest.SearchParams.SEARCH_CHAINSEPARATOR) - 1)); var ChainedSearchParam = new Tuple <string, string>(x, ParameterValue); SearchParameterGeneric.ParameterList.Add(ChainedSearchParam); FHIRAllTypes?TypeModifierResource = null; if (oSearchParameter.Modifier.HasValue && oSearchParameter.Modifier.Value == SearchParameter.SearchModifierCode.Type && !string.IsNullOrWhiteSpace(oSearchParameter.TypeModifierResource)) { //var ChainedSearchParam = new Tuple<string, string>(ParameterName.Split(Hl7.Fhir.Rest.SearchParams.SEARCH_CHAINSEPARATOR)[1], ParameterValue); TypeModifierResource = ModelInfo.FhirTypeNameToFhirType(oSearchParameter.TypeModifierResource).Value; } else { // If the chained reference has no Type modifier then their must be only one Target resource for the parameter! // The FHIR spec does allow the server to try and resolve resources for many resource targets in this case. Yet, the server must // reject the search if Resource instances are returned across more then one of the types for the search parameter. // This seams like a very fragile rule and would also be hard to implement given the current framework. // Therefore I am making a design decision that if more that one target resource is available for the given search // parameter and the user does not specify which by supplying a Type modifier, then I will reject the search parameter. if (oSearchParameter.TargetResourceTypeList != null && oSearchParameter.TargetResourceTypeList.Count == 1) { TypeModifierResource = ModelInfo.FhirTypeNameToFhirType(oSearchParameter.TargetResourceTypeList[0].ResourceType.GetLiteral()).Value; } else { if (oSearchParameter.TargetResourceTypeList != null && oSearchParameter.TargetResourceTypeList.Count > 1) { oSearchParameter.IsValid = false; oSearchParameter.InvalidMessage = $"The chained search parameter '{oSearchParameter.RawValue}' has no Type modifier specifying the target resource for the parameter and the parameter in use has many possible target resources. The search parameter must specify a target resource using the type modifier. For example '[base]/DiagnosticReport?subject:Patient.name=peter' where Patient is the Type modifier."; } else { throw new FormatException($"Server error: chained search parameter did not resolve to any target resource types. Parameter was: '{oSearchParameter.RawValue}' "); } } } ISearchParameterService SearchService = ISearchParameterServiceFactory.CreateSearchParameterService(); //oSearchParameter.ChainedSearchParameterList.Add(SearchService.ProcessResourceSearchParameters(SearchParameterGeneric, SearchParameterService.SearchParameterServiceType.Resource, TypeModifierResource.Value)); } else { if (oSearchParameter.Type == SearchParamType.Reference) { (oSearchParameter as SearchParameterReferance).AllowedReferanceResourceList = ServiceSearchParameterFactory.GetSearchParameterTargetResourceList(oSearchParameter); } if (!oSearchParameter.TryParseValue(ParameterValue)) { oSearchParameter.IsValid = false; } } return(oSearchParameter); }
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); }