Пример #1
0
        public void TestFhirUri_OperationResourceInstance(FhirVersion fhirVersion, string serversBase, string requestBase, string resourceName, string resourceId, string operationName, string query)
        {
            // Prepare
            FhirUriFactory FhirUriFactory = GetFhirUriFactory(serversBase, new string[] { resourceName });

            string RequestUrl = $"{requestBase}/{resourceName}/{resourceId}/${operationName}?{query}";

            //Act
            if (FhirUriFactory.TryParse(RequestUrl, fhirVersion, out IFhirUri? IFhirUri, out string ErrorMessage))
            {
                //Assert
                if (IFhirUri is object)
                {
                    Assert.Equal(operationName, IFhirUri.OperationName);
                    Assert.Equal(OperationScope.Instance, IFhirUri.OperationType);
                    Assert.Equal(resourceName, IFhirUri.ResourseName);
                    Assert.Equal(resourceId, IFhirUri.ResourceId);
                    Assert.False(IFhirUri.IsContained);
                    Assert.True(IFhirUri.IsRelativeToServer);
                    Assert.Equal(new Uri(serversBase), IFhirUri.UriPrimaryServiceRoot);
                    Assert.False(IFhirUri.IsHistoryReferance);
                    Assert.Equal(string.Empty, IFhirUri.VersionId);
                    Assert.Null(IFhirUri.PrimaryServiceRootRemote);
                    Assert.Equal(new Uri(serversBase), IFhirUri.PrimaryServiceRootServers);
                    Assert.False(IFhirUri.IsCompartment);
                    Assert.False(IFhirUri.ErrorInParseing);
                    Assert.False(IFhirUri.IsMetaData);
                    Assert.False(IFhirUri.IsCompartment);
                    Assert.False(IFhirUri.IsUrn);
                    Assert.False(IFhirUri.IsFormDataSearch);
                    Assert.Equal(RequestUrl, IFhirUri.OriginalString);
                    Assert.Equal(string.Empty, IFhirUri.CompartmentalisedResourseName);
                    Assert.Equal(fhirVersion, IFhirUri.FhirVersion);
                    Assert.Equal(query, IFhirUri.Query);
                    Assert.Equal(string.Empty, IFhirUri.Urn);
                    Assert.Null(IFhirUri.UrnType);
                    Assert.Equal(string.Empty, IFhirUri.ParseErrorMessage);
                }
            }
            else
            {
                Assert.Equal("some error message", ErrorMessage);
            }
        }
Пример #2
0
        public void TestFhirUriCanonical(FhirVersion fhirVersion, string resourceName, string resourceId, string CanonicalVersionId)
        {
            // Prepare
            FhirUriFactory FhirUriFactory = GetFhirUriFactory(TestData.BaseUrlServer, new string[] { resourceName });


            string RequestUrl = $"{resourceName}/{resourceId}|{CanonicalVersionId}";

            //Act
            if (FhirUriFactory.TryParse(RequestUrl, fhirVersion, out IFhirUri? IFhirUri, out string ErrorMessage))
            {
                //Assert
                if (IFhirUri is object)
                {
                    Assert.Equal(resourceName, IFhirUri.ResourseName);
                    Assert.Equal(resourceId, IFhirUri.ResourceId);
                    Assert.Equal(string.Empty, IFhirUri.VersionId);
                    Assert.Equal(CanonicalVersionId, IFhirUri.CanonicalVersionId);

                    Assert.Equal(new Uri(TestData.BaseUrlServer), IFhirUri.PrimaryServiceRootServers);
                    Assert.False(IFhirUri.IsCompartment);
                    Assert.False(IFhirUri.ErrorInParseing);
                    Assert.False(IFhirUri.IsMetaData);
                    Assert.False(IFhirUri.IsOperation);
                    Assert.False(IFhirUri.IsCompartment);
                    Assert.False(IFhirUri.IsUrn);
                    Assert.False(IFhirUri.IsFormDataSearch);
                    Assert.Equal(RequestUrl, IFhirUri.OriginalString);
                    Assert.Equal(string.Empty, IFhirUri.CompartmentalisedResourseName);
                    Assert.Equal(fhirVersion, IFhirUri.FhirVersion);
                    Assert.Equal(string.Empty, IFhirUri.OperationName);
                    Assert.Null(IFhirUri.OperationType);
                    Assert.Equal(string.Empty, IFhirUri.Query);
                    Assert.Equal(string.Empty, IFhirUri.Urn);
                    Assert.Null(IFhirUri.UrnType);
                    Assert.Equal(string.Empty, IFhirUri.ParseErrorMessage);
                }
            }
            else
            {
                Assert.Equal("some error message", ErrorMessage);
            }
        }
Пример #3
0
        public SerachQueryServiceOutcome(FhirVersion FhirVersion, ResourceType ResourceContext, IFhirSearchQuery IFhirSearchQuery)
        {
            this.FhirVersion     = FhirVersion;
            this.ResourceContext = ResourceContext;
            this.CountRequested  = IFhirSearchQuery.Count;
            this.PageRequested   = IFhirSearchQuery.Page;
            this.SummaryType     = IFhirSearchQuery.SummaryType;
            this.Contained       = IFhirSearchQuery.Contained;
            this.ContainedType   = IFhirSearchQuery.ContainedType;

            this.Text    = IFhirSearchQuery.Text;
            this.Content = IFhirSearchQuery.Content;
            this.Filter  = IFhirSearchQuery.Filter;
            this.Query   = IFhirSearchQuery.Query;

            this.InvalidSearchQueryList     = IFhirSearchQuery.InvalidParameterList;
            this.UnsupportedSearchQueryList = new List <InvalidSearchQueryParameter>();
            this.IncludeList     = new List <SearchQueryInclude>();
            this.SearchQueryList = new List <ISearchQueryBase>();
            this.HasList         = new List <SearchQueryHas>();
        }
