public async Task GivenUpdatedResourcesWithWrongWeakETag_WhenBulkUpdatingSearchParameterIndicesAsync_ThenExceptionIsThrown()
        {
            ResourceElement patientResource1 = CreatePatientResourceElement("Patient1", Guid.NewGuid().ToString());
            SaveOutcome     upsertResult1    = await Mediator.UpsertResourceAsync(patientResource1);

            ResourceElement patientResource2 = CreatePatientResourceElement("Patient2", Guid.NewGuid().ToString());
            SaveOutcome     upsertResult2    = await Mediator.UpsertResourceAsync(patientResource2);

            SearchParameter searchParam1     = null;
            const string    searchParamName1 = "newSearchParam1";

            SearchParameter searchParam2     = null;
            const string    searchParamName2 = "newSearchParam2";

            try
            {
                searchParam1 = await CreatePatientSearchParam(searchParamName1, SearchParamType.String, "Patient.name");

                ISearchValue searchValue1 = new StringSearchValue(searchParamName1);

                (ResourceWrapper original1, ResourceWrapper updated1) = await CreateUpdatedWrapperFromExistingPatient(upsertResult1, searchParam1, searchValue1);

                (ResourceWrapper original2, ResourceWrapper updated2) = await CreateUpdatedWrapperFromExistingPatient(upsertResult2, searchParam1, searchValue1);

                await _dataStore.UpsertAsync(updated1, WeakETag.FromVersionId(original1.Version), allowCreate : false, keepHistory : false, CancellationToken.None);

                await _dataStore.UpsertAsync(updated2, WeakETag.FromVersionId(original2.Version), allowCreate : false, keepHistory : false, CancellationToken.None);

                // Let's update the resources again with new information
                searchParam2 = await CreatePatientSearchParam(searchParamName2, SearchParamType.Token, "Patient.gender");

                ISearchValue searchValue2 = new TokenSearchValue("system", "code", "text");

                // Create the updated wrappers using the original resource and its outdated version
                (_, ResourceWrapper updated1WithSearchParam2) = await CreateUpdatedWrapperFromExistingPatient(upsertResult1, searchParam2, searchValue2, original1);

                (_, ResourceWrapper updated2WithSearchParam2) = await CreateUpdatedWrapperFromExistingPatient(upsertResult2, searchParam2, searchValue2, original2);

                var resources = new List <ResourceWrapper> {
                    updated1WithSearchParam2, updated2WithSearchParam2
                };

                // Attempt to reindex resources with the old versions
                await Assert.ThrowsAsync <PreconditionFailedException>(() => _dataStore.BulkUpdateSearchParameterIndicesAsync(resources, CancellationToken.None));
            }
            finally
            {
                if (searchParam1 != null)
                {
                    _searchParameterDefinitionManager.DeleteSearchParameter(searchParam1.ToTypedElement());
                    await _fixture.TestHelper.DeleteSearchParameterStatusAsync(searchParam1.Url, CancellationToken.None);
                }

                if (searchParam2 != null)
                {
                    _searchParameterDefinitionManager.DeleteSearchParameter(searchParam2.ToTypedElement());
                    await _fixture.TestHelper.DeleteSearchParameterStatusAsync(searchParam2.Url, CancellationToken.None);
                }
            }
        }
