From fe0d1b689c1cf2a6d8761e417167dda811edae6a Mon Sep 17 00:00:00 2001 From: Marten Smits Date: Thu, 16 Jul 2020 15:58:27 +0200 Subject: [PATCH 1/2] feature: add includeDesignations parameter in ValueSet expander --- .../Source/TerminologyTests.cs | 60 ++++++++++++++++++ .../Terminology/ValueSetExpander.cs | 61 ++++++++++++++++--- .../Terminology/ValueSetExpanderSettings.cs | 6 ++ 3 files changed, 118 insertions(+), 9 deletions(-) diff --git a/src/Hl7.Fhir.Specification.Tests/Source/TerminologyTests.cs b/src/Hl7.Fhir.Specification.Tests/Source/TerminologyTests.cs index d97ef2a88c..2c59dc181c 100644 --- a/src/Hl7.Fhir.Specification.Tests/Source/TerminologyTests.cs +++ b/src/Hl7.Fhir.Specification.Tests/Source/TerminologyTests.cs @@ -4,6 +4,7 @@ using Hl7.Fhir.Specification.Terminology; using Hl7.Fhir.Validation; using System; +using System.Collections.Generic; using System.Linq; using Xunit; @@ -89,6 +90,65 @@ public void ExpansionOfComposeImport() Assert.Equal(304, testVs.Expansion.Total); } + [Fact] + public void TestIncludeDesignation() + { + var testVs = _resolver.ResolveByCanonicalUri("http://hl7.org/fhir/ValueSet/animal-genderstatus").DeepCopy() as ValueSet; + Assert.False(testVs.HasExpansion); + var expander = new ValueSetExpander(new ValueSetExpanderSettings { ValueSetSource = _resolver }); + + //Import codes from codesystem + expander.Expand(testVs); + Assert.DoesNotContain(testVs.Expansion.Contains, c => c.Designation.Any()); + + expander.Settings.IncludeDesignations = true; + expander.Expand(testVs); + + Assert.Contains(testVs.Expansion.Parameter, p => p.Name == "includeDesignations" && (p.Value as FhirBoolean).Value == true); + Assert.Contains(testVs.Expansion.Contains, c => c.Designation.Any(d => d.Language == "nl" && d.Value == "gesteriliseerd")); + + //compose codes + testVs = new ValueSet + { + Compose = new ValueSet.ComposeComponent + { + Include = new List + { + new ValueSet.ConceptSetComponent + { + System = "http://hl7.org/fhir/v3/NullFlavor", + Concept = new List + { + + new ValueSet.ConceptReferenceComponent + { + Code = "UNK", + Display = "unknown", + Designation = new List + { + new ValueSet.DesignationComponent + { + Language = "nl", + Value = "onbekend" + } + } + } + } + } + } + } + }; + + expander.Settings.IncludeDesignations = false; + expander.Expand(testVs); + Assert.DoesNotContain(testVs.Expansion.Contains, c => c.Designation.Any()); + expander.Settings.IncludeDesignations = true; + expander.Expand(testVs); + + Assert.Contains(testVs.Expansion.Parameter, p => p.Name == "includeDesignations" && (p.Value as FhirBoolean).Value == true); + Assert.Contains(testVs.Expansion.Contains, c => c.Designation.Any(d => d.Language == "nl" && d.Value == "onbekend")); + } + [Fact] public void TestPropertyRetrieval() { diff --git a/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpander.cs b/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpander.cs index 0b0a863aea..9c91450d41 100644 --- a/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpander.cs +++ b/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpander.cs @@ -36,8 +36,8 @@ public void Expand(ValueSet source) { // Note we are expanding the valueset in-place, so it's up to the caller to decide whether // to clone the valueset, depending on store and performance requirements. - source.Expansion = ValueSet.ExpansionComponent.Create(); + setExpansionParameters(source, Settings); try { @@ -49,6 +49,21 @@ public void Expand(ValueSet source) source.Expansion = null; throw e; } + + } + + private void setExpansionParameters(ValueSet vs, ValueSetExpanderSettings settings) + { + vs.Expansion.Parameter = new List(); + if(settings.IncludeDesignations) + { + vs.Expansion.Parameter.Add(new ValueSet.ParameterComponent + { + Name = "includeDesignations", + Value = new FhirBoolean(true) + }); + } + //TODO add more parameters to the valuset here when we implement them. } @@ -79,10 +94,9 @@ private void handleCompose(ValueSet source) // handleImport(source); handleInclude(source); - handleExclude(source); + handleExclude(source); } - private List collectConcepts(ValueSet.ConceptSetComponent conceptSet) { List result = new List(); @@ -101,7 +115,15 @@ private void handleCompose(ValueSet source) { // We'd probably really have to look this code up in the original ValueSet (by system) to know something about 'abstract' // and what would we do with a hierarchy if we encountered that in the include? - result.Add(conceptSet.System, conceptSet.Version, concept.Code, concept.Display); + if(Settings.IncludeDesignations) + { + result.Add(conceptSet.System, conceptSet.Version, concept.Code, concept.Display, concept.Designation); + } + else + { + result.Add(conceptSet.System, conceptSet.Version, concept.Code, concept.Display); + } + } } else @@ -200,7 +222,7 @@ private void handleExclude(ValueSet source) if (importedCs == null) throw new ValueSetUnknownException($"Cannot resolve canonical reference '{uri}' to CodeSystem"); var result = new List(); - result.AddRange(importedCs.Concept.Select(c => c.ToContainsComponent(importedCs))); + result.AddRange(importedCs.Concept.Select(c => c.ToContainsComponent(importedCs, Settings))); return result; } @@ -209,7 +231,7 @@ private void handleExclude(ValueSet source) public static class ContainsSetExtensions { - public static ValueSet.ContainsComponent Add(this List dest, string system, string version, string code, string display, IEnumerable children = null) + public static ValueSet.ContainsComponent Add(this List dest, string system, string version, string code, string display, List designations = null, IEnumerable children = null) { var newContains = new ValueSet.ContainsComponent(); @@ -217,6 +239,7 @@ public static ValueSet.ContainsComponent Add(this List(children); @@ -245,14 +268,16 @@ public static void Remove(this List dest, List c.ToContainsComponent(system))); + source.Concept.Select(c => c.ToContainsComponent(system, settings))); return newContains; } + + private static List ToValueSetDesignations(this List csDesignations) + { + var vsDesignations = new List(); + csDesignations.ForEach(d => vsDesignations.Add(d.ToVsDesignation())); + return vsDesignations; + } + + private static ValueSet.DesignationComponent ToVsDesignation(this CodeSystem.DesignationComponent dsDesignation) + { + return new ValueSet.DesignationComponent + { + Language = dsDesignation.Language, + Use = dsDesignation.Use, + Value = dsDesignation.Value + }; + } + } } diff --git a/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpanderSettings.cs b/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpanderSettings.cs index d818b47bfc..9955b08dee 100644 --- a/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpanderSettings.cs +++ b/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpanderSettings.cs @@ -31,6 +31,11 @@ public class ValueSetExpanderSettings /// public int MaxExpansionSize { get; set; } = DefaultMaxExpansionSize; + /// + /// Controls whether concept designations are to be included or excluded in value set expansions + /// + public bool IncludeDesignations { get; set; } + /// Default constructor. Creates a new instance with default property values. public ValueSetExpanderSettings() { } @@ -51,6 +56,7 @@ public void CopyTo(ValueSetExpanderSettings other) other.MaxExpansionSize = MaxExpansionSize; other.ValueSetSource = ValueSetSource; + other.IncludeDesignations = IncludeDesignations; } /// Creates a new object that is a copy of the current instance. From 71bbea2845a27f6c6b4079af06eb763af46e855a Mon Sep 17 00:00:00 2001 From: Marten Smits Date: Mon, 20 Jul 2020 21:44:43 +0200 Subject: [PATCH 2/2] removed unnecessary settings parameter and renamed some stuff --- .../Terminology/ValueSetExpander.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpander.cs b/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpander.cs index 9c91450d41..a4b7f8e083 100644 --- a/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpander.cs +++ b/src/Hl7.Fhir.Specification/Specification/Terminology/ValueSetExpander.cs @@ -37,7 +37,7 @@ public void Expand(ValueSet source) // Note we are expanding the valueset in-place, so it's up to the caller to decide whether // to clone the valueset, depending on store and performance requirements. source.Expansion = ValueSet.ExpansionComponent.Create(); - setExpansionParameters(source, Settings); + setExpansionParameters(source); try { @@ -52,10 +52,10 @@ public void Expand(ValueSet source) } - private void setExpansionParameters(ValueSet vs, ValueSetExpanderSettings settings) + private void setExpansionParameters(ValueSet vs) { vs.Expansion.Parameter = new List(); - if(settings.IncludeDesignations) + if(Settings.IncludeDesignations) { vs.Expansion.Parameter.Add(new ValueSet.ParameterComponent { @@ -297,17 +297,17 @@ internal static ValueSet.ContainsComponent ToContainsComponent(this CodeSystem.C private static List ToValueSetDesignations(this List csDesignations) { var vsDesignations = new List(); - csDesignations.ForEach(d => vsDesignations.Add(d.ToVsDesignation())); + csDesignations.ForEach(d => vsDesignations.Add(d.ToValueSetDesignation())); return vsDesignations; } - private static ValueSet.DesignationComponent ToVsDesignation(this CodeSystem.DesignationComponent dsDesignation) + private static ValueSet.DesignationComponent ToValueSetDesignation(this CodeSystem.DesignationComponent csDesignation) { return new ValueSet.DesignationComponent { - Language = dsDesignation.Language, - Use = dsDesignation.Use, - Value = dsDesignation.Value + Language = csDesignation.Language, + Use = csDesignation.Use, + Value = csDesignation.Value }; }