Пример #4
0
        public void DoubleChainQueryPositive(FhirVersion fhirVersion, ResourceType resourceContext, string parameterName, string parameterValue)
        {
            //Prepare
            SearchQueryService SearchQueryService = SetupSearchQueryService();

            Dictionary <string, StringValues> QueryDictonary = new Dictionary <string, StringValues>
            {
                { parameterName, new StringValues(parameterValue) },
            };

            FhirSearchQuery FhirSearchQuery = new FhirSearchQuery();

            FhirSearchQuery.Parse(QueryDictonary);

            //Act
            ISerachQueryServiceOutcome Outcome = SearchQueryService.Process(fhirVersion, resourceContext, FhirSearchQuery).Result;

            //Assert
            Assert.NotNull(Outcome);
            Assert.Equal(0, Outcome.InvalidSearchQueryList.Count);
            Assert.Null(Outcome.CountRequested);
            Assert.Equal(1, Outcome.SearchQueryList.Count);
            Assert.Equal(Common.Enums.ResourceType.Observation, Outcome.ResourceContext);

            var ChainSearchQuery = Outcome.SearchQueryList[0];

            Assert.NotNull(ChainSearchQuery);

            Assert.Equal("subject", ChainSearchQuery.Name);
            Assert.NotNull(ChainSearchQuery.ChainedSearchParameter);
            Assert.Equal("organization", ChainSearchQuery.ChainedSearchParameter !.Name);
            Assert.NotNull(ChainSearchQuery.ChainedSearchParameter !.ChainedSearchParameter);
            Assert.Equal("name", ChainSearchQuery.ChainedSearchParameter !.ChainedSearchParameter !.Name);
            if (ChainSearchQuery.ChainedSearchParameter !.ChainedSearchParameter is SearchQueryString SearchQueryString)
            {
                Assert.Single(SearchQueryString.ValueList);
                Assert.Equal("acmehealth", SearchQueryString.ValueList[0].Value);
            }
        }
Пример #5
0
 public FhirUri(FhirVersion fhirVersion, Uri PrimaryServiceRootServers)
 {
     this.PrimaryServiceRootServers = PrimaryServiceRootServers;
     this.FhirVersion                   = fhirVersion;
     this.ParseErrorMessage             = string.Empty;
     this.ErrorInParseing               = false;
     this.ResourseName                  = string.Empty;
     this.CompartmentalisedResourseName = string.Empty;
     this.ResourseName                  = string.Empty;
     this.ResourceId         = string.Empty;
     this.VersionId          = string.Empty;
     this.OperationName      = string.Empty;
     this.Query              = string.Empty;
     this.OriginalString     = string.Empty;
     this.IsUrn              = false;
     this.Urn                = string.Empty;
     this.IsFormDataSearch   = false;
     this.IsRelativeToServer = false;
     this.IsContained        = false;
     this.IsCompartment      = false;
     this.IsMetaData         = false;
     this.IsHistoryReferance = false;
     this.CanonicalVersionId = string.Empty;
 }
Пример #6
0
        public static bool CanConvertBetweenVersions(FhirVersion from, FhirVersion to)
        {
            int versionHops = Math.Abs(to - from);

            return(MAX_VERSION_HOPS == versionHops);
        }
Пример #7
0
        private static FhirLookupTemplateProcessor <Observation> GetFhirTemplateProcessor(FhirVersion fhirVersion)
        {
            switch (fhirVersion)
            {
            case FhirVersion.R4:
                return(new R4FhirLookupTemplateProcessor());

            default:
                throw new NotImplementedException();
            }

            throw new NotImplementedException();
        }
Пример #8
0
 public static string GetFhirVersionAsString(this FhirVersion version)
 {
     return(FhirConstants.KnownFhirVersions[version]);
 }
Пример #9
0
 public static bool IsVersionSupported(FhirVersion version)
 {
     return(SupportedVersions.Contains(version));
 }