Exemple #2
0
        protected override IEnumerable <ISearchValue> ConvertTo(CodeableConcept value)
        {
            // Based on spec: http://hl7.org/fhir/STU3/search.html#token,
            // CodeableConcept.text is searchable.
            if (!string.IsNullOrWhiteSpace(value.Text))
            {
                yield return(new TokenSearchValue(null, null, value.Text));
            }

            if (value.Coding?.Count == 0)
            {
                yield break;
            }

            foreach (Coding coding in value.Coding)
            {
                if (coding == null)
                {
                    continue;
                }

                TokenSearchValue searchValue = coding.ToTokenSearchValue();

                if (searchValue != null)
                {
                    yield return(searchValue);
                }
            }
        }
        public void GivenASearchValue_WhenToStringIsCalled_ThenCorrectStringShouldBeReturned(string system, string code, string expected)
        {
            _builder.System = system;
            _builder.Code   = code;

            TokenSearchValue value = _builder.ToTokenSearchValue();

            Assert.Equal(expected, value.ToString());
        }
        public void GivenAValidString_WhenParsed_ThenCorrectSearchValueShouldBeReturned(string s, string expectedSystem, string expectedCode)
        {
            TokenSearchValue value = TokenSearchValue.Parse(s);

            Assert.NotNull(value);
            Assert.Equal(expectedSystem, value.System);
            Assert.Equal(expectedCode, value.Code);
            Assert.Null(value.Text);
        }
Exemple #5
0
        protected override IEnumerable <ISearchValue> ConvertTo(Coding value)
        {
            TokenSearchValue searchValue = value.ToTokenSearchValue();

            if (searchValue != null)
            {
                yield return(searchValue);
            }
        }
Exemple #6
0
        void ISearchValueVisitor.Visit(TokenSearchValue token)
        {
            EnsureArg.IsNotNull(token, nameof(token));

            EnsureOnlyEqualComparatorIsSupported();

            if (_modifier == null)
            {
                _outputExpression = BuildEqualityExpression();
            }
            else if (_modifier == SearchModifierCode.Not)
            {
                _outputExpression = Expression.Not(BuildEqualityExpression());
            }
            else if (_modifier == SearchModifierCode.Above ||
                     _modifier == SearchModifierCode.Below ||
                     _modifier == SearchModifierCode.In ||
                     _modifier == SearchModifierCode.NotIn)
            {
                // These modifiers are not supported yet but will be supported eventually.
                ThrowModifierNotSupported();
            }
            else
            {
                ThrowModifierNotSupported();
            }

            Expression BuildEqualityExpression()
            {
                // Based on spec http://hl7.org/fhir/search.html#token,
                // we need to make sure to test if system is missing or not based on how it is supplied.
                if (token.System == null)
                {
                    // If the system is not supplied, then the token code is matched irrespective of the value of system.
                    return(Expression.StringEquals(FieldName.TokenCode, _componentIndex, token.Code, false));
                }
                else if (token.System.Length == 0)
                {
                    // If the system is empty, then the token is matched if there is no system property.
                    return(Expression.And(
                               Expression.Missing(FieldName.TokenSystem, _componentIndex),
                               Expression.StringEquals(FieldName.TokenCode, _componentIndex, token.Code, false)));
                }
                else if (string.IsNullOrWhiteSpace(token.Code))
                {
                    // If the code is empty, then the token is matched if system is matched.
                    return(Expression.StringEquals(FieldName.TokenSystem, _componentIndex, token.System, false));
                }
                else
                {
                    return(Expression.And(
                               Expression.StringEquals(FieldName.TokenSystem, _componentIndex, token.System, false),
                               Expression.StringEquals(FieldName.TokenCode, _componentIndex, token.Code, false)));
                }
            }
        }
        public void GivenOneNonEmptyField_WhenInitialized_ThenTokenSearchValueShouldBeCreated(string system, string code, string text)
        {
            _builder.System = system;
            _builder.Code   = code;
            _builder.Text   = text;

            TokenSearchValue value = _builder.ToTokenSearchValue();

            Assert.Equal(text, value.Text);
        }
