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