Пример #10
0
        public async Task <ChainQueryProcessingOutcome> Process(FhirVersion fhirVersion, ResourceType resourceContext, KeyValuePair <string, StringValues> Parameter)
        {
            this.FhirVersion     = fhirVersion;
            this.ResourceContext = resourceContext;

            var Outcome = new ChainQueryProcessingOutcome();

            this.RawParameter = $"{Parameter.Key}={Parameter.Value}";
            string[] ChaimedParameterSplit = Parameter.Key.Split(FhirSearchQuery.TermChainDelimiter);

            for (int i = 0; i < ChaimedParameterSplit.Length; i++)
            {
                //Each segment in the chain is a IsChainedReferance except the last segment in the chain which has the value.
                bool IsChainedReferance = !(i == ChaimedParameterSplit.Length - 1);
                Bug.Logic.DomainModel.SearchParameter?SearchParameter = null;
                string       ParameterNameWithModifier = Parameter.Key.Split(FhirSearchQuery.TermChainDelimiter)[i];
                StringValues 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 unless this is the last parameter in the whole chain.
                if (i == ChaimedParameterSplit.Count() - 1)
                {
                    ParameterValue = Parameter.Value;
                }

                var SingleChainedParameter = new KeyValuePair <string, StringValues>(ParameterNameWithModifier, ParameterValue);

                string ParameterName = string.Empty;
                string ParameterModifierTypedResource = string.Empty;

                //Check for and deal with modifiers e.g 'Patient' in the example: subject:Patient.family=millar
                if (ParameterNameWithModifier.Contains(FhirSearchQuery.TermSearchModifierDelimiter))
                {
                    string[] ParameterModifierSplit = ParameterNameWithModifier.Split(FhirSearchQuery.TermSearchModifierDelimiter);
                    ParameterName = ParameterModifierSplit[0].Trim();

                    if (ParameterModifierSplit.Length > 1)
                    {
                        ResourceType?ModifierResourceType = IResourceTypeSupport.GetTypeFromName(ParameterModifierSplit[1].Trim());
                        if (ModifierResourceType.HasValue && IKnownResource.IsKnownResource(this.FhirVersion, ParameterModifierSplit[1].Trim()))
                        {
                            ParameterModifierTypedResource = ParameterModifierSplit[1].Trim();
                        }
                        else
                        {
                            ErrorInSearchParameterProcessing = true;
                            //If the Parent is ok then we can assume that any error further down the chain is an invalid search term rather than an unsupported term
                            //as it is clear that this is a FHIR search term and not some other search parameter forgen to FHIR
                            if (ParentChainSearchParameter is object)
                            {
                                InvalidSearchQueryParameterList.Add(new InvalidSearchQueryParameter(this.RawParameter, $"The resource type modifier: {ParameterModifierSplit[1].Trim()} within the chained search query of {this.RawParameter} is not a known resource for FHIR version: {this.FhirVersion.GetCode()} within this server"));
                            }
                            else
                            {
                                //Here we are only looking up the ParameterName to check weather this should be an unsupported parameter or an invalid parameter.
                                //If we know the ParameterName then it is invalid whereas if we don't then it is unsupported and both are not known.
                                List <Bug.Logic.DomainModel.SearchParameter> TempSearchParameterList = await ISearchParameterCache.GetForIndexingAsync(this.FhirVersion, this.ResourceContext);

                                var TempSearchParameter = TempSearchParameterList.SingleOrDefault(x => x.Name == ParameterName);
                                if (TempSearchParameter is null)
                                {
                                    string Message = $"Both the search parameter name: {ParameterName} for the resource type: {this.ResourceContext.GetCode()} and its resource type modifier: {ParameterModifierSplit[1].Trim()} within the chained search query of {this.RawParameter} are unsupported within this server for FHIR version: {this.FhirVersion.GetCode()}.";
                                    UnsupportedSearchQueryParameterList.Add(new InvalidSearchQueryParameter(this.RawParameter, Message));
                                }
                                else
                                {
                                    InvalidSearchQueryParameterList.Add(new InvalidSearchQueryParameter(this.RawParameter, $"The resource type modifier: {ParameterModifierSplit[1].Trim()} within the chained search query of {this.RawParameter} is not a known resource type for this server and FHIR version {this.FhirVersion.GetCode()}."));
                                }
                            }
                            break;
                        }
                    }
                }
                else
                {
                    ParameterName = ParameterNameWithModifier;
                }

                SearchParameter = await GetSearchParameter(ParameterName);

                //We have no resolved a SearchParameter so we parse the value if it is the end of the chain, see IsChainedReferance
                //or we are only parsing as a chain segment with no end value
                if (SearchParameter != null)
                {
                    //If this is the last parameter in the chain then treat is as not a chain, otherwise treat as a chain
                    await SetChain(SearchParameter, SingleChainedParameter, IsChainedReferance);
                }
                else
                {
                    ErrorInSearchParameterProcessing = true;
                    if (this.InvalidSearchQueryParameterList.Count == 0 && this.UnsupportedSearchQueryParameterList.Count == 0)
                    {
                        throw new ApplicationException("Internal Server Error: When processing a chain search query we failed to resolve a search parameter for the query string however their are " +
                                                       $"no items found in either the {nameof(InvalidSearchQueryParameterList)} or the {nameof(UnsupportedSearchQueryParameterList)}. This is an error in its self.");
                    }
                    break;
                }
            }

            //End of Chain loop
            if (!ErrorInSearchParameterProcessing)
            {
                if (ParentChainSearchParameter is object)
                {
                    Outcome !.SearchQueryList.Add(ParentChainSearchParameter);
                    return(Outcome);
                }
                else
                {
                    throw new NullReferenceException(nameof(PreviousChainSearchParameter));
                }
            }
            else
            {
                InvalidSearchQueryParameterList.ForEach(x => Outcome !.InvalidSearchQueryList.Add(x));
                UnsupportedSearchQueryParameterList.ForEach(x => Outcome !.UnsupportedSearchQueryList.Add(x));
                return(Outcome);
            }
        }
Пример #11
0
 public void Is_FhirVersion_Supported(FhirVersion version)
 {
     Assert.True(FhirConverter.IsVersionSupported(version));
 }
