Skip to content

Commit

Permalink
Passing the Terminology Service to the FhirEvaluationContext, so Fhir…
Browse files Browse the repository at this point in the history
…Path van validate codes with valuesets.
  • Loading branch information
marcovisserFurore committed Sep 14, 2023
1 parent 8878276 commit 7501c6d
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 48 deletions.
32 changes: 31 additions & 1 deletion src/Firely.Fhir.Validation/Impl/FhirPathValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

using Hl7.Fhir.ElementModel;
using Hl7.Fhir.FhirPath;
using Hl7.Fhir.Model;
using Hl7.Fhir.Specification.Terminology;
using Hl7.Fhir.Support;
using Hl7.Fhir.Utility;
using Hl7.Fhir.Validation;
Expand All @@ -14,6 +16,7 @@
using Newtonsoft.Json.Linq;
using System;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using static Hl7.Fhir.Model.OperationOutcome;

namespace Firely.Fhir.Validation
Expand Down Expand Up @@ -99,7 +102,11 @@ protected override (bool, ResultReport?) RunInvariant(ITypedElement input, Valid
try
{
var node = input as ScopedNode ?? new ScopedNode(input);
return (predicate(input, new EvaluationContext(node.ResourceContext), vc), null);
var context = new FhirEvaluationContext(node.ResourceContext)
{
TerminologyService = new ValidateCodeServiceToTerminologyServiceAdapter(vc.ValidateCodeService)
};
return (predicate(input, context, vc), null);
}
catch (Exception e)
{
Expand Down Expand Up @@ -152,5 +159,28 @@ private bool predicate(ITypedElement input, EvaluationContext context, Validatio

return compiledExpression.IsTrue(input, context);
}

/// <summary>
/// An adapter between the <see cref="ICodeValidationTerminologyService"/> and <see cref="ITerminologyService"/>. Be careful to use
/// this adapter, because it does only implement the <see cref="ICodeValidationTerminologyService"/> methods. The other methods, like those
/// from <see cref="IMappingTerminologyService"/> are not implemented will raise an exception.
/// </summary>
private class ValidateCodeServiceToTerminologyServiceAdapter : ITerminologyService
{
private readonly ICodeValidationTerminologyService _service;

public ValidateCodeServiceToTerminologyServiceAdapter(ICodeValidationTerminologyService service)
{
_service = service;
}

public Task<Resource> Closure(Parameters parameters, bool useGet = false) => throw new NotImplementedException();
public Task<Parameters> CodeSystemValidateCode(Parameters parameters, string? id = null, bool useGet = false) => throw new NotImplementedException();
public Task<Resource> Expand(Parameters parameters, string? id = null, bool useGet = false) => throw new NotImplementedException();
public Task<Parameters> Lookup(Parameters parameters, bool useGet = false) => throw new NotImplementedException();
public Task<Parameters> Subsumes(Parameters parameters, string? id = null, bool useGet = false) => _service.Subsumes(parameters, id, useGet);
public Task<Parameters> Translate(Parameters parameters, string? id = null, bool useGet = false) => throw new NotImplementedException();
public Task<Parameters> ValueSetValidateCode(Parameters parameters, string? id = null, bool useGet = false) => _service.ValueSetValidateCode(parameters, id, useGet);
}
}
}
46 changes: 0 additions & 46 deletions src/Firely.Fhir.Validation/Schema/FhirEvaluationContext.cs

This file was deleted.

45 changes: 45 additions & 0 deletions test/Firely.Fhir.Validation.Tests/Impl/FhirPathValidatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@

using FluentAssertions;
using Hl7.Fhir.ElementModel;
using Hl7.Fhir.FhirPath;
using Hl7.Fhir.Model;
using Hl7.Fhir.Specification.Terminology;
using Hl7.Fhir.Support;
using Hl7.FhirPath;
using Hl7.FhirPath.Expressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static Hl7.Fhir.Model.OperationOutcome;
using Task = System.Threading.Tasks.Task;

namespace Firely.Fhir.Validation.Tests
{
Expand All @@ -24,6 +30,7 @@ public FhirPathValidatorTests()
{
var symbolTable = new SymbolTable();
symbolTable.AddStandardFP();
symbolTable.AddFhirExtensions();
_fpCompiler = new FhirPathCompiler(symbolTable);
}

Expand Down Expand Up @@ -94,5 +101,43 @@ public void ValidateNullableInput()

result?.IsSuccessful.Should().Be(false, because: "FhirPath epressions resulting in null should return false in the FhirPathValidator");
}

[TestMethod]
public void ValidateMemberOf()
{
var validatable = new FhirPathValidator("memberof", "memberOf('http://hl7.org/fhir/ValueSet/iso3166-1-2')", "This expression should use FP memberOf()", IssueSeverity.Error, false);

var input = ElementNodeAdapter.Root("Coding");
input.Add("system", "http://hl7.org/fhir/ValueSet/iso3166-1-2", "uri");
input.Add("code", "NL", "string");

var minimalContextWithFp = ValidationContext.BuildMinimalContext(fpCompiler: _fpCompiler);
minimalContextWithFp.ValidateCodeService = new AlwaysSuccessfulTS();
var result = validatable.Validate(input, minimalContextWithFp);

result?.Warnings.Should().BeEmpty(because: "There should be no warnings about the terminology service.");
result?.IsSuccessful.Should().BeTrue();
}

/// <summary>
/// A CodeValidationTerminologyService that always return a success with the method <see cref="ValueSetValidateCode"/>. Only meant for
/// testing purposes.
/// </summary>
private class AlwaysSuccessfulTS : ICodeValidationTerminologyService
{
public Task<Parameters> Subsumes(Parameters parameters, string? id = null, bool useGet = false) =>
throw new System.NotImplementedException();

public Task<Parameters> ValueSetValidateCode(Parameters parameters, string? id = null, bool useGet = false) =>
Task.FromResult(new Parameters
{
Parameter = new List<Parameters.ParameterComponent>() {
new Parameters.ParameterComponent()
{
Name = "result",
Value = new FhirBoolean(true)}
}
});
}
}
}

0 comments on commit 7501c6d

Please sign in to comment.