public void TestCodeableConceptValidation()
        {
            var val = new BindingValidator(_termService, "Demo");

            var binding = new ElementDefinition.BindingComponent
            {
                ValueSet = new ResourceReference("http://hl7.org/fhir/ValueSet/data-absent-reason"),
                Strength = BindingStrength.Required
            };

            var cc = new CodeableConcept();

            cc.Coding.Add(new Coding("http://hl7.org/fhir/data-absent-reason", "NaN"));
            cc.Coding.Add(new Coding("http://hl7.org/fhir/data-absent-reason", "not-asked"));

            var result = val.ValidateBinding(cc, binding);

            Assert.True(result.Success);

            cc.Coding.First().Code = "NaNX";
            result = val.ValidateBinding(cc, binding);
            Assert.True(result.Success);

            cc.Coding.Skip(1).First().Code = "did-ask";
            result = val.ValidateBinding(cc, binding);
            Assert.False(result.Success);

            //EK 2017-07-6 No longer reports warnings when failing a preferred binding
            binding.Strength = BindingStrength.Preferred;
            result           = val.ValidateBinding(cc, binding);
            Assert.True(result.Success);
            Assert.Equal(0, result.Warnings);
        }
示例#2
0
        public void TestEmptyIllegalAndLegalCode()
        {
            var val = new BindingValidator(_termService, "Demo");

            var binding = new ElementDefinition.BindingComponent
            {
                ValueSet = new ResourceReference("http://hl7.org/fhir/ValueSet/data-absent-reason"),
                Strength = BindingStrength.Required
            };

            var cc = new CodeableConcept();

            cc.Coding.Add(new Coding(null, null, "Just some display text"));

            // First, with no code at all in a CC
            var result = val.ValidateBinding(cc, binding);

            Assert.False(result.Success);
            Assert.Contains("No code found in instance", result.ToString());

            // Now with no code + illegal code
            cc.Coding.Add(new Coding("urn:oid:1.2.3.4.5", "16", "Here's a code"));
            result = val.ValidateBinding(cc, binding);
            Assert.False(result.Success);
            Assert.Contains("None of the Codings in the CodeableConcept were valid for the binding", result.ToString());

            // Now, add a third valid code according to the binding.
            cc.Coding.Add(new Coding("http://hl7.org/fhir/data-absent-reason", "asked"));
            result = val.ValidateBinding(cc, binding);
            Assert.True(result.Success);
        }
        public static double DistanceBinding(ElementDefinition.BindingComponent binding1, ElementDefinition.BindingComponent binding2, double weight)
        {
            double distance = 0;

            if (binding1 == null && binding2 == null)
            {
                return(0);
            }
            if ((binding1 == null && binding2 != null) || (binding2 == null && binding1 != null))
            {
                Program.LogAspectDifference(weight, "Binding");
                return(weight);
            }
            if (binding1.Strength != binding2.Strength)
            {
                distance += AspectWeights.WEIGHT_BINDING_STRENGTH;
            }
            if (!CompareValueProperty.ComplexElementComparer.Default.Equals(binding1.ValueSet, binding2.ValueSet))
            {
                distance += AspectWeights.WEIGHT_BINDING_VALUESET;
            }
            if (binding1.Description != binding2.Description)
            {
                distance += AspectWeights.WEIGHT_BINDING_DESCRIPTION;
            }
            Program.LogAspectDifference((weight * distance), "Binding");
            return(weight * distance);
        }