Пример #12
0
        public void TestFhirUriHistory(FhirVersion fhirVersion, string serversBase, string requestBase, string resourceName, string resourceId, string versionId)
        {
            // Prepare
            FhirUriFactory FhirUriFactory = GetFhirUriFactory(serversBase, new string[] { resourceName });

            string RequestUrl;

            if (!string.IsNullOrWhiteSpace(versionId))
            {
                RequestUrl = $"{resourceName}/{resourceId}/_history/{versionId}";
            }
            else
            {
                if (!string.IsNullOrWhiteSpace(resourceId))
                {
                    RequestUrl = $"{resourceName}/{resourceId}";
                }
                else
                {
                    RequestUrl = $"{resourceName}";
                }
            }
            if (!string.IsNullOrWhiteSpace(requestBase))
            {
                RequestUrl = $"{requestBase}/{RequestUrl}";
            }

            //Act
            if (FhirUriFactory.TryParse(RequestUrl, fhirVersion, out IFhirUri? IFhirUri, out string ErrorMessage))
            {
                //Assert
                if (IFhirUri is object)
                {
                    Assert.Equal(resourceName, IFhirUri.ResourseName);

                    if (!string.IsNullOrWhiteSpace(resourceId))
                    {
                        if (resourceId.StartsWith('#'))
                        {
                            Assert.True(IFhirUri.IsContained);
                            Assert.Equal(resourceId.TrimStart('#'), IFhirUri.ResourceId);
                        }
                        else
                        {
                            Assert.False(IFhirUri.IsContained);
                            Assert.Equal(resourceId, IFhirUri.ResourceId);
                        }
                    }
                    else
                    {
                        Assert.Equal(string.Empty, IFhirUri.ResourceId);
                    }

                    if (!string.IsNullOrWhiteSpace(versionId))
                    {
                        Assert.True(IFhirUri.IsHistoryReferance);
                        Assert.Equal(versionId, IFhirUri.VersionId);
                    }
                    else
                    {
                        Assert.False(IFhirUri.IsHistoryReferance);
                        Assert.Equal(string.Empty, IFhirUri.VersionId);
                    }

                    if (serversBase == requestBase)
                    {
                        Assert.Null(IFhirUri.PrimaryServiceRootRemote);
                        Assert.True(IFhirUri.IsRelativeToServer);
                        Assert.Equal(new Uri(requestBase), IFhirUri.UriPrimaryServiceRoot);
                    }
                    else
                    {
                        if (!string.IsNullOrWhiteSpace(requestBase))
                        {
                            Assert.NotNull(IFhirUri.PrimaryServiceRootRemote);
                            Assert.False(IFhirUri.IsRelativeToServer);
                            Assert.Equal(new Uri(requestBase), IFhirUri.PrimaryServiceRootRemote);
                        }
                        else
                        {
                            Assert.Null(IFhirUri.PrimaryServiceRootRemote);
                            Assert.True(IFhirUri.IsRelativeToServer);
                        }
                    }

                    Assert.Equal(new Uri(serversBase), IFhirUri.PrimaryServiceRootServers);
                    Assert.False(IFhirUri.IsCompartment);
                    Assert.False(IFhirUri.ErrorInParseing);
                    Assert.False(IFhirUri.IsMetaData);
                    Assert.False(IFhirUri.IsOperation);
                    Assert.False(IFhirUri.IsCompartment);
                    Assert.False(IFhirUri.IsUrn);
                    Assert.False(IFhirUri.IsFormDataSearch);
                    Assert.Equal(RequestUrl, IFhirUri.OriginalString);
                    Assert.Equal(string.Empty, IFhirUri.CompartmentalisedResourseName);
                    Assert.Equal(fhirVersion, IFhirUri.FhirVersion);
                    Assert.Equal(string.Empty, IFhirUri.OperationName);
                    Assert.Null(IFhirUri.OperationType);
                    Assert.Equal(string.Empty, IFhirUri.Query);
                    Assert.Equal(string.Empty, IFhirUri.Urn);
                    Assert.Null(IFhirUri.UrnType);
                    Assert.Equal(string.Empty, IFhirUri.ParseErrorMessage);
                }
            }
            else
            {
                Assert.Equal("some error message", ErrorMessage);
            }
        }
        private DirectoryInfo CreateBaseDirectory(Uri uri, FhirVersion fhirVersion)
        {
            var path = Path.Combine(SafeDirectoryName(uri.Host), SafeFilename(fhirVersion.GetFhirVersionAsString()));

            return(Directory.CreateDirectory(path));
        }
Пример #14
0
 public FhirVersionFatalException(FhirVersion fhirMajorVersion)
 {
     HttpStatusCode = HttpStatusCode.InternalServerError;
     MessageList    = new string[] { $"A FhirMajorVersion was not handled by the server. The FhirMajorVersion value literal was: {fhirMajorVersion.GetCode()}" };
 }
Пример #15
0
        public static ResourceTypeWrapper ResourceType(this Resource it, FhirVersion v)
        {
            var wrapper = new ResourceWrapper(it, v);

            return(wrapper.ResourceType);
        }
Пример #16
0
        public static void SerializeResourceToDiskAsJson(this Resource resource, string path, FhirVersion version, bool pretty = true)
        {
            switch (version)
            {
            case FhirVersion.R3:
                SerializeResourceToDiskAsJsonR3(resource, path, pretty);
                break;

            case FhirVersion.R4:
                SerializeResourceToDiskAsJsonR4(resource, path, pretty);
                break;
            }
        }
Пример #17
0
 public FhirApiResourceQuery(HttpVerb HttpVerb, FhirVersion FhirVersion, Uri RequestUri, Dictionary <string, StringValues> RequestQuery, Dictionary <string, StringValues> HeaderDictionary, string ResourceName)
     : base(HttpVerb, FhirVersion, RequestUri, RequestQuery, HeaderDictionary)
 {
     this.ResourceName = ResourceName;
 }
Пример #18
0
        private Task HandleExceptionAsync(HttpContext context, Exception exec, ILogger <ErrorHandlingMiddleware> _logger)
        {
            _logger.LogError(exec, exec.Message);
            FhirVersion VersionInUse = GetFhirVersionInUse(context.Request.Path.Value);

            if (exec is FhirException FhirException)
            {
                _logger.LogError(FhirException, "FhirException has been thrown");
                FhirFormatType AcceptFormatType = Bug.Api.ContentFormatters.FhirMediaType.GetFhirFormatTypeFromAcceptHeader(context.Request.Headers.SingleOrDefault(x => x.Key.ToLower(System.Globalization.CultureInfo.CurrentCulture) == "accept").Value);
                switch (VersionInUse)
                {
                case FhirVersion.Stu3:
                {
                    return(Stu3FhirExceptionProcessing(context, FhirException, AcceptFormatType));
                }

                case FhirVersion.R4:
                {
                    return(R4FhirExceptionProcessing(context, FhirException, AcceptFormatType));
                }

                default:
                    throw new ApplicationException($"Unable to resolve which major version of FHIR is in use. Found enum: {VersionInUse.ToString()}");
                }
            }
            else
            {
                string ErrorGuid         = Common.FhirTools.FhirGuidSupport.NewFhirGuid();
                string UsersErrorMessage = string.Empty;
                if (Debugger.IsAttached)
                {
                    UsersErrorMessage = $"{System.Text.Encodings.Web.HtmlEncoder.Default.Encode(exec.ToString())} ->  Server Error log identifier: {ErrorGuid}";
                }
                else
                {
                    UsersErrorMessage = $"An unhanded exception has been thrown. To protect data privacy the exception information has been written to the application log with the error log identifier: {ErrorGuid}";
                }
                _logger.LogError(exec, $"Error log identifier: {ErrorGuid}");
                switch (VersionInUse)
                {
                case FhirVersion.Stu3:
                {
                    Stu3Model.OperationOutcome Stu3OperationOutcomeResult = IOperationOutComeSupportFactory.GetStu3().GetFatal(new string[] { UsersErrorMessage });
                    context.Response.ContentType = Bug.Api.ContentFormatters.FhirMediaType.GetMediaTypeHeaderValue(Stu3OperationOutcomeResult.GetType(), FhirFormatType.xml).Value;
                    context.Response.StatusCode  = (int)HttpStatusCode.InternalServerError;
                    return(context.Response.WriteAsync(IStu3SerializationToXml.SerializeToXml(Stu3OperationOutcomeResult)));
                }

                case FhirVersion.R4:
                {
                    R4Model.OperationOutcome R4OperationOutcomeResult = IOperationOutComeSupportFactory.GetR4().GetFatal(new string[] { UsersErrorMessage });
                    context.Response.ContentType = Bug.Api.ContentFormatters.FhirMediaType.GetMediaTypeHeaderValue(R4OperationOutcomeResult.GetType(), FhirFormatType.xml).Value;
                    context.Response.StatusCode  = (int)HttpStatusCode.InternalServerError;
                    return(context.Response.WriteAsync(IR4SerializationToXml.SerializeToXml(R4OperationOutcomeResult)));
                }

                default:
                    string msg = $"Unable to resolve which major version of FHIR is in use. Found enum: {VersionInUse.ToString()}";
                    _logger.LogError(msg);
                    throw new ApplicationException(msg);
                }
            }
        }
