diff --git a/src/Firely.Fhir.Validation/Impl/MinMaxValueValidator.cs b/src/Firely.Fhir.Validation/Impl/MinMaxValueValidator.cs
index c8fcb7d9..958db772 100644
--- a/src/Firely.Fhir.Validation/Impl/MinMaxValueValidator.cs
+++ b/src/Firely.Fhir.Validation/Impl/MinMaxValueValidator.cs
@@ -73,23 +73,38 @@ public MinMaxValueValidator(ITypedElement limit, ValidationMode minMaxType)
Limit = limit ?? throw new ArgumentNullException(nameof(limit), $"{nameof(limit)} cannot be null");
MinMaxType = minMaxType;
- if (Any.TryConvert(Limit.Value, out _minMaxAnyValue!) == false)
- throw new IncorrectElementDefinitionException($"Cannot convert the limit value ({Limit.Value}) to a comparable primitive.");
+ if (limit.InstanceType == "Quantity") //Quantity is the only non primitive that can be used as min/max value;
+ {
+
+ var quantity = limit.ParseQuantity()?.ToQuantity()!; // first parse to a Hl7.Model Qunatity, which we convert to a Hl7.Fhir.ElementModel.Types Quantity
+ if (quantity is not null)
+ {
+ _minMaxAnyValue = quantity!;
+ }
+
+ else
+ throw new IncorrectElementDefinitionException($"Cannot convert the limit value ({limit.Value}) to a quantity for comparison.");
+ }
+ else
+ {
+ if (Any.TryConvert(Limit.Value, out _minMaxAnyValue!) == false)
+ throw new IncorrectElementDefinitionException($"Cannot convert the limit value ({Limit.Value}) to a comparable primitive.");
+
+ // Min/max are only defined for ordered types
+ if (!isOrderedType(_minMaxAnyValue))
+ throw new IncorrectElementDefinitionException($"{Limit.Name} was given in ElementDefinition, but type '{Limit.InstanceType}' is not an ordered type");
+
+ static bool isOrderedType(Any value) => value is ICqlOrderable;
+ }
_comparisonOutcome = MinMaxType == ValidationMode.MinValue ? -1 : 1;
_comparisonLabel = _comparisonOutcome == -1 ? "smaller than" :
_comparisonOutcome == 0 ? "equal to" :
"larger than";
_comparisonIssue = _comparisonOutcome == -1 ? Issue.CONTENT_ELEMENT_PRIMITIVE_VALUE_TOO_SMALL :
- Issue.CONTENT_ELEMENT_PRIMITIVE_VALUE_TOO_LARGE;
-
+ Issue.CONTENT_ELEMENT_PRIMITIVE_VALUE_TOO_LARGE;
_minMaxLabel = $"{MinMaxType.GetLiteral().Uncapitalize()}";
- // Min/max are only defined for ordered types
- if (!isOrderedType(_minMaxAnyValue))
- throw new IncorrectElementDefinitionException($"{Limit.Name} was given in ElementDefinition, but type '{Limit.InstanceType}' is not an ordered type");
-
- static bool isOrderedType(Any value) => value is ICqlOrderable;
}
///
@@ -98,10 +113,24 @@ public MinMaxValueValidator(long limit, ValidationMode minMaxType) : this(Elemen
///
ResultReport IValidatable.Validate(IScopedNode input, ValidationSettings _, ValidationState s)
{
- if (!Any.TryConvert(input.Value, out var instanceValue))
+ Any instanceValue;
+ if (input.InstanceType == "Quantity")
+ {
+ var quantity = input.ParseQuantity()?.ToQuantity()!; // first parse to a Hl7.Model Qunatity, which we convert to a Hl7.Fhir.ElementModel.Types Quantity
+ if (quantity is not null)
+ {
+ instanceValue = quantity;
+ }
+ else
+ {
+ return new IssueAssertion(Issue.CONTENT_ELEMENT_PRIMITIVE_VALUE_NOT_COMPARABLE,
+ $"Value '{input.Value ?? input}' cannot be compared with {_minMaxAnyValue})").AsResult(s);
+ }
+ }
+ else if (!Any.TryConvert(input.Value, out instanceValue!))
{
return new IssueAssertion(Issue.CONTENT_ELEMENT_PRIMITIVE_VALUE_NOT_COMPARABLE,
- $"Value '{input.Value}' cannot be compared with {Limit.Value})").AsResult(s);
+ $"Value '{input.Value}' cannot be compared with {_minMaxAnyValue})").AsResult(s);
}
try
@@ -113,17 +142,17 @@ ResultReport IValidatable.Validate(IScopedNode input, ValidationSettings _, Vali
(false, true) => 1,
_ => 0
};
-
+
if (intResult == _comparisonOutcome)
{
- return new IssueAssertion(_comparisonIssue, $"Value '{input.Value}' is {_comparisonLabel} {Limit.Value})")
+ return new IssueAssertion(_comparisonIssue, $"Value '{instanceValue}' is {_comparisonLabel} {_minMaxAnyValue})")
.AsResult(s);
}
}
catch (ArgumentException)
{
return new IssueAssertion(Issue.CONTENT_ELEMENT_PRIMITIVE_VALUE_NOT_COMPARABLE,
- $"Value '{input.Value}' cannot be compared with {Limit.Value})")
+ $"Value '{instanceValue}' cannot be compared with {_minMaxAnyValue})")
.AsResult(s);
}
diff --git a/test/Firely.Fhir.Validation.Compilation.Tests.Shared/FhirTestCases b/test/Firely.Fhir.Validation.Compilation.Tests.Shared/FhirTestCases
index 8c5a7331..8068ff26 160000
--- a/test/Firely.Fhir.Validation.Compilation.Tests.Shared/FhirTestCases
+++ b/test/Firely.Fhir.Validation.Compilation.Tests.Shared/FhirTestCases
@@ -1 +1 @@
-Subproject commit 8c5a7331020a580da9e2a0b19c941221c390e4d7
+Subproject commit 8068ff2636300fe1299af6c62c47247839688786
diff --git a/test/Firely.Fhir.Validation.Tests/Impl/MinMaxValueValidatorTests.cs b/test/Firely.Fhir.Validation.Tests/Impl/MinMaxValueValidatorTests.cs
index 52dfada7..ad52f7af 100644
--- a/test/Firely.Fhir.Validation.Tests/Impl/MinMaxValueValidatorTests.cs
+++ b/test/Firely.Fhir.Validation.Tests/Impl/MinMaxValueValidatorTests.cs
@@ -8,7 +8,6 @@
using FluentAssertions;
using Hl7.Fhir.ElementModel;
-using Hl7.Fhir.ElementModel.Types;
using Hl7.Fhir.Model;
using Hl7.Fhir.Support;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -116,6 +115,42 @@ public void InvalidConstructors()
action.Should().Throw();
}
+ [TestMethod]
+ public void QuantityComparison()
+ {
+ var maxValue = new Hl7.Fhir.Model.Quantity
+ {
+ Value = 4,
+ Unit = "kg",
+ System = "http://unitsofmeasure.org",
+ Code = "kg"
+ }.ToTypedElement(ModelInfo.ModelInspector);
+
+ var assertion = new MinMaxValueValidator(maxValue, MinMaxValueValidator.ValidationMode.MaxValue);
+
+ assertion.Should().NotBeNull();
+ assertion.Limit.Should().BeAssignableTo();
+
+ var quantityCorrect = new Quantity
+ {
+ Value = 3,
+ Unit = "kg",
+ System = "http://unitsofmeasure.org",
+ Code = "kg"
+ }.ToTypedElement(ModelInfo.ModelInspector);
+
+ base.BasicValidatorTestcases(assertion, quantityCorrect, true, null, "");
+
+ var quantityIncorrect = new Quantity
+ {
+ Value = 5,
+ Unit = "kg",
+ System = "http://unitsofmeasure.org",
+ Code = "kg"
+ }.ToTypedElement(ModelInfo.ModelInspector);
+ base.BasicValidatorTestcases(assertion, quantityIncorrect, false, Issue.CONTENT_ELEMENT_PRIMITIVE_VALUE_TOO_LARGE, "");
+ }
+
[TestMethod]
public void CorrectConstructor()
{