Skip to content

Commit

Permalink
Merge pull request #2968 from FirelyTeam/bugfix/2854-fix-validate-code
Browse files Browse the repository at this point in the history
Bugfix/2854 fix validate code
  • Loading branch information
mmsmits authored Nov 22, 2024
2 parents cf1e39a + cb9cd6a commit 40ae960
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 11 deletions.
14 changes: 14 additions & 0 deletions src/Hl7.Fhir.Base/CompatibilitySuppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,18 @@
<Left>lib/netstandard2.0/Hl7.Fhir.Base.dll</Left>
<Right>lib/net8.0/Hl7.Fhir.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Hl7.Fhir.Specification.Terminology.ValidateCodeParameters.WithCode(System.String,System.String,System.String,System.String,System.String,System.String)</Target>
<Left>lib/net8.0/Hl7.Fhir.Base.dll</Left>
<Right>lib/net8.0/Hl7.Fhir.Base.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Hl7.Fhir.Specification.Terminology.ValidateCodeParameters.WithCode(System.String,System.String,System.String,System.String,System.String,System.String)</Target>
<Left>lib/netstandard2.0/Hl7.Fhir.Base.dll</Left>
<Right>lib/netstandard2.0/Hl7.Fhir.Base.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
</Suppressions>
2 changes: 1 addition & 1 deletion src/Hl7.Fhir.Base/FhirPath/ElementNavFhirExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
8 changes: 5 additions & 3 deletions src/Hl7.Fhir.Base/Model/ParametersExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -41,6 +42,7 @@ public ValidateCodeParameters(Parameters parameters)
Date = parameters.GetSingleValue<FhirDateTime>(_dateAttribute);
Abstract = parameters.GetSingleValue<FhirBoolean>(_abstractAttribute);
DisplayLanguage = parameters.GetSingleValue<Code>(_displayLanguageAttribute);
InferSystem = parameters.GetSingleValue<FhirBoolean>(_inferSystemAttribute);
}


Expand All @@ -58,14 +60,15 @@ 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);
if (!string.IsNullOrWhiteSpace(systemVersion)) SystemVersion = new FhirString(systemVersion);
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;
}

Expand Down Expand Up @@ -151,6 +154,8 @@ public ValidateCodeParameters WithAbstract(bool? @abstract)
/// </summary>
public Code DisplayLanguage { get; private set; }

public FhirBoolean InferSystem { get; private set; }

/// <summary>
///
/// </summary>
Expand All @@ -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);
Expand All @@ -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;
}
}
Expand Down
46 changes: 46 additions & 0 deletions src/Hl7.Fhir.Specification.Shared.Tests/Source/TerminologyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Parameters> validateCodedValue(ITerminologyService service, string url = null, string context = null, string code = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -59,7 +59,7 @@ public async Task LanguageValidationTest()
.Build();

validateCode = async () => await _service.ValueSetValidateCode(parameters);
await validateCode.Should().ThrowAsync<FhirOperationException>().WithMessage("If a code is provided, a system or a context must be provided");
await validateCode.Should().ThrowAsync<FhirOperationException>().WithMessage("If a code is provided, a url or a context must be provided");

parameters = new ValidateCodeParameters()
.WithValueSet(LANGUAGE_VS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public async Task MimeTypeValidationTest()
.Build();

validateCode = async () => await _service.ValueSetValidateCode(parameters);
await validateCode.Should().ThrowAsync<FhirOperationException>().WithMessage("If a code is provided, a system or a context must be provided");
await validateCode.Should().ThrowAsync<FhirOperationException>().WithMessage("If a code is provided, a url or a context must be provided");

parameters = new ValidateCodeParameters()
.WithValueSet(MIMETYPEVS)
Expand Down

0 comments on commit 40ae960

Please sign in to comment.