Stream: conformance
Topic: Validator problem for compound enableWhen clause?
Morten Ernebjerg (Apr 28 2020 at 05:27):
I am using the (4.2.20-SNAPSHOT) Java validator to validate QuestionnaireResponses against a Questionnaire. One of the questions (call it N2) should only be shown if at least one of two previous questions (N0 & N1) have been answered with a specific answer. On the other hand, if N2 is enabled, it must be answered. The R4 enableWhen documentation says
(...) treat "enableWhen"s as being joined by an "or" clause. This element is a modifier because if enableWhen is present for an item, "required" is ignored unless one of the enableWhen conditions is met.
So I did the following
{
"resourceType": "Questionnaire",
"url": "http://example.com/qexampel",
"status": "draft",
"item": [{
"type": "integer",
"linkId": "N0"
},
{
"type": "integer",
"linkId": "N1"
},
{
"type": "integer",
"required": true,
"linkId": "N2",
"enableWhen": [{
"question": "N0",
"operator": "=",
"answerInteger": 1
},
{
"question": "N1",
"operator": "=",
"answerInteger": 1
}
]
}
]
}
The following should now be a valid answer because N2 should not be enabled:
{
"resourceType": "QuestionnaireResponse",
"questionnaire": "http://example.com/qexampel",
"status": "completed",
"item": [{
"linkId": "N0",
"answer": [{
"valueInteger": 0
}]
},
{
"linkId": "N1",
"answer": [{
"valueInteger": 0
}]
}
]
}
However, the validator says
*FAILURE* validating qtest/test.questionnaireresponse.json: error:1 warn:0 info:0
Error @ QuestionnaireResponse (line 1, col2) : No response answer found for required item "N2"
If I remove one of the conditions in the enableWHen, the error disappears. Is there an issue with how the validator handles multiple enableWhen conditions or did I read the specs wrong?
Lloyd McKenzie (Apr 28 2020 at 13:43):
@Grahame Grieve - do we still have an issue with evaluating 'required' elements in the presence of enableWhen?
Patrick Werner (Apr 28 2020 at 14:51):
@Morten Ernebjerg have a look at Questionnaire.item.enableBehavior. This defines this behaviour.
Patrick Werner (Apr 28 2020 at 14:52):
The "or" statement in description is only valid if you are evaluating repeating elements. Then only one repetition has to be true
Patrick Werner (Apr 28 2020 at 14:53):
The description text here should be improved. Do you mind opening a JIRA Ticket for this @Morten Ernebjerg ?
Morten Ernebjerg (Apr 28 2020 at 15:18):
@Patrick Werner ah, thanks! I did indeed not spot this because I thought the formulation in the documentation of Questionnaire.item.enableWhen clearly specified that it was always an OR:
If multiple repetitions of this extension are present, the item should be enabled when the condition for any of the repetitions is true. I.e. treat "enableWhen"s as being joined by an "or" clause.
I will put in a tickets (might take a few hours though, busy days...)(
@Grahame Grieve When I validate the Questionnaire
given above against the base spec, I get no errors so it seems constraint que-12 (enableWhen.count() > 2 implies enableBehavior.exists()
) is not enforced.
Morten Ernebjerg (Apr 28 2020 at 15:21):
And actually, my initial question still lingers. Whether or not one takes AND or OR for the enableWhen, the condition is not met in the above example --> required: true
on conditional question should be ignored --> response should be valid. Or...?
Morten Ernebjerg (Apr 28 2020 at 15:25):
But adding "enableBehavior": "any"
does it indeed make the above come out without errors :+1:
Patrick Werner (Apr 28 2020 at 16:23):
You are mixing twoOR
: the one you are refering to only applies to repeating items. Imagine asking for all medication of a patient in a repeatable item. Adding a enable when if the patient takes a certain medication will look in every reported repetition/medication. If one of these matches (OR) then the enableWhen is triggered.
Patrick Werner (Apr 28 2020 at 16:24):
enableBehavior changes the behavior in the case you have multiple enableWhens attached to an item.
Patrick Werner (Apr 28 2020 at 16:24):
But yes guidance, especially on the enableWhen element would be nice (made the same mis-assumption in the past).
Patrick Werner (Apr 28 2020 at 16:25):
So the tracker would be for having better guidance
Grahame Grieve (Apr 29 2020 at 03:49):
que-12 has an error. It should be :
(enableWhen.count() >= 2 implies enableBehavior.exists())
Grahame Grieve (Apr 29 2020 at 03:58):
so it shouldn't make any difference whether it's all or any
Grahame Grieve (Apr 29 2020 at 04:23):
I hacked the validator to make that work
Morten Ernebjerg (Apr 29 2020 at 14:24):
@Patrick Werner Ah OK, now I see what was meant by "multiple repetitions".... I created ticket #FHIR-26993 for this.
Morten Ernebjerg (May 14 2020 at 08:51):
@Patrick Werner Back again :slight_smile: I was wondering what the behaviour was for STU3 for the case that I specify 2 conditions in enableWhen
that refer to different (non-repeatable questions). Does it behave like enableBehaviour: "any"
or enableBehaviour: "all"
? I tried to surmise it from the R3 --> R4 maps, but as far as I can tell, there enableBehaviour
is not included anywhere, despite the fact that it is required if there are multiple enableWhen
conditions.
Grahame Grieve (May 14 2020 at 11:08):
this appears to be the relevant behavior:
public boolean checkConditionResults(List<EnableWhenResult> evaluationResults, QuestionnaireItemComponent questionnaireItem) {
if ((questionnaireItem.hasEnableBehavior() && questionnaireItem.getEnableBehavior() == EnableWhenBehavior.ANY) || evaluationResults.size() == 1) {
return evaluationResults.stream().anyMatch(EnableWhenResult::isEnabled);
}
if (questionnaireItem.hasEnableBehavior() && questionnaireItem.getEnableBehavior() == EnableWhenBehavior.ALL) {
return evaluationResults.stream().allMatch(EnableWhenResult::isEnabled);
}
//TODO: Throw exception? enableBehavior is mandatory when there are multiple conditions
return true;
}
Grahame Grieve (May 14 2020 at 11:08):
in otherwords: an exception. Do you want to make a test case (Q/QR combination) that I can add to the unit tests ?
Morten Ernebjerg (May 14 2020 at 13:33):
@Grahame Grieve If I read this correctly, it is code from the R4 validation, right? (here). So is the point that when validating an STU3 Q/QR pair, it comes through here as well and always returns true
because there is never any enableBehaviour
?
I'd be happy to add an STU3 test case for this - where do I submit it?
Grahame Grieve (May 14 2020 at 18:29):
that's actually the R5 code. But submit me an R3 test case. You can just send them to me, or make an issue or a PR against https://github.com/FHIR/fhir-test-cases
Morten Ernebjerg (May 15 2020 at 13:36):
OK, will go via the repo.
BTW I see that when you convert an STU3 questionnaire to an R4 one with the validator, it seems to insert enableBehaviour: "any"
for all questions. Yet I cannot see that in the STU3 --> R4 map in the Questionnaire documentation - am I missing smt. or is the validator using a different map?
Morten Ernebjerg (May 15 2020 at 14:04):
This is conversion the -native
option which, I suppose, might just about answer my question for me... Without this option, I get an error (for a minimal 3-question example)
Exception in thread "main" java.lang.Error: Cannot set property operator on enableWhen
at org.hl7.fhir.r5.elementmodel.Element.setProperty(Element.java:378)
at org.hl7.fhir.r5.utils.StructureMapUtilities.processTarget(StructureMapUtilities.java:1827)
at org.hl7.fhir.r5.utils.StructureMapUtilities.executeRule(StructureMapUtilities.java:1412)
at org.hl7.fhir.r5.utils.StructureMapUtilities.executeGroup(StructureMapUtilities.java:1399)
at org.hl7.fhir.r5.utils.StructureMapUtilities.executeDependency(StructureMapUtilities.java:1458)
at org.hl7.fhir.r5.utils.StructureMapUtilities.executeRule(StructureMapUtilities.java:1420)
at org.hl7.fhir.r5.utils.StructureMapUtilities.executeGroup(StructureMapUtilities.java:1399)
at org.hl7.fhir.r5.utils.StructureMapUtilities.executeDependency(StructureMapUtilities.java:1458)
at org.hl7.fhir.r5.utils.StructureMapUtilities.executeRule(StructureMapUtilities.java:1420)
at org.hl7.fhir.r5.utils.StructureMapUtilities.executeGroup(StructureMapUtilities.java:1399)
at org.hl7.fhir.r5.utils.StructureMapUtilities.transform(StructureMapUtilities.java:1361)
at org.hl7.fhir.validation.ValidationEngine.transformVersion(ValidationEngine.java:1754)
at org.hl7.fhir.validation.cli.services.ValidationService.transformVersion(ValidationService.java:157)
at org.hl7.fhir.validation.Validator.main(Validator.java:168)
Grahame Grieve (May 15 2020 at 17:33):
yes it does use the native conversion internally, but that's still not using the internal conversion, which is https://github.com/hapifhir/org.hl7.fhir.core/blob/master/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv30_50/Questionnaire30_50.java
Morten Ernebjerg (May 18 2020 at 12:14):
@Grahame Grieve PR is in, just let me know if adjustments are needed.
Last updated: Apr 12 2022 at 19:14 UTC