diff --git a/src/Hl7.Fhir.Base/CompatibilitySuppressions.xml b/src/Hl7.Fhir.Base/CompatibilitySuppressions.xml index ccb72627c2..9319cf6767 100644 --- a/src/Hl7.Fhir.Base/CompatibilitySuppressions.xml +++ b/src/Hl7.Fhir.Base/CompatibilitySuppressions.xml @@ -7,4 +7,18 @@ lib/netstandard2.0/Hl7.Fhir.Base.dll lib/net8.0/Hl7.Fhir.Base.dll + + CP0002 + M:Hl7.Fhir.Specification.Terminology.ValidateCodeParameters.WithCode(System.String,System.String,System.String,System.String,System.String,System.String) + lib/net8.0/Hl7.Fhir.Base.dll + lib/net8.0/Hl7.Fhir.Base.dll + true + + + CP0002 + M:Hl7.Fhir.Specification.Terminology.ValidateCodeParameters.WithCode(System.String,System.String,System.String,System.String,System.String,System.String) + lib/netstandard2.0/Hl7.Fhir.Base.dll + lib/netstandard2.0/Hl7.Fhir.Base.dll + true + \ No newline at end of file diff --git a/src/Hl7.Fhir.Base/FhirPath/ElementNavFhirExtensions.cs b/src/Hl7.Fhir.Base/FhirPath/ElementNavFhirExtensions.cs index 7ab1e73e10..8e0d9655fc 100644 --- a/src/Hl7.Fhir.Base/FhirPath/ElementNavFhirExtensions.cs +++ b/src/Hl7.Fhir.Base/FhirPath/ElementNavFhirExtensions.cs @@ -278,7 +278,7 @@ internal static P.Time BoundaryTime(P.Time time, long? precision, int minutes, i inParams = input.InstanceType switch { - "code" when input is ScopedNode sn => inParams.WithCode(code: sn.Value as string, context: sn.LocalLocation), + "code" when input is ScopedNode sn => inParams.WithCode(code: sn.Value as string, context: sn.LocalLocation, inferSystem: true), "Coding" => inParams.WithCoding(input.ParseCoding()), "CodeableConcept" => inParams.WithCodeableConcept(input.ParseCodeableConcept()), "string" or "System.String" => inParams.WithCode(code: input.Value as string, context: "No context available"), diff --git a/src/Hl7.Fhir.Base/Model/ParametersExtensions.cs b/src/Hl7.Fhir.Base/Model/ParametersExtensions.cs index af139c813d..30b06149c9 100644 --- a/src/Hl7.Fhir.Base/Model/ParametersExtensions.cs +++ b/src/Hl7.Fhir.Base/Model/ParametersExtensions.cs @@ -9,6 +9,7 @@ namespace Hl7.Fhir.Model public static class ParametersExtensions { private const string CODEATTRIBUTE = "code"; + private const string URLATTRIBUTE = "url"; private const string SYSTEMATTRIBUTE = "system"; private const string CONTEXTATTRIBUTE = "context"; @@ -39,12 +40,13 @@ internal static void CheckForValidityOfValidateCodeParams(this Parameters parame { parameters.NoDuplicates(); - //If a code is provided, a system or a context must be provided (http://hl7.org/fhir/valueset-operation-validate-code.html) - if (parameters.Parameter.Any(p => p.Name == CODEATTRIBUTE) && !(parameters.Parameter.Any(p => p.Name == SYSTEMATTRIBUTE) || + //This error was changed from system to url. See: https://chat.fhir.org/#narrow/channel/179202-terminology/topic/Required.20.24validate-code.20parameters/near/482250225 + //If a code is provided, a url or a context must be provided (http://hl7.org/fhir/valueset-operation-validate-code.html) + if (parameters.Parameter.Any(p => p.Name == CODEATTRIBUTE) && !(parameters.Parameter.Any(p => p.Name == URLATTRIBUTE) || parameters.Parameter.Any(p => p.Name == CONTEXTATTRIBUTE))) { //422 Unproccesable Entity - throw new FhirOperationException($"If a code is provided, a system or a context must be provided", (HttpStatusCode)422); + throw new FhirOperationException($"If a code is provided, a url or a context must be provided", (HttpStatusCode)422); } } } diff --git a/src/Hl7.Fhir.Base/Specification/Terminology/ValidateCodeParameters.cs b/src/Hl7.Fhir.Base/Specification/Terminology/ValidateCodeParameters.cs index ff3d6fadd5..6534a4d727 100644 --- a/src/Hl7.Fhir.Base/Specification/Terminology/ValidateCodeParameters.cs +++ b/src/Hl7.Fhir.Base/Specification/Terminology/ValidateCodeParameters.cs @@ -25,6 +25,7 @@ public class ValidateCodeParameters private readonly string _dateAttribute = "date"; private readonly string _abstractAttribute = "abstract"; private readonly string _displayLanguageAttribute = "displayLanguage"; + private readonly string _inferSystemAttribute = "inferSystem"; public ValidateCodeParameters(Parameters parameters) { @@ -41,6 +42,7 @@ public ValidateCodeParameters(Parameters parameters) Date = parameters.GetSingleValue(_dateAttribute); Abstract = parameters.GetSingleValue(_abstractAttribute); DisplayLanguage = parameters.GetSingleValue(_displayLanguageAttribute); + InferSystem = parameters.GetSingleValue(_inferSystemAttribute); } @@ -58,7 +60,7 @@ public ValidateCodeParameters WithValueSet(string url, string context = null, Re return this; } - public ValidateCodeParameters WithCode(string code = null, string system = null, string systemVersion = null, string display = null, string displayLanguage = null, string context = null) + public ValidateCodeParameters WithCode(string code = null, string system = null, string systemVersion = null, string display = null, string displayLanguage = null, string context = null, bool? inferSystem = null) { if (!string.IsNullOrWhiteSpace(code)) Code = new Code(code); if (!string.IsNullOrWhiteSpace(system)) System = new FhirUri(system); @@ -66,6 +68,7 @@ public ValidateCodeParameters WithCode(string code = null, string system = null, if (!string.IsNullOrWhiteSpace(display)) Display = new FhirString(display); if (!string.IsNullOrWhiteSpace(displayLanguage)) DisplayLanguage = new Code(displayLanguage); if (!string.IsNullOrWhiteSpace(context)) Context = new FhirUri(context); + if (inferSystem is { }) InferSystem = new FhirBoolean(inferSystem); return this; } @@ -151,6 +154,8 @@ public ValidateCodeParameters WithAbstract(bool? @abstract) /// public Code DisplayLanguage { get; private set; } + public FhirBoolean InferSystem { get; private set; } + /// /// /// @@ -160,8 +165,8 @@ public Parameters Build() var result = new Parameters(); if (Url is { }) result.Add(_urlAttribute, Url); - if (Context is { }) result.Add(_contextAttribute, Context); if (ValueSet is { }) result.Add(_valueSetAttribute, ValueSet); + if (Context is { }) result.Add(_contextAttribute, Context); if (ValueSetVersion is { }) result.Add(_valueSetVersionAttribute, ValueSetVersion); if (Code is { }) result.Add(_codeAttribute, Code); if (System is { }) result.Add(_systemAttribute, System); @@ -171,8 +176,8 @@ public Parameters Build() if (CodeableConcept is { }) result.Add(_codeableConceptAttribute, CodeableConcept); if (Date is { }) result.Add(_dateAttribute, Date); if (Abstract is { }) result.Add(_abstractAttribute, Abstract); - if (DisplayLanguage is { }) result.Add(_displayAttribute, DisplayLanguage); - + if (DisplayLanguage is { }) result.Add(_displayLanguageAttribute, DisplayLanguage); + if (InferSystem is { }) result.Add(_inferSystemAttribute, InferSystem); return result; } } diff --git a/src/Hl7.Fhir.Specification.Shared.Tests/Source/TerminologyTests.cs b/src/Hl7.Fhir.Specification.Shared.Tests/Source/TerminologyTests.cs index f6d41e5958..327ceefc19 100644 --- a/src/Hl7.Fhir.Specification.Shared.Tests/Source/TerminologyTests.cs +++ b/src/Hl7.Fhir.Specification.Shared.Tests/Source/TerminologyTests.cs @@ -757,6 +757,52 @@ void expandAction(string url) } } + [Fact] + public void TestValidateCodeParametersCode() + { + var parameters = new ValidateCodeParameters() + .WithCode("bar", "http://foo.com", "1.0.4", "barDisplay", "nl-NL", "Patient.gender", true); + + parameters.Code.Value.Should().Be("bar"); + parameters.System.Value.Should().Be("http://foo.com"); + parameters.SystemVersion.Value.Should().Be("1.0.4"); + parameters.DisplayLanguage.Value.Should().Be("nl-NL"); + parameters.Display.Value.Should().Be("barDisplay"); + parameters.Context.Value.Should().Be("Patient.gender"); + parameters.InferSystem.Value.Should().Be(true); + + var paramResource = parameters.Build(); + + paramResource.Parameter.Should().HaveCount(7); + paramResource.Parameter.Should().ContainSingle(p => p.Name == "code" && ((Code)p.Value).Value == "bar"); + paramResource.Parameter.Should().ContainSingle(p => p.Name == "system" && ((FhirUri)p.Value).Value == "http://foo.com"); + paramResource.Parameter.Should().ContainSingle(p => p.Name == "systemVersion" && ((FhirString)p.Value).Value == "1.0.4"); + paramResource.Parameter.Should().ContainSingle(p => p.Name == "display" && ((FhirString)p.Value).Value == "barDisplay"); + paramResource.Parameter.Should().ContainSingle(p => p.Name == "displayLanguage" && ((Code)p.Value).Value == "nl-NL"); + paramResource.Parameter.Should().ContainSingle(p => p.Name == "context" && ((FhirUri)p.Value).Value == "Patient.gender"); + paramResource.Parameter.Should().ContainSingle(p => p.Name == "inferSystem" && ((FhirBoolean)p.Value).Value == true); + } + + [Fact] + public void TestValidateCodeParametersValueSet() + { + var parameters = new ValidateCodeParameters() + .WithValueSet("http://foo.bar", "Patient.gender", new ValueSet(), "1.0.4"); + + parameters.Url.Value.Should().Be("http://foo.bar"); + parameters.Context.Value.Should().Be("Patient.gender"); + parameters.ValueSet.Should().NotBeNull(); + parameters.ValueSetVersion.Value.Should().Be("1.0.4"); + + var paramResource = parameters.Build(); + + paramResource.Parameter.Should().HaveCount(4); + paramResource.Parameter.Should().ContainSingle(p => p.Name == "url" && ((FhirUri)p.Value).Value == "http://foo.bar"); + paramResource.Parameter.Should().ContainSingle(p => p.Name == "context" && ((FhirUri)p.Value).Value == "Patient.gender"); + paramResource.Parameter.Should().ContainSingle(p => p.Name == "valueSet" && ((ValueSet)p.Resource) != null); + paramResource.Parameter.Should().ContainSingle(p => p.Name == "valueSetVersion" && ((FhirString)p.Value).Value == "1.0.4"); + } + #region helper functions private static Tasks.Task validateCodedValue(ITerminologyService service, string url = null, string context = null, string code = null, diff --git a/src/Hl7.Fhir.Support.Tests/Specification/LanguageTerminologyServiceTests.cs b/src/Hl7.Fhir.Support.Tests/Specification/LanguageTerminologyServiceTests.cs index cf82805c3c..88af45fbc1 100644 --- a/src/Hl7.Fhir.Support.Tests/Specification/LanguageTerminologyServiceTests.cs +++ b/src/Hl7.Fhir.Support.Tests/Specification/LanguageTerminologyServiceTests.cs @@ -36,7 +36,7 @@ public async Task LanguageValidationTest() result = await _service.ValueSetValidateCode(parameters); result.Parameter.Should().Contain(p => p.Name == "result") .Subject.Value.Should().BeEquivalentTo(new FhirBoolean(true)); - + parameters = new ValidateCodeParameters() .WithValueSet(LANGUAGE_VS) .WithCode(code: "fr-CH", context: "context") @@ -59,7 +59,7 @@ public async Task LanguageValidationTest() .Build(); validateCode = async () => await _service.ValueSetValidateCode(parameters); - await validateCode.Should().ThrowAsync().WithMessage("If a code is provided, a system or a context must be provided"); + await validateCode.Should().ThrowAsync().WithMessage("If a code is provided, a url or a context must be provided"); parameters = new ValidateCodeParameters() .WithValueSet(LANGUAGE_VS) diff --git a/src/Hl7.Fhir.Support.Tests/Specification/MimeTypeTerminologyServiceTests.cs b/src/Hl7.Fhir.Support.Tests/Specification/MimeTypeTerminologyServiceTests.cs index 95e2d79fa8..58b373dd1c 100644 --- a/src/Hl7.Fhir.Support.Tests/Specification/MimeTypeTerminologyServiceTests.cs +++ b/src/Hl7.Fhir.Support.Tests/Specification/MimeTypeTerminologyServiceTests.cs @@ -52,7 +52,7 @@ public async Task MimeTypeValidationTest() .Build(); validateCode = async () => await _service.ValueSetValidateCode(parameters); - await validateCode.Should().ThrowAsync().WithMessage("If a code is provided, a system or a context must be provided"); + await validateCode.Should().ThrowAsync().WithMessage("If a code is provided, a url or a context must be provided"); parameters = new ValidateCodeParameters() .WithValueSet(MIMETYPEVS)