Пример #19
0
        public IActionResult Post([FromBody] TransformationTestRequest request)
        {
            // Validate Request.
            if (!IsValidRequest(request, out string errorMessage))
            {
                return(this.BadRequest(
                           new TransformationTestResponse()
                {
                    Result = TestResult.Fail.ToString(),
                    Reason = errorMessage,
                }));
            }

            // Validate mapping semantic.
            var templateContext = CollectionFhirTemplateFactory.Default.Create(request.FhirMapping);

            if (!templateContext.IsValid(out string errors))
            {
                return(this.BadRequest(
                           new TransformationTestResponse()
                {
                    Result = TestResult.Fail.ToString(),
                    Reason = errors,
                }));
            }

            FhirVersion fhirVersion = (FhirVersion)Enum.Parse(typeof(FhirVersion), request.FhirVersion, true);
            FhirIdentityResolutionType fhirIdentityResolutionType = (FhirIdentityResolutionType)Enum.Parse(typeof(FhirIdentityResolutionType), request.FhirIdentityResolutionType, true);
            IMeasurementGroup          measurementGroup;

            try
            {
                measurementGroup = JToken.Parse(request.NormalizedData).ToObject <MeasurementGroup>();

                if (string.IsNullOrWhiteSpace(measurementGroup.DeviceId))
                {
                    return(this.BadRequest(
                               new TransformationTestResponse()
                    {
                        Result = TestResult.Fail.ToString(),
                        Reason = "Device Id can't be null or empty.",
                    }));
                }

                if (fhirIdentityResolutionType == FhirIdentityResolutionType.Create &&
                    string.IsNullOrWhiteSpace(measurementGroup.PatientId))
                {
                    return(this.BadRequest(
                               new TransformationTestResponse()
                    {
                        Result = TestResult.Fail.ToString(),
                        Reason = "Patient Id can't be null with identity resolution type as \"Create\".",
                    }));
                }
            }
            catch (Exception ex)
            {
                return(this.BadRequest(
                           new TransformationTestResponse()
                {
                    Result = TestResult.Fail.ToString(),
                    Reason = ex.Message,
                }));
            }

            // Start processing.
            try
            {
                FhirLookupTemplateProcessor <Observation> processor = GetFhirTemplateProcessor(fhirVersion);
                var grps = processor.CreateObservationGroups(templateContext.Template, measurementGroup);

                Observation observation = null;
                string      deviceId    = measurementGroup.DeviceId;
                string      patientId   =
                    fhirIdentityResolutionType == FhirIdentityResolutionType.Create ? measurementGroup.PatientId : PatientIdPlaceholder;
                foreach (var grp in grps)
                {
                    if (observation == null)
                    {
                        observation         = processor.CreateObservation(templateContext.Template, grp);
                        observation.Subject = patientId.ToReference <Patient>();
                        observation.Device  = deviceId.ToReference <Device>();

                        var identity        = GenerateObservationId(grp, deviceId, patientId);
                        var observerationId = new Identifier
                        {
                            System = identity.System,
                            Value  = identity.Identifer,
                        };

                        observation.Identifier = new List <Identifier> {
                            observerationId
                        };
                    }
                    else
                    {
                        observation = processor.MergeObservation(templateContext.Template, grp, observation);
                    }
                }

                return(this.Ok(
                           new TransformationTestResponse()
                {
                    Result = TestResult.Success.ToString(),
                    FhirData = observation.ToJson(new FhirJsonSerializationSettings()
                    {
                        Pretty = true,
                    }),
                }));
            }
            catch (Exception ex)
            {
                return(this.BadRequest(
                           new TransformationTestResponse()
                {
                    Result = TestResult.Fail.ToString(),
                    Reason = ex.Message,
                }));
            }
        }
Пример #20
0
        public void TestFhirUri_ResourceNameValidForFhirVersion(FhirVersion fhirVersion, string serversBase, string resourceNameR4, string resourceNameStu3, string resourceId)
        {
            // Prepare
            Mock <IServiceBaseUrlConfi>         IServiceBaseUrlMock              = IServiceBaseUrl_MockFactory.Get(serversBase, serversBase);
            Mock <IR4ValidateResourceName>      IR4ValidateResourceNameMock      = IR4ValidateResourceName_MockFactory.Get(new string[] { resourceNameR4 });
            Mock <IStu3ValidateResourceName>    IStu3ValidateResourceNameMock    = IStu3ValidateResourceName_MockFactory.Get(new string[] { resourceNameStu3 });
            Mock <IValidateResourceNameFactory> IValidateResourceNameFactoryMock = IValidateResourceNameFactory_MockFactory.Get(IStu3ValidateResourceNameMock.Object, IR4ValidateResourceNameMock.Object);

            FhirUriFactory FhirUriFactory = new FhirUriFactory(IServiceBaseUrlMock.Object, IValidateResourceNameFactoryMock.Object);

            string RequestUrl;

            if (fhirVersion == FhirVersion.Stu3)
            {
                RequestUrl = $"{resourceNameStu3}/{resourceId}";
            }
            else
            {
                RequestUrl = $"{resourceNameR4}/{resourceId}";
            }


            //Act
            if (FhirUriFactory.TryParse(RequestUrl, fhirVersion, out IFhirUri? IFhirUri, out string ErrorMessage))
            {
                //Assert
                if (IFhirUri is object)
                {
                    if (fhirVersion == FhirVersion.Stu3)
                    {
                        Assert.Equal(resourceNameStu3, IFhirUri.ResourseName);
                    }
                    else
                    {
                        Assert.Equal(resourceNameR4, IFhirUri.ResourseName);
                    }
                    Assert.Equal(fhirVersion, IFhirUri.FhirVersion);
                    Assert.False(IFhirUri.IsContained);
                    Assert.Equal(resourceId.TrimStart('#'), IFhirUri.ResourceId);
                    Assert.True(IFhirUri.IsRelativeToServer);
                    Assert.Equal(new Uri(serversBase), IFhirUri.UriPrimaryServiceRoot);
                    Assert.False(IFhirUri.IsHistoryReferance);
                    Assert.Equal(string.Empty, IFhirUri.VersionId);
                    Assert.Null(IFhirUri.PrimaryServiceRootRemote);
                    Assert.Equal(new Uri(serversBase), IFhirUri.PrimaryServiceRootServers);
                    Assert.False(IFhirUri.IsCompartment);
                    Assert.False(IFhirUri.ErrorInParseing);
                    Assert.False(IFhirUri.IsMetaData);
                    Assert.False(IFhirUri.IsOperation);
                    Assert.False(IFhirUri.IsCompartment);
                    Assert.False(IFhirUri.IsUrn);
                    Assert.False(IFhirUri.IsFormDataSearch);
                    Assert.Equal(RequestUrl, IFhirUri.OriginalString);
                    Assert.Equal(string.Empty, IFhirUri.CompartmentalisedResourseName);

                    Assert.Equal(string.Empty, IFhirUri.OperationName);
                    Assert.Null(IFhirUri.OperationType);
                    Assert.Equal(string.Empty, IFhirUri.Query);
                    Assert.Equal(string.Empty, IFhirUri.Urn);
                    Assert.Null(IFhirUri.UrnType);
                    Assert.Equal(string.Empty, IFhirUri.ParseErrorMessage);
                }
                else
                {
                    Assert.Equal("some error message", ErrorMessage);
                }
            }
        }
Пример #21
0
 public HistoryInstanceQuery(HttpVerb HttpVerb, FhirVersion FhirVersion, Uri RequestUri, Dictionary <string, StringValues> RequestQuery, Dictionary <string, StringValues> HeaderDictionary, string ResourceName, string ResourceId)
     : base(HttpVerb, FhirVersion, RequestUri, RequestQuery, HeaderDictionary, ResourceName, ResourceId)
 {
 }
Пример #22
0
 public void CanConvert_Between_FhirVersion_WithOneHop(FhirVersion from, FhirVersion to)
 {
     Assert.True(FhirConverter.CanConvertBetweenVersions(from, to));
 }
Пример #23
0
        private async Task <Bug.Logic.DomainModel.SearchParameter?> GetSearchParameter(string parameterName)
        {
            Bug.Logic.DomainModel.SearchParameter        SearchParameter;
            List <Bug.Logic.DomainModel.SearchParameter> SearchParameterList = await ISearchParameterCache.GetForIndexingAsync(this.FhirVersion, this.ResourceContext);

            //Here we go through a series of ways to locate the SearchParameter for each segment of the chain query
            if (PreviousChainSearchParameter is null)
            {
                //If there is no previous then we look through the search parameter for the root resource type stored in this.ResourceContext
                SearchParameter = SearchParameterList.SingleOrDefault(x => x.Name == parameterName);
                if (SearchParameter is null)
                {
                    ErrorInSearchParameterProcessing = true;
                    UnsupportedSearchQueryParameterList.Add(new InvalidSearchQueryParameter(this.RawParameter, $"The resource search parameter name of: {parameterName} within the chained search query of: {this.RawParameter} is not a known search parameter for the resource: {this.ResourceContext} for this server in FHIR version: {this.FhirVersion.GetCode()}"));
                    return(null);
                }
                else
                {
                    return(SearchParameter);
                }
            }
            else
            {
                //Here we are using the PreviousChainSearchParameter's TypeModifierResource as the context to find the search parameter
                if (!PreviousChainSearchParameter.TypeModifierResource.HasValue)
                {
                    //If there is no TypeModifierResource on the previous then we look at how many it supports and if only one we can use that.
                    if (PreviousChainSearchParameter.TargetResourceTypeList.Count == 1)
                    {
                        PreviousChainSearchParameter.TypeModifierResource = PreviousChainSearchParameter.TargetResourceTypeList.ToArray()[0].ResourceTypeId;
                        List <Bug.Logic.DomainModel.SearchParameter> SearchParametersListForTarget = await ISearchParameterCache.GetForIndexingAsync(this.FhirVersion, PreviousChainSearchParameter.TargetResourceTypeList.ToArray()[0].ResourceTypeId);

                        Bug.Logic.DomainModel.SearchParameter SearchParameterForTarget = SearchParametersListForTarget.SingleOrDefault(x => x.Name == parameterName);
                        if (SearchParameterForTarget is null)
                        {
                            string Message = $"Unable to locate the search parameter named: {parameterName} for the resource type: {PreviousChainSearchParameter.TypeModifierResource} for FHIR version: {this.FhirVersion.GetCode()} within the chain search query of: {this.RawParameter}";
                            ErrorInSearchParameterProcessing = true;
                            InvalidSearchQueryParameterList.Add(new InvalidSearchQueryParameter(this.RawParameter, Message));
                            return(null);
                        }
                        else
                        {
                            SearchParameter = SearchParameterForTarget;
                            return(SearchParameter);
                        }
                    }
                    else
                    {
                        //If more than one then we search for the given search parameter name among all  resource types supported for the PreviousChainSearchParameter
                        Dictionary <ResourceType, Bug.Logic.DomainModel.SearchParameter> MultiChainedSearchParameter = new Dictionary <ResourceType, DomainModel.SearchParameter>();
                        foreach (var TargetResourceType in PreviousChainSearchParameter.TargetResourceTypeList)
                        {
                            List <Bug.Logic.DomainModel.SearchParameter> SearchParametersListForTarget = await ISearchParameterCache.GetForIndexingAsync(this.FhirVersion, TargetResourceType.ResourceTypeId);

                            Bug.Logic.DomainModel.SearchParameter SearchParameterForTarget = SearchParametersListForTarget.SingleOrDefault(x => x.Name == parameterName);
                            if (SearchParameterForTarget != null)
                            {
                                MultiChainedSearchParameter.Add(TargetResourceType.ResourceTypeId, SearchParameterForTarget);
                            }
                        }
                        if (MultiChainedSearchParameter.Count() == 1)
                        {
                            //If this resolves to only one found then we use it
                            PreviousChainSearchParameter.TypeModifierResource = MultiChainedSearchParameter.First().Key;
                            SearchParameter = MultiChainedSearchParameter.First().Value;
                            return(SearchParameter);
                        }
                        else
                        {
                            if (MultiChainedSearchParameter.Count > 1)
                            {
                                //We still have many to choose from so it cannot be resolved. The user need to specify the ResourceType with the Type modifier on the search parameter query e.g subject:Patient.family
                                string RefResources = string.Empty;
                                foreach (var DicItem in MultiChainedSearchParameter)
                                {
                                    RefResources += ", " + DicItem.Key.GetCode();
                                }
                                string ResourceName = this.ResourceContext.GetCode();
                                string Message      = string.Empty;
                                Message  = $"The chained search parameter '{this.RawParameter}' is ambiguous. ";
                                Message += $"Additional information: ";
                                Message += $"The search parameter '{parameterName}' could be a search parameter for any of 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}:{MultiChainedSearchParameter.First().Key.GetCode()}.{MultiChainedSearchParameter.First().Value.Name}' ";
                                Message += $"If the '{MultiChainedSearchParameter.First().Key.GetCode()}' resource was the intended reference for the search parameter '{MultiChainedSearchParameter.First().Value.Name}'.";
                                ErrorInSearchParameterProcessing = true;
                                InvalidSearchQueryParameterList.Add(new InvalidSearchQueryParameter(this.RawParameter, Message));
                                return(null);
                            }
                            else
                            {
                                //We have found zero matches for this search parameter name from the previous allowed resource types, so the search parameter name is possibly wrong.
                                string TargetResourceTypes = string.Empty;
                                foreach (var TargetResourceType in PreviousChainSearchParameter.TargetResourceTypeList)
                                {
                                    TargetResourceTypes += ", " + TargetResourceType.ResourceTypeId.GetCode();
                                }
                                string ResourceName = this.ResourceContext.GetCode();
                                string Message      = string.Empty;
                                Message  = $"The chained search parameter '{this.RawParameter}' is unresolvable. ";
                                Message += $"Additional information: ";
                                Message += $"The search parameter: {parameterName} should be a search parameter for any of the following resource types ({TargetResourceTypes.TrimStart(',').Trim()}) as resolved from the previous link in the chain: {PreviousChainSearchParameter.Name}. ";
                                Message += $"To correct this you must specify a search parameter here that is supported by those resource types. ";
                                Message += $"Please review your chained search query and specifically the use of the search parameter: {parameterName}'";
                                ErrorInSearchParameterProcessing = true;
                                InvalidSearchQueryParameterList.Add(new InvalidSearchQueryParameter(this.RawParameter, Message));
                                return(null);
                            }
                        }
                    }
                }
                else if (CheckModifierTypeResourceValidForSearchParameter(PreviousChainSearchParameter.TypeModifierResource.Value, PreviousChainSearchParameter.TargetResourceTypeList))
                {
                    //PreviousChainSearchParameter.TypeModifierResource = PreviousChainSearchParameter.TypeModifierResource;
                    //Double check the final Type modifier resource resolved is valid for the previous search parameter, the user could have got it wrong in the query.
                    ResourceType ResourceTypeTest        = PreviousChainSearchParameter.TypeModifierResource.Value;
                    FhirVersion  FhirVersionTest         = this.FhirVersion;
                    var          TempSearchParameterList = await this.ISearchParameterCache.GetForIndexingAsync(FhirVersionTest, ResourceTypeTest);

                    SearchParameter = TempSearchParameterList.SingleOrDefault(x => x.Name == parameterName);
                    if (SearchParameter is object)
                    {
                        return(SearchParameter);
                    }
                    else
                    {
                        string ResourceName = ResourceTypeTest.GetCode();
                        string Message      = $"The chained search query part: {parameterName} is not a supported search parameter name for the resource type: {ResourceName} for this server in FHIR version {this.FhirVersion.GetCode()}. ";
                        Message += $"Additional information: ";
                        Message += $"This search parameter was a chained search parameter. The part that was not recognized was: {parameterName}.";
                        ErrorInSearchParameterProcessing = true;
                        InvalidSearchQueryParameterList.Add(new InvalidSearchQueryParameter(this.RawParameter, Message));
                        return(null);
                    }
                }
                else
                {
                    //The modifier target resource provided is not valid for the previous reference, e.g subject:DiagnosticReport.family=millar
                    string ResourceName = this.ResourceContext.GetCode();
                    string Message      = $"The search parameter '{parameterName}' is not supported by this server for the resource type '{ResourceName}'. ";
                    Message += $"Additional information: ";
                    Message += $"This search parameter was a chained search parameter. The part that was not recognized was '{PreviousChainSearchParameter.Name}.{parameterName}', The search parameter modifier given '{PreviousChainSearchParameter.TypeModifierResource}' is not valid for the search parameter {PreviousChainSearchParameter.Name}. ";
                    ErrorInSearchParameterProcessing = true;
                    InvalidSearchQueryParameterList.Add(new InvalidSearchQueryParameter(this.RawParameter, Message));
                    return(null);
                }
            }
        }
Пример #24
0
        public async Task AddLocationAsync(Dictionary <string, StringValues> Headers, FhirVersion fhirVersion, string scheme, string resourceId, int versionId)
        {
            var ServiceBaseUrl = await IServiceBaseUrlCache.GetPrimaryAsync(fhirVersion);

            Headers.Add(HeaderNames.Location, $"{scheme}://{ServiceBaseUrl.Url}/{resourceId}/_history/{versionId.ToString()}");
        }
Пример #25
0
 public void FhirVersion_Matches_Version_Of_FhirType(FhirVersion expected, Type fhirType)
 {
     Assert.Equal(expected, FhirConverter.GetFhirVersion(fhirType));
 }
Пример #26
0
 public VReadQuery(HttpVerb HttpVerb, FhirVersion FhirVersion, Uri RequestUri, Dictionary <string, StringValues> RequestQuery, Dictionary <string, StringValues> HeaderDictionary, string ResourceName, string ResourceId, int VersionId)
     : base(HttpVerb, FhirVersion, RequestUri, RequestQuery, HeaderDictionary, ResourceName, ResourceId, VersionId)
 {
 }
Пример #27
0
 public void FhirVersion_Is_Not_Supported(FhirVersion version)
 {
     Assert.False(FhirConverter.IsVersionSupported(version));
 }
Пример #28
0
 public Uri Url(FhirVersion fhirMajorVersion)
 {
     return(ConstructFullUrl(fhirMajorVersion));
 }
Пример #29
0
 public void CannotConvert_Between_FhirVersion_WithMoreThanOneHop(FhirVersion from, FhirVersion to)
 {
     Assert.False(FhirConverter.CanConvertBetweenVersions(from, to));
 }
Пример #30
0
        public void TestFhirUri_Compartment(FhirVersion fhirVersion, string serversBase, string requestBase, string resourceName, string resourceId, string compartmentName, string query)
        {
            // Prepare
            //hit: the resource is unknown because we do not pass it into the GetFhirUriFactory below, we only pass in the resourceName and not the compatmentName
            FhirUriFactory FhirUriFactory;

            if (compartmentName == "Unknown")
            {
                FhirUriFactory = GetFhirUriFactory(serversBase, new string[] { resourceName });
            }
            else
            {
                FhirUriFactory = GetFhirUriFactory(serversBase, new string[] { resourceName, compartmentName });
            }

            string RequestUrl;

            if (string.IsNullOrWhiteSpace(query))
            {
                RequestUrl = $"{requestBase}/{resourceName}/{resourceId}/{compartmentName}";
            }
            else
            {
                RequestUrl = $"{requestBase}/{resourceName}/{resourceId}/{compartmentName}?{query}";
            }


            //Act
            if (FhirUriFactory.TryParse(RequestUrl, fhirVersion, out IFhirUri? IFhirUri, out string ErrorMessage))
            {
                //Assert
                if (IFhirUri is object)
                {
                    Assert.Equal(string.Empty, IFhirUri.OperationName);
                    Assert.Null(IFhirUri.OperationType);
                    Assert.Equal(resourceName, IFhirUri.ResourseName);
                    Assert.Equal(resourceId, IFhirUri.ResourceId);
                    Assert.False(IFhirUri.IsContained);
                    Assert.True(IFhirUri.IsRelativeToServer);
                    Assert.Equal(new Uri(serversBase), IFhirUri.UriPrimaryServiceRoot);
                    Assert.False(IFhirUri.IsHistoryReferance);
                    Assert.Equal(string.Empty, IFhirUri.VersionId);
                    Assert.Null(IFhirUri.PrimaryServiceRootRemote);
                    Assert.Equal(new Uri(serversBase), IFhirUri.PrimaryServiceRootServers);
                    Assert.True(IFhirUri.IsCompartment);
                    Assert.Equal(compartmentName, IFhirUri.CompartmentalisedResourseName);
                    Assert.False(IFhirUri.ErrorInParseing);
                    Assert.False(IFhirUri.IsMetaData);
                    Assert.False(IFhirUri.IsUrn);
                    Assert.False(IFhirUri.IsFormDataSearch);
                    Assert.Equal(RequestUrl, IFhirUri.OriginalString);
                    Assert.Equal(compartmentName, IFhirUri.CompartmentalisedResourseName);
                    Assert.True(IFhirUri.IsCompartment);
                    Assert.Equal(fhirVersion, IFhirUri.FhirVersion);

                    Assert.Equal(string.Empty, IFhirUri.Urn);
                    Assert.Null(IFhirUri.UrnType);
                    Assert.Equal(string.Empty, IFhirUri.ParseErrorMessage);

                    if (string.IsNullOrWhiteSpace(query))
                    {
                        Assert.Equal(string.Empty, IFhirUri.Query);
                    }
                    else
                    {
                        Assert.Equal(query, IFhirUri.Query);
                    }
                }
            }
            else
            {
                if (string.IsNullOrWhiteSpace(query))
                {
                    Assert.Equal("The URI has extra unknown content near the end of : 'Unknown'. The full URI was: 'http://base/stuff/Patient/10/Unknown'", ErrorMessage);
                }
                else
                {
                    Assert.Equal("The URI has extra unknown content near the end of : 'Unknown'. The full URI was: 'http://base/stuff/Patient/10/Unknown?query_one=one, query_two=two'", ErrorMessage);
                }
            }
        }