diff --git a/src/Firely.Fhir.Validation/Impl/PatternValidator.cs b/src/Firely.Fhir.Validation/Impl/PatternValidator.cs index 5e78e0a9..57b53f23 100644 --- a/src/Firely.Fhir.Validation/Impl/PatternValidator.cs +++ b/src/Firely.Fhir.Validation/Impl/PatternValidator.cs @@ -54,12 +54,11 @@ ResultReport IValidatable.Validate(PocoNode input, ValidationSettings _, Validat if (input.Matches(PatternValue)) return ResultReport.SUCCESS; - var severity = OperationOutcome.IssueSeverity.Error; - // element with no value and extension - might have a special meaning, so let's make it into warning instead + // element with no value and extension is valid per spec if (input is PrimitiveNode && input.GetValue() is null && (input.Poco as IExtendable)?.HasExtensions() is true) - severity = OperationOutcome.IssueSeverity.Warning; + return ResultReport.SUCCESS; - return new IssueAssertion(Issue.CONTENT_DOES_NOT_MATCH_PATTERN_VALUE.Code, $"Value '{displayValue(input)}' does not match pattern '{displayValue(PatternValue)}'", severity, OperationOutcome.IssueType.Invalid) + return new IssueAssertion(Issue.CONTENT_DOES_NOT_MATCH_PATTERN_VALUE.Code, $"Value '{displayValue(input)}' does not match pattern '{displayValue(PatternValue)}'", OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Invalid) .AsResult(s, input, nameof(PatternValidator)); static string displayValue(ITypedElement te) => diff --git a/src/Firely.Fhir.Validation/Impl/RegExValidator.cs b/src/Firely.Fhir.Validation/Impl/RegExValidator.cs index 90004b35..8836d49e 100644 --- a/src/Firely.Fhir.Validation/Impl/RegExValidator.cs +++ b/src/Firely.Fhir.Validation/Impl/RegExValidator.cs @@ -60,13 +60,12 @@ internal override ResultReport BasicValidate(PocoNode input, ValidationSettings if (value is not null && _regex.IsMatch(value)) return ResultReport.SUCCESS; - var severity = OperationOutcome.IssueSeverity.Error; - // element with no value and extension - might have a special meaning, so let's make it into warning instead + // element with no value and extension is valid per spec if (value is null && (input.Poco as IExtendable)?.HasExtensions() is true) - severity = OperationOutcome.IssueSeverity.Warning; + return ResultReport.SUCCESS; - return new IssueAssertion(Issue.CONTENT_ELEMENT_INVALID_PRIMITIVE_VALUE.Code, $"Value '{value}' does not match regex '{Pattern}'", severity, OperationOutcome.IssueType.Invalid) - .AsResult(s, input, nameof (RegExValidator)); + return new IssueAssertion(Issue.CONTENT_ELEMENT_INVALID_PRIMITIVE_VALUE.Code, $"Value '{value}' does not match regex '{Pattern}'", OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Invalid) + .AsResult(s, input, nameof(RegExValidator)); } private static string? toStringRepresentation(PocoNode vp) diff --git a/test/Firely.Fhir.Validation.Compilation.Tests.Shared/FhirTestCases b/test/Firely.Fhir.Validation.Compilation.Tests.Shared/FhirTestCases index 7eac7b9e..e33c0add 160000 --- a/test/Firely.Fhir.Validation.Compilation.Tests.Shared/FhirTestCases +++ b/test/Firely.Fhir.Validation.Compilation.Tests.Shared/FhirTestCases @@ -1 +1 @@ -Subproject commit 7eac7b9e294adf5c1053553ef424a8b64d8ed044 +Subproject commit e33c0addd9ecdba237b0ac7a37c480026c9a6c6e diff --git a/test/Firely.Fhir.Validation.Tests/Impl/PatternValidatorTests.cs b/test/Firely.Fhir.Validation.Tests/Impl/PatternValidatorTests.cs index 493196aa..dec70af3 100644 --- a/test/Firely.Fhir.Validation.Tests/Impl/PatternValidatorTests.cs +++ b/test/Firely.Fhir.Validation.Tests/Impl/PatternValidatorTests.cs @@ -98,6 +98,12 @@ internal class PatternValidatorData : BasicValidatorDataAttribute new CodeableConcept() { Coding = [new() { CodeElement = new() { Extension = [new("http://test", new FhirString("Test"))]}}]}.ToPocoNode(), false, Issue.CONTENT_DOES_NOT_MATCH_PATTERN_VALUE, "Complex inputs primitive entry with extension and no value will still generate an error." }; + yield return new object?[] + { + new PatternValidator(new CodeableConcept("test-system", "test-code").ToPocoNode()), + new CodeableConcept() { Extension = [new("http://test", new FhirString("Test"))] }.ToPocoNode(), + false, Issue.CONTENT_DOES_NOT_MATCH_PATTERN_VALUE, "Complex inputs primitive entry with extension and no value will still generate an error." + }; } } diff --git a/test/Firely.Fhir.Validation.Tests/Impl/RegExValidatorTests.cs b/test/Firely.Fhir.Validation.Tests/Impl/RegExValidatorTests.cs index b336c2cd..d806bc83 100644 --- a/test/Firely.Fhir.Validation.Tests/Impl/RegExValidatorTests.cs +++ b/test/Firely.Fhir.Validation.Tests/Impl/RegExValidatorTests.cs @@ -28,6 +28,13 @@ internal class RegExValidatorData : BasicValidatorDataAttribute new RegExValidator(@"^((\+31)|(0031)|0)(\(0\)|)(\d{1,3})(\s|\-|)(\d{8}|\d{4}\s\d{4}|\d{2}\s\d{2}\s\d{2}\s\d{2})$"), PocoNode.ForPrimitive("+31(0)612345678"), true, null, "result must be true (Dutch phonenumber)" }; + + yield return new object?[] + { + new RegExValidator("[0-9]"), + new FhirString { Extension = [new("http://example.org/ext", new FhirString("test"))] }.ToPocoNode(), + true, null, "extension-only primitive (no value) must pass regex validation" + }; } }