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