@@ -772,10 +772,7 @@ def self.apply_invariants!(resource)
772772 # i.maxLength = nil if !['boolean', 'decimal', 'integer', 'string', 'text', 'url'].include?(i.type)
773773 # end
774774 when FHIR ::QuestionnaireResponse
775- resource . item . each do |i |
776- i . item = nil
777- i . answer . each { |q |q . valueBoolean = true if !q . value }
778- end
775+ fix_questionnaire_response_items ( resource . item )
779776 when FHIR ::Range
780777 # validate that the low/high values in the range are correct (e.g. the low value is not higher than the high value)
781778 if resource . low && resource . high
@@ -1559,10 +1556,7 @@ def self.apply_invariants!(resource)
15591556 i . maxLength = nil if ![ 'boolean' , 'decimal' , 'integer' , 'string' , 'text' , 'url' ] . include? ( i . type )
15601557 end
15611558 when FHIR ::STU3 ::QuestionnaireResponse
1562- resource . item . each do |i |
1563- i . item = nil
1564- i . answer . each { |q |q . valueBoolean = true if !q . value }
1565- end
1559+ fix_questionnaire_response_items ( resource . item )
15661560 when FHIR ::STU3 ::Range
15671561 # validate that the low/high values in the range are correct (e.g. the low value is not higher than the high value)
15681562 if resource . low && resource . high
@@ -2267,6 +2261,36 @@ def self.apply_invariants!(resource)
22672261 end
22682262 end
22692263
2264+ # Recursively fixes a QuestionnaireResponse item tree so it can be accepted
2265+ # by a strict FHIR parser.
2266+ #
2267+ # The generated tree can be arbitrarily deep via two nesting axes:
2268+ # item.answer[].item[] — items nested inside an answer
2269+ # item.item[] — direct sub-item groups on an item
2270+ #
2271+ # Two problems are corrected at every level:
2272+ # 1. Answers with no value are given `valueBoolean = true`. A strict parser
2273+ # rejects answer objects that are completely empty (`{}`).
2274+ # 2. Direct sub-item groups (`item.item`) are removed. They are often
2275+ # generated empty or with invalid content that would fail validation.
2276+ #
2277+ # Ordering matters: `answer.item` is recursed BEFORE `item.item` is cleared,
2278+ # because answer-nested items may themselves contain answers that need fixing.
2279+ # Clearing `item.item` first would not affect `answer.item`, but fixing
2280+ # `answer.item` last would process items that are immediately discarded —
2281+ # so the current order keeps the logic clear: fix answers deeply first, then drop
2282+ # the direct sub-groups.
2283+ def self . fix_questionnaire_response_items ( items )
2284+ return if items . nil? || items . empty?
2285+ items . each do |item |
2286+ item . answer . each do |answer |
2287+ answer . valueBoolean = true unless answer . value
2288+ fix_questionnaire_response_items ( answer . item ) unless answer . item . nil?
2289+ end
2290+ item . item = nil
2291+ end
2292+ end
2293+
22702294 end
22712295 end
22722296end
0 commit comments