示例#4
0
        public static ElementDefinition WithBinding(this ElementDefinition ed, string valueSetUri, BindingStrength strength)
        {
            var binding = new ElementDefinition.BindingComponent
            {
                ValueSet = new ResourceReference(valueSetUri),
                Strength = strength
            };

            ed.Binding = binding;

            return(ed);
        }
        public void TestCodingValidation()
        {
            var val     = new BindingValidator(_termService, "Demo");
            var binding = new ElementDefinition.BindingComponent
            {
                ValueSet = new ResourceReference("http://hl7.org/fhir/ValueSet/data-absent-reason"),
                Strength = BindingStrength.Required
            };

            var c      = new Coding("http://hl7.org/fhir/data-absent-reason", "NaN");
            var result = val.ValidateBinding(c, binding);

            Assert.True(result.Success);

            c.Code = "NaNX";
            result = val.ValidateBinding(c, binding);
            Assert.False(result.Success);

            c.Code           = "NaN";
            binding.Strength = null;
            result           = val.ValidateBinding(c, binding);
            Assert.True(result.Success);
            Assert.Equal(1, result.Warnings);  // missing binding strength

            c.Display        = "Not a Number";
            binding.Strength = BindingStrength.Required;
            result           = val.ValidateBinding(c, binding);
            Assert.True(result.Success);

            c.Display = "Not a NumberX";
            result    = val.ValidateBinding(c, binding);
            Assert.False(result.Success);

            // But this won't, it's also a composition, but without expansion - the local term server won't help you here
            var binding2 = new ElementDefinition.BindingComponent
            {
                ValueSet = new FhirUri("http://hl7.org/fhir/ValueSet/allergyintolerance-substance-code"),
                Strength = BindingStrength.Required
            };

            c      = new Coding("http://snomed.info/sct", "160244002");
            result = val.ValidateBinding(c, binding2);
            Assert.True(result.Success);
            Assert.NotEmpty(result.Where(type: OperationOutcome.IssueType.NotSupported));
        }
        public OperationOutcome ValidateBinding(Element bindable, ElementDefinition.BindingComponent binding)
        {
            // bindable should be code, Coding or CodeableConcept

            if (binding.Strength == null)
            {
                return(Issue.PROFILE_INCOMPLETE_BINDING.NewOutcomeWithIssue($"Encountered a binding element without a binding strength", _path));
            }

            var uri = (binding.ValueSet as FhirUri)?.Value ??
                      (binding.ValueSet as ResourceReference)?.Reference;

            if (uri == null)
            {
                return(Issue.PROFILE_INCOMPLETE_BINDING.NewOutcomeWithIssue($"Encountered a binding element without either a ValueSet reference or uri", _path));
            }

            var abstractAllowed = true;     // no way to say otherwise in the current spec?

            OperationOutcome outcome;

            if (!hasCode(bindable))
            {
                var isCCWithJustText = bindable is CodeableConcept cc && !String.IsNullOrEmpty(cc.Text);
                if (isCCWithJustText)
                {
                    return(new OperationOutcome());   // OK
                }
                return(Issue.TERMINOLOGY_NO_CODE_IN_INSTANCE.NewOutcomeWithIssue($"No code found in instance.", _path));
            }

            switch (bindable)
            {
            case Code co:
                outcome = callService(uri, co?.Value, system: null, display: null, abstractAllowed: abstractAllowed);
                break;

            case Coding cd:
                outcome = callService(uri, coding: cd, abstractAllowed: abstractAllowed);
                break;

            case CodeableConcept cc:
                outcome = callService(uri, cc: cc, abstractAllowed: abstractAllowed);
                break;

            default:
                throw Error.NotSupported($"Validating a binding against a '{bindable.TypeName}' is not supported in FHIR.");
            }

            //EK 20170605 - disabled inclusion of warnings/erros for all but required bindings since this will
            // 1) create superfluous messages (both saying the code is not valid) coming from the validateResult + the outcome.AddIssue()
            // 2) add the validateResult as warnings for preferred bindings, which are confusing in the case where the slicing entry is
            //    validating the binding against the core and slices will refine it: if it does not generate warnings against the slice,
            //    it should not generate warnings against the slicing entry.
            if (binding.Strength == BindingStrength.Required)
            {
                return(outcome);
            }
            else
            {
                return(new OperationOutcome());
            }
        }