Exemple #8
0
        void ISearchValueVisitor.Visit(TokenSearchValue token)
        {
            AddPropertyIfNotNull(SearchValueConstants.SystemName, token.System);
            AddPropertyIfNotNull(SearchValueConstants.CodeName, token.Code);

            if (!IsCompositeComponent)
            {
                // Since text is case-insensitive search, it will always be normalized.
                AddPropertyIfNotNull(SearchValueConstants.NormalizedTextName, token.Text?.ToUpperInvariant());
            }
        }
        public void GivenATokenSearchValueWithNullText_WhenGenerated_ThenCorrectJObjectShouldBeCreated()
        {
            const string system = "system";
            const string code   = "code";

            var value = new TokenSearchValue(system, code, null);

            var expectedValues = new[]
            {
                CreateTuple(SystemName, system),
                CreateTuple(CodeName, code),
            };

            TestAndValidateOutput(
                "token",
                value,
                expectedValues);
        }
        public void GivenATokenSearchValueWithNullCode_WhenGenerated_ThenCorrectJObjectShouldBeCreated()
        {
            const string system = "system";
            const string text   = "TEXT";

            var value = new TokenSearchValue(system, null, text);

            var expectedValues = new[]
            {
                CreateTuple(SystemName, system),
                CreateTuple(TextName, text),
            };

            TestAndValidateOutput(
                "token",
                value,
                expectedValues);
        }
        public void GivenATokenSearchValueWithNullSystem_WhenGenerated_ThenCorrectJObjectShouldBeCreated()
        {
            const string code = "code";
            const string text = "TEXT";

            var value = new TokenSearchValue(null, code, text);

            var expectedValues = new[]
            {
                CreateTuple(CodeName, code),
                CreateTuple(TextName, text),
            };

            TestAndValidateOutput(
                "token",
                value,
                expectedValues);
        }
        public void GivenATokenSearchValue_WhenGenerated_ThenCorrectJObjectShouldBeCreated()
        {
            const string system = "system";
            const string code   = "code";
            const string text   = "MixedCaseText";

            var value = new TokenSearchValue(system, code, text);

            var expectedValues = new[]
            {
                CreateTuple(SystemName, system),
                CreateTuple(CodeName, code),
                CreateTuple(TextName, text.ToUpperInvariant()),
            };

            TestAndValidateOutput(
                "token",
                value,
                expectedValues);
        }
        protected override IEnumerable <ISearchValue> ConvertTo(CodeableConcept value)
        {
            // Based on spec: http://hl7.org/fhir/STU3/search.html#token,
            // CodeableConcept.text is searchable, but we will only create a dedicated entry for it
            // if it is different from the display text of one of its codings

            bool conceptTextNeedsToBeAdded = !string.IsNullOrWhiteSpace(value.Text);

            if (value.Coding != null)
            {
                foreach (Coding coding in value.Coding)
                {
                    if (coding == null)
                    {
                        continue;
                    }

                    TokenSearchValue searchValue = coding.ToTokenSearchValue();

                    if (searchValue != null)
                    {
                        if (conceptTextNeedsToBeAdded)
                        {
                            conceptTextNeedsToBeAdded = !value.Text.Equals(searchValue.Text, StringComparison.OrdinalIgnoreCase);
                        }

                        yield return(searchValue);
                    }
                }
            }

            if (conceptTextNeedsToBeAdded)
            {
                yield return(new TokenSearchValue(null, null, value.Text));
            }
        }
 public void GivenAnInvalidString_WhenParsing_ThenExceptionShouldBeThrown(string s)
 {
     Assert.Throws <ArgumentException>(ParamNameS, () => TokenSearchValue.Parse(s));
 }
 public void GivenANullString_WhenParsing_ThenExceptionShouldBeThrown()
 {
     Assert.Throws <ArgumentNullException>(ParamNameS, () => TokenSearchValue.Parse(null));
 }
 public void GivenAStringContainingMoreThanOneTokenSeparator_WhenParsing_ThenExceptionShouldBeThrown()
 {
     Assert.Throws <FormatException>(() => TokenSearchValue.Parse(@"s12\|s12|c12\|c12|c12"));
 }
 public void Visit(TokenSearchValue token)
 {
 }
        public void GivenASearchValue_WhenIsValidCompositeComponentIsCalled_ThenCorrectValueShouldBeReturned(string system, string code, bool expected)
        {
            var value = new TokenSearchValue(system, code, "test");

            Assert.Equal(expected, value.IsValidAsCompositeComponent);
        }