us_core_test_kit 0.4.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/lib/us_core_test_kit/generated/v3.1.1/allergy_intolerance/metadata.yml +1 -24
  3. data/lib/us_core_test_kit/generated/v3.1.1/bodyheight/metadata.yml +0 -52
  4. data/lib/us_core_test_kit/generated/v3.1.1/bodytemp/metadata.yml +0 -52
  5. data/lib/us_core_test_kit/generated/v3.1.1/bodyweight/metadata.yml +0 -52
  6. data/lib/us_core_test_kit/generated/v3.1.1/bp/metadata.yml +0 -76
  7. data/lib/us_core_test_kit/generated/v3.1.1/care_plan/metadata.yml +0 -28
  8. data/lib/us_core_test_kit/generated/v3.1.1/care_team/metadata.yml +0 -16
  9. data/lib/us_core_test_kit/generated/v3.1.1/condition/metadata.yml +1 -39
  10. data/lib/us_core_test_kit/generated/v3.1.1/device/metadata.yml +1 -1013
  11. data/lib/us_core_test_kit/generated/v3.1.1/diagnostic_report_lab/metadata.yml +1 -1021
  12. data/lib/us_core_test_kit/generated/v3.1.1/diagnostic_report_note/metadata.yml +1 -1017
  13. data/lib/us_core_test_kit/generated/v3.1.1/document_reference/document_reference_must_support_test.rb +0 -1
  14. data/lib/us_core_test_kit/generated/v3.1.1/document_reference/document_reference_reference_resolution_test.rb +0 -1
  15. data/lib/us_core_test_kit/generated/v3.1.1/document_reference/metadata.yml +1 -81
  16. data/lib/us_core_test_kit/generated/v3.1.1/encounter/metadata.yml +2 -85
  17. data/lib/us_core_test_kit/generated/v3.1.1/goal/metadata.yml +1 -46
  18. data/lib/us_core_test_kit/generated/v3.1.1/head_circumference/metadata.yml +0 -52
  19. data/lib/us_core_test_kit/generated/v3.1.1/heartrate/metadata.yml +0 -52
  20. data/lib/us_core_test_kit/generated/v3.1.1/immunization/metadata.yml +0 -48
  21. data/lib/us_core_test_kit/generated/v3.1.1/medication_request/metadata.yml +0 -60
  22. data/lib/us_core_test_kit/generated/v3.1.1/metadata.yml +14 -6471
  23. data/lib/us_core_test_kit/generated/v3.1.1/observation_lab/metadata.yml +1 -1053
  24. data/lib/us_core_test_kit/generated/v3.1.1/organization/metadata.yml +0 -20
  25. data/lib/us_core_test_kit/generated/v3.1.1/patient/metadata.yml +1 -29
  26. data/lib/us_core_test_kit/generated/v3.1.1/pediatric_bmi_for_age/metadata.yml +0 -52
  27. data/lib/us_core_test_kit/generated/v3.1.1/pediatric_weight_for_height/metadata.yml +0 -52
  28. data/lib/us_core_test_kit/generated/v3.1.1/practitioner/metadata.yml +0 -16
  29. data/lib/us_core_test_kit/generated/v3.1.1/procedure/metadata.yml +1 -1049
  30. data/lib/us_core_test_kit/generated/v3.1.1/provenance/metadata.yml +0 -36
  31. data/lib/us_core_test_kit/generated/v3.1.1/pulse_oximetry/metadata.yml +0 -76
  32. data/lib/us_core_test_kit/generated/v3.1.1/resprate/metadata.yml +0 -52
  33. data/lib/us_core_test_kit/generated/v3.1.1/smokingstatus/metadata.yml +1 -62
  34. data/lib/us_core_test_kit/generated/v3.1.1/us_core_test_suite.rb +20 -1
  35. data/lib/us_core_test_kit/generated/v4.0.0/allergy_intolerance/metadata.yml +1 -24
  36. data/lib/us_core_test_kit/generated/v4.0.0/blood_pressure/metadata.yml +0 -80
  37. data/lib/us_core_test_kit/generated/v4.0.0/bmi/metadata.yml +0 -56
  38. data/lib/us_core_test_kit/generated/v4.0.0/body_height/metadata.yml +0 -56
  39. data/lib/us_core_test_kit/generated/v4.0.0/body_temperature/metadata.yml +0 -56
  40. data/lib/us_core_test_kit/generated/v4.0.0/body_weight/metadata.yml +0 -56
  41. data/lib/us_core_test_kit/generated/v4.0.0/care_plan/metadata.yml +0 -28
  42. data/lib/us_core_test_kit/generated/v4.0.0/care_team/metadata.yml +0 -16
  43. data/lib/us_core_test_kit/generated/v4.0.0/condition/metadata.yml +1 -39
  44. data/lib/us_core_test_kit/generated/v4.0.0/device/metadata.yml +1 -1013
  45. data/lib/us_core_test_kit/generated/v4.0.0/diagnostic_report_lab/metadata.yml +1 -1021
  46. data/lib/us_core_test_kit/generated/v4.0.0/diagnostic_report_note/metadata.yml +1 -1017
  47. data/lib/us_core_test_kit/generated/v4.0.0/document_reference/metadata.yml +1 -78
  48. data/lib/us_core_test_kit/generated/v4.0.0/encounter/metadata.yml +2 -85
  49. data/lib/us_core_test_kit/generated/v4.0.0/goal/metadata.yml +1 -46
  50. data/lib/us_core_test_kit/generated/v4.0.0/head_circumference/metadata.yml +0 -56
  51. data/lib/us_core_test_kit/generated/v4.0.0/head_circumference_percentile/metadata.yml +0 -56
  52. data/lib/us_core_test_kit/generated/v4.0.0/heart_rate/metadata.yml +0 -56
  53. data/lib/us_core_test_kit/generated/v4.0.0/immunization/metadata.yml +0 -48
  54. data/lib/us_core_test_kit/generated/v4.0.0/medication_request/metadata.yml +0 -60
  55. data/lib/us_core_test_kit/generated/v4.0.0/metadata.yml +13 -6618
  56. data/lib/us_core_test_kit/generated/v4.0.0/observation_lab/metadata.yml +1 -1053
  57. data/lib/us_core_test_kit/generated/v4.0.0/organization/metadata.yml +0 -20
  58. data/lib/us_core_test_kit/generated/v4.0.0/patient/metadata.yml +1 -29
  59. data/lib/us_core_test_kit/generated/v4.0.0/pediatric_bmi_for_age/metadata.yml +0 -56
  60. data/lib/us_core_test_kit/generated/v4.0.0/pediatric_weight_for_height/metadata.yml +0 -56
  61. data/lib/us_core_test_kit/generated/v4.0.0/practitioner/metadata.yml +0 -16
  62. data/lib/us_core_test_kit/generated/v4.0.0/procedure/metadata.yml +1 -1049
  63. data/lib/us_core_test_kit/generated/v4.0.0/provenance/metadata.yml +0 -40
  64. data/lib/us_core_test_kit/generated/v4.0.0/pulse_oximetry/metadata.yml +0 -80
  65. data/lib/us_core_test_kit/generated/v4.0.0/respiratory_rate/metadata.yml +0 -56
  66. data/lib/us_core_test_kit/generated/v4.0.0/smokingstatus/metadata.yml +0 -56
  67. data/lib/us_core_test_kit/generated/v4.0.0/us_core_test_suite.rb +20 -1
  68. data/lib/us_core_test_kit/generated/v5.0.1/allergy_intolerance/metadata.yml +1 -24
  69. data/lib/us_core_test_kit/generated/v5.0.1/blood_pressure/metadata.yml +0 -80
  70. data/lib/us_core_test_kit/generated/v5.0.1/bmi/metadata.yml +0 -56
  71. data/lib/us_core_test_kit/generated/v5.0.1/body_height/metadata.yml +0 -56
  72. data/lib/us_core_test_kit/generated/v5.0.1/body_temperature/metadata.yml +0 -56
  73. data/lib/us_core_test_kit/generated/v5.0.1/body_weight/metadata.yml +0 -56
  74. data/lib/us_core_test_kit/generated/v5.0.1/care_plan/metadata.yml +0 -28
  75. data/lib/us_core_test_kit/generated/v5.0.1/care_team/metadata.yml +0 -16
  76. data/lib/us_core_test_kit/generated/v5.0.1/condition_encounter_diagnosis/metadata.yml +1 -43
  77. data/lib/us_core_test_kit/generated/v5.0.1/condition_problems_health_concerns/metadata.yml +2 -44
  78. data/lib/us_core_test_kit/generated/v5.0.1/device/metadata.yml +1 -1013
  79. data/lib/us_core_test_kit/generated/v5.0.1/diagnostic_report_lab/metadata.yml +1 -1021
  80. data/lib/us_core_test_kit/generated/v5.0.1/diagnostic_report_note/metadata.yml +1 -1021
  81. data/lib/us_core_test_kit/generated/v5.0.1/document_reference/metadata.yml +1 -82
  82. data/lib/us_core_test_kit/generated/v5.0.1/encounter/metadata.yml +2 -85
  83. data/lib/us_core_test_kit/generated/v5.0.1/goal/metadata.yml +2 -1047
  84. data/lib/us_core_test_kit/generated/v5.0.1/head_circumference/metadata.yml +0 -56
  85. data/lib/us_core_test_kit/generated/v5.0.1/head_circumference_percentile/metadata.yml +0 -56
  86. data/lib/us_core_test_kit/generated/v5.0.1/heart_rate/metadata.yml +0 -56
  87. data/lib/us_core_test_kit/generated/v5.0.1/immunization/metadata.yml +0 -48
  88. data/lib/us_core_test_kit/generated/v5.0.1/medication_request/metadata.yml +5 -65
  89. data/lib/us_core_test_kit/generated/v5.0.1/metadata.yml +27 -11041
  90. data/lib/us_core_test_kit/generated/v5.0.1/observation_clinical_test/metadata.yml +0 -52
  91. data/lib/us_core_test_kit/generated/v5.0.1/observation_imaging/metadata.yml +1 -1053
  92. data/lib/us_core_test_kit/generated/v5.0.1/observation_lab/metadata.yml +1 -1053
  93. data/lib/us_core_test_kit/generated/v5.0.1/observation_sdoh_assessment/metadata.yml +0 -57
  94. data/lib/us_core_test_kit/generated/v5.0.1/observation_sexual_orientation/metadata.yml +1 -62
  95. data/lib/us_core_test_kit/generated/v5.0.1/observation_social_history/metadata.yml +1 -1058
  96. data/lib/us_core_test_kit/generated/v5.0.1/organization/metadata.yml +0 -20
  97. data/lib/us_core_test_kit/generated/v5.0.1/patient/metadata.yml +1 -29
  98. data/lib/us_core_test_kit/generated/v5.0.1/pediatric_bmi_for_age/metadata.yml +0 -56
  99. data/lib/us_core_test_kit/generated/v5.0.1/pediatric_weight_for_height/metadata.yml +0 -56
  100. data/lib/us_core_test_kit/generated/v5.0.1/practitioner/metadata.yml +0 -20
  101. data/lib/us_core_test_kit/generated/v5.0.1/procedure/metadata.yml +1 -1049
  102. data/lib/us_core_test_kit/generated/v5.0.1/provenance/metadata.yml +0 -40
  103. data/lib/us_core_test_kit/generated/v5.0.1/pulse_oximetry/metadata.yml +0 -80
  104. data/lib/us_core_test_kit/generated/v5.0.1/questionnaire_response/metadata.yml +0 -20
  105. data/lib/us_core_test_kit/generated/v5.0.1/related_person/metadata.yml +0 -12
  106. data/lib/us_core_test_kit/generated/v5.0.1/respiratory_rate/metadata.yml +0 -56
  107. data/lib/us_core_test_kit/generated/v5.0.1/service_request/metadata.yml +1 -1041
  108. data/lib/us_core_test_kit/generated/v5.0.1/smokingstatus/metadata.yml +0 -56
  109. data/lib/us_core_test_kit/generated/v5.0.1/us_core_test_suite.rb +20 -1
  110. data/lib/us_core_test_kit/generator/must_support_metadata_extractor.rb +17 -7
  111. data/lib/us_core_test_kit/generator/search_definition_metadata_extractor.rb +13 -93
  112. data/lib/us_core_test_kit/generator/suite_generator.rb +11 -0
  113. data/lib/us_core_test_kit/generator/terminology_binding_metadata_extractor.rb +15 -3
  114. data/lib/us_core_test_kit/generator/value_extractor.rb +101 -0
  115. data/lib/us_core_test_kit/provenance_validator.rb +37 -0
  116. data/lib/us_core_test_kit/version.rb +1 -1
  117. metadata +4 -2
@@ -168,66 +168,10 @@
168
168
  - Observation.value[x]
169
169
  - Observation.component.code
170
170
  :bindings:
171
- - :type: code
172
- :strength: preferred
173
- :system: http://hl7.org/fhir/ValueSet/languages
174
- :path: language
175
171
  - :type: code
176
172
  :strength: required
177
173
  :system: http://hl7.org/fhir/us/core/ValueSet/us-core-observation-smoking-status-status
178
174
  :path: status
179
- - :type: CodeableConcept
180
- :strength: preferred
181
- :system: http://hl7.org/fhir/ValueSet/observation-category
182
- :path: category
183
- - :type: CodeableConcept
184
- :strength: preferred
185
- :system: http://hl7.org/fhir/ValueSet/observation-category
186
- :path: category
187
- - :type: CodeableConcept
188
- :strength: extensible
189
- :system: http://hl7.org/fhir/us/core/ValueSet/us-core-smoking-status-observation-codes
190
- :path: code
191
- - :type: CodeableConcept
192
- :strength: preferred
193
- :system: http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.11.20.9.38
194
- :path: value
195
- - :type: CodeableConcept
196
- :strength: extensible
197
- :system: http://hl7.org/fhir/ValueSet/data-absent-reason
198
- :path: dataAbsentReason
199
- - :type: CodeableConcept
200
- :strength: extensible
201
- :system: http://hl7.org/fhir/ValueSet/observation-interpretation
202
- :path: interpretation
203
- - :type: CodeableConcept
204
- :strength: example
205
- :system: http://hl7.org/fhir/ValueSet/body-site
206
- :path: bodySite
207
- - :type: CodeableConcept
208
- :strength: example
209
- :system: http://hl7.org/fhir/ValueSet/observation-methods
210
- :path: method
211
- - :type: CodeableConcept
212
- :strength: preferred
213
- :system: http://hl7.org/fhir/ValueSet/referencerange-meaning
214
- :path: referenceRange.type
215
- - :type: CodeableConcept
216
- :strength: example
217
- :system: http://hl7.org/fhir/ValueSet/referencerange-appliesto
218
- :path: referenceRange.appliesTo
219
- - :type: CodeableConcept
220
- :strength: example
221
- :system: http://hl7.org/fhir/ValueSet/observation-codes
222
- :path: component.code
223
- - :type: CodeableConcept
224
- :strength: extensible
225
- :system: http://hl7.org/fhir/ValueSet/data-absent-reason
226
- :path: component.dataAbsentReason
227
- - :type: CodeableConcept
228
- :strength: extensible
229
- :system: http://hl7.org/fhir/ValueSet/observation-interpretation
230
- :path: component.interpretation
231
175
  :references:
232
176
  - :path: Observation.basedOn
233
177
  :profiles:
@@ -3,6 +3,7 @@ require_relative '../../version'
3
3
  require_relative '../../custom_groups/v5.0.1/capability_statement_group'
4
4
  require_relative '../../custom_groups/v4.0.0/clinical_notes_guidance_group'
5
5
  require_relative '../../custom_groups/data_absent_reason_group'
6
+ require_relative '../../provenance_validator'
6
7
  require_relative 'patient_group'
7
8
  require_relative 'allergy_intolerance_group'
8
9
  require_relative 'care_plan_group'
@@ -48,13 +49,27 @@ module USCoreTestKit
48
49
  module USCoreV501
49
50
  class USCoreTestSuite < Inferno::TestSuite
50
51
  title 'US Core v5.0.1'
52
+ description %(
53
+ The US Core Test Kit tests systems for their conformance to the [US Core
54
+ Implementation Guide](http://hl7.org/fhir/us/core/STU5.0.1).
55
+
56
+ Resources are validated with the FHIR Java validator using `tx.fhir.org`
57
+ as the terminology server. Users should note that the although the ONC
58
+ Certification (g)(10) Standardized API Test Suite includes tests from
59
+ this suite, [it uses a different method to perform terminology
60
+ validation](https://github.com/onc-healthit/onc-certification-g10-test-kit/wiki/FAQ#q-why-do-some-resources-fail-in-us-core-test-kit-with-terminology-validation-errors).
61
+ As a result, resource validation results may not be consistent between
62
+ the US Core Test Suite and the ONC Certification (g)(10) Standardized
63
+ API Test Suite.
64
+ )
51
65
  version VERSION
52
66
 
53
67
  VALIDATION_MESSAGE_FILTERS = [
54
68
  %r{Sub-extension url 'introspect' is not defined by the Extension http://fhir-registry\.smarthealthit\.org/StructureDefinition/oauth-uris$},
55
69
  %r{Sub-extension url 'revoke' is not defined by the Extension http://fhir-registry\.smarthealthit\.org/StructureDefinition/oauth-uris$},
56
70
  /Observation\.effective\.ofType\(Period\): .*vs-1:/, # Invalid invariant in FHIR v4.0.1
57
- /Observation\.effective\.ofType\(Period\): .*us-core-1:/ # Invalid invariant in US Core v3.1.1
71
+ /Observation\.effective\.ofType\(Period\): .*us-core-1:/, # Invalid invariant in US Core v3.1.1
72
+ /Provenance.agent\[\d*\]: Rule provenance-1/ #Invalid invariant in US Core v5.0.1
58
73
  ].freeze
59
74
 
60
75
  def self.metadata
@@ -68,6 +83,10 @@ module USCoreTestKit
68
83
  exclude_message do |message|
69
84
  VALIDATION_MESSAGE_FILTERS.any? { |filter| filter.match? message.message }
70
85
  end
86
+
87
+ perform_additional_validation do |resource, profile_url|
88
+ ProvenanceValidator.validate(resource) if resource.instance_of?(FHIR::Provenance)
89
+ end
71
90
  end
72
91
 
73
92
  id :us_core_v501
@@ -1,3 +1,5 @@
1
+ require_relative 'value_extractor'
2
+
1
3
  module USCoreTestKit
2
4
  class Generator
3
5
  class MustSupportMetadataExtractor
@@ -97,13 +99,10 @@ module USCoreTestKit
97
99
  elsif pattern_element.binding&.strength == 'required' &&
98
100
  pattern_element.binding&.valueSet.present?
99
101
 
100
- value_set = ig_resources.value_set_by_url(pattern_element.binding.valueSet)
101
- bound_systems = value_set&.compose&.include&.reject { |code| code.concept.blank? }
102
- values = []
102
+ value_extractor = ValueExactor.new(ig_resources, resource, profile_elements)
103
103
 
104
- if bound_systems.present?
105
- values = bound_systems&.flat_map { |system| system.concept.map { |code| code.code } }.uniq
106
- end
104
+ values = value_extractor.values_from_value_set_binding(pattern_element).presence ||
105
+ value_extractor.values_from_resource_metadata([metadata[:path]]).presence || []
107
106
 
108
107
  {
109
108
  type: 'requiredBinding',
@@ -292,6 +291,8 @@ module USCoreTestKit
292
291
  add_must_support_choices
293
292
 
294
293
  case profile.version
294
+ when '3.1.1'
295
+ remove_document_reference_custodian
295
296
  when '4.0.0'
296
297
  add_device_distinct_identifier
297
298
  add_patient_uscdi_elements
@@ -354,6 +355,15 @@ module USCoreTestKit
354
355
  end
355
356
  end
356
357
 
358
+ # US Core clarified that server implmentation is not required to support DocumentReference.custodian (FHIR-28393)
359
+ def remove_document_reference_custodian
360
+ if profile.type == 'DocumentReference'
361
+ @must_supports[:elements].delete_if do |element|
362
+ element[:path] == 'custodian'
363
+ end
364
+ end
365
+ end
366
+
357
367
  def remove_document_reference_attachment_data_url
358
368
  if profile.type == 'DocumentReference'
359
369
  @must_supports[:elements].delete_if do |element|
@@ -482,7 +492,7 @@ module USCoreTestKit
482
492
 
483
493
  slice = @must_supports[:slices].find{|slice| slice[:path] == 'category'}
484
494
 
485
- slice[:discriminator][:values] << 'clinical-note' if slice.present?
495
+ slice[:discriminator][:values] = ['clinical-note'] if slice.present?
486
496
  end
487
497
 
488
498
  # FHIR-37794 Server systems are not required to support US Core QuestionnaireResponse
@@ -1,3 +1,5 @@
1
+ require_relative 'value_extractor'
2
+
1
3
  module USCoreTestKit
2
4
  class Generator
3
5
  class SearchDefinitionMetadataExtractor
@@ -112,103 +114,21 @@ module USCoreTestKit
112
114
  end
113
115
 
114
116
  def values
115
- values = (
116
- (
117
- values_from_pattern_codeable_concept_slices +
118
- values_from_required_binding_slices +
119
- values_from_fixed_codes +
120
- values_from_pattern_coding +
121
- values_from_pattern_codeable_concept
122
- ).uniq.presence || values_from_value_set_binding(profile_element)
123
- ).presence || values_from_resource_metadata
124
- values
125
- end
126
-
127
- def slices
128
- return [] unless contains_multiple?
129
-
130
- profile_elements.select do |element|
131
- full_paths.include?(element.path) &&
132
- element.sliceName.present? &&
133
- (
134
- element.patternCodeableConcept.present? ||
135
- element.binding.present? && element.binding.strength == 'required'
136
- )
137
- end
117
+ value_extractor.values_from_slicing(profile_element, type).presence ||
118
+ value_extractor.values_from_value_set_binding(profile_element).presence ||
119
+ values_from_resource_metadata(paths).presence || []
138
120
  end
139
121
 
140
- def values_from_pattern_codeable_concept_slices
141
- slices.map do |slice|
142
- slice.patternCodeableConcept.coding.first.code if slice.patternCodeableConcept.present?
143
- end.compact
144
- end
145
-
146
- def values_from_required_binding_slices
147
- slices.map do |slice|
148
- if slice.binding.present? && slice.binding.strength == 'required'
149
- values_from_value_set_binding(slice)
150
- end
151
- end.flatten.compact
152
- end
153
-
154
- def values_from_fixed_codes
155
- return [] unless type == 'CodeableConcept'
156
-
157
- profile_elements
158
- .select { |element| element.path == "#{profile_element.path}.coding.code" && element.fixedCode.present? }
159
- .map { |element| element.fixedCode }
160
- end
161
-
162
- def values_from_pattern_coding
163
- return [] unless type == 'CodeableConcept'
164
-
165
- profile_elements
166
- .select { |element| element.path == "#{profile_element.path}.coding" && element.patternCoding.present? }
167
- .map { |element| element.patternCoding.code }
168
- end
169
-
170
- def values_from_pattern_codeable_concept
171
- return [] if type != 'CodeableConcept' || profile_element.patternCodeableConcept.blank?
172
-
173
- [profile_element.patternCodeableConcept.coding.first.code]
174
- end
175
-
176
- def value_set_binding(the_element)
177
- the_element&.binding
178
- end
179
-
180
- def value_set(the_element)
181
- ig_resources.value_set_by_url(value_set_binding(the_element)&.valueSet)
182
- end
183
-
184
- def bound_systems(the_element)
185
- value_set(the_element)&.compose&.include&.reject { |code| code.concept.nil? }
186
- end
187
-
188
- def values_from_value_set_binding(the_element)
189
- bound_systems = bound_systems(the_element)
190
-
191
- return [] if bound_systems.blank?
192
-
193
- bound_systems.flat_map { |system| system.concept.map { |code| code.code } }.uniq
194
- end
195
-
196
- def fhir_metadata(current_path)
197
- FHIR.const_get(resource)::METADATA[current_path]
198
- end
199
-
200
- def values_from_resource_metadata
201
- values = []
202
-
203
- paths.each do |current_path|
204
- current_metadata = fhir_metadata(current_path)
205
-
206
- if current_metadata&.dig('valid_codes').present?
207
- values = values + current_metadata['valid_codes'].values.flatten
208
- end
122
+ def values_from_resource_metadata(paths)
123
+ if multiple_or_expectation == 'SHALL' || paths.include?('status')
124
+ value_extractor.values_from_resource_metadata(paths)
125
+ else
126
+ []
209
127
  end
128
+ end
210
129
 
211
- values
130
+ def value_extractor
131
+ @value_extractor ||= ValueExactor.new(ig_resources, resource, profile_elements)
212
132
  end
213
133
  end
214
134
  end
@@ -53,6 +53,17 @@ module USCoreTestKit
53
53
  "#{ig_metadata.reformatted_version.upcase}_VALIDATOR_URL"
54
54
  end
55
55
 
56
+ def ig_link
57
+ case ig_metadata.ig_version
58
+ when 'v5.0.1'
59
+ 'http://hl7.org/fhir/us/core/STU5.0.1'
60
+ when 'v4.0.0'
61
+ 'http://hl7.org/fhir/us/core/STU4'
62
+ when 'v3.1.1'
63
+ 'http://hl7.org/fhir/us/core/STU3.1.1'
64
+ end
65
+ end
66
+
56
67
  def generate
57
68
  File.open(output_file_name, 'w') { |f| f.write(output) }
58
69
  end
@@ -27,21 +27,33 @@ module USCoreTestKit
27
27
  end
28
28
  end
29
29
 
30
+ def element_has_optional_binding_slice?(element)
31
+ element.sliceName.present? && element.min == 0
32
+ end
33
+
30
34
  def profile_elements_with_bindings
31
35
  profile_elements
32
- .select { |element| element.binding.present? }
33
- .reject { |element| element_has_fixed_value? element }
36
+ .select { |element| element.binding.present? && element.binding.strength == 'required'}
37
+ .reject { |element| element_has_fixed_value?(element) || element_has_optional_binding_slice?(element) }
34
38
  end
35
39
 
40
+
41
+
36
42
  def element_terminology_bindings
37
43
  profile_elements_with_bindings.map do |element|
38
- {
44
+ binding = {
39
45
  type: element.type.first.code,
40
46
  strength: element.binding.strength,
41
47
  # Goal.target.detail has an unbound binding
42
48
  system: element.binding.valueSet&.split('|')&.first,
43
49
  path: element.path.gsub('[x]', '').gsub("#{resource}.", '')
44
50
  }
51
+
52
+ if element.sliceName.present? && element.min > 0
53
+ binding[:required_binding_slice] = true
54
+ end
55
+
56
+ binding
45
57
  end
46
58
  end
47
59
 
@@ -0,0 +1,101 @@
1
+ module USCoreTestKit
2
+ class Generator
3
+ class ValueExactor
4
+ attr_accessor :ig_resources, :resource, :profile_elements
5
+
6
+ def initialize(ig_resources, resource, profile_elements)
7
+ self.ig_resources = ig_resources
8
+ self.resource = resource
9
+ self.profile_elements = profile_elements
10
+ end
11
+
12
+ def values_from_slicing(profile_element, type)
13
+ (
14
+ values_from_required_binding(profile_element) +
15
+ values_from_fixed_codes(profile_element, type) +
16
+ values_from_pattern_coding(profile_element, type) +
17
+ values_from_pattern_codeable_concept(profile_element, type)
18
+ ).uniq
19
+ end
20
+
21
+ def values_from_required_binding(profile_element)
22
+ return [] unless profile_element&.max == '*'
23
+
24
+ profile_elements
25
+ .select do |element|
26
+ element.path == profile_element.path && element.binding&.strength == 'required'
27
+ end
28
+ .map { |element| values_from_value_set_binding(element) }
29
+ .flatten.compact
30
+ end
31
+
32
+ def values_from_fixed_codes(profile_element, type)
33
+ return [] unless type == 'CodeableConcept'
34
+
35
+ profile_elements
36
+ .select do
37
+ |element| element.path == "#{profile_element.path}.coding.code" && element.fixedCode.present?
38
+ end
39
+ .map { |element| element.fixedCode }
40
+ end
41
+
42
+ def values_from_pattern_coding(profile_element, type)
43
+ return [] unless type == 'CodeableConcept'
44
+
45
+ profile_elements
46
+ .select do |element|
47
+ element.path == "#{profile_element.path}.coding" && element.patternCoding.present?
48
+ end
49
+ .map { |element| element.patternCoding.code }
50
+ end
51
+
52
+ def values_from_pattern_codeable_concept(profile_element, type)
53
+ return [] unless type == 'CodeableConcept'
54
+
55
+ profile_elements
56
+ .select do |element|
57
+ element.path == profile_element.path && element.patternCodeableConcept.present? && element.min > 0
58
+ end
59
+ .map { |element| element.patternCodeableConcept.coding.first.code }
60
+ end
61
+
62
+ def value_set_binding(the_element)
63
+ the_element&.binding
64
+ end
65
+
66
+ def value_set(the_element)
67
+ ig_resources.value_set_by_url(value_set_binding(the_element)&.valueSet)
68
+ end
69
+
70
+ def bound_systems(the_element)
71
+ value_set(the_element)&.compose&.include&.reject { |code| code.concept.nil? }
72
+ end
73
+
74
+ def values_from_value_set_binding(the_element)
75
+ bound_systems = bound_systems(the_element)
76
+
77
+ return [] if bound_systems.blank?
78
+
79
+ bound_systems.flat_map { |system| system.concept.map { |code| code.code } }.uniq
80
+ end
81
+
82
+ def fhir_metadata(current_path)
83
+ FHIR.const_get(resource)::METADATA[current_path]
84
+ end
85
+
86
+ def values_from_resource_metadata(paths)
87
+ values = []
88
+
89
+ paths.each do |current_path|
90
+ current_metadata = fhir_metadata(current_path)
91
+
92
+ if current_metadata&.dig('valid_codes').present?
93
+ values = values + current_metadata['valid_codes'].values.flatten
94
+ end
95
+ end
96
+
97
+ values
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,37 @@
1
+ module USCoreTestKit
2
+ class ProvenanceValidator
3
+ include FHIRResourceNavigation
4
+
5
+ def self.validate(...)
6
+ new(...).validate
7
+ end
8
+
9
+ attr_reader :resource, :validation_messages
10
+
11
+ def initialize(resource)
12
+ @resource = resource
13
+ @validation_messages = []
14
+ end
15
+
16
+ def validate
17
+ # Invariant provenance-1 in US Core 5 causes validation error. See FHIR-39518
18
+ return validation_messages unless resource.instance_of?(FHIR::Provenance)
19
+
20
+ failed_provenance =
21
+ find_a_value_at(resource, 'agent') do |agent|
22
+ ['Practitioner', 'Device'].any? { |resource_type| agent.who.reference&.include?(resource_type) } &&
23
+ agent.onBehalfOf.nil?
24
+ end
25
+
26
+
27
+ if failed_provenance.present?
28
+ validation_messages << {
29
+ type: 'error',
30
+ message: "#{resource.resourceType}/#{resource.id}: Rule provenance-1: 'onBehalfOf SHALL be present when Provenance.agent.who is a Practitioner or Device' Failed"
31
+ }
32
+ end
33
+
34
+ validation_messages
35
+ end
36
+ end
37
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module USCoreTestKit
4
- VERSION = '0.4.0'
4
+ VERSION = '0.4.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: us_core_test_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen MacVicar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-31 00:00:00.000000000 Z
11
+ date: 2022-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inferno_core
@@ -1292,6 +1292,7 @@ files:
1292
1292
  - lib/us_core_test_kit/generator/suite_generator.rb
1293
1293
  - lib/us_core_test_kit/generator/terminology_binding_metadata_extractor.rb
1294
1294
  - lib/us_core_test_kit/generator/validation_test_generator.rb
1295
+ - lib/us_core_test_kit/generator/value_extractor.rb
1295
1296
  - lib/us_core_test_kit/igs/us_core_311.tgz
1296
1297
  - lib/us_core_test_kit/igs/us_core_311/StructureDefinition-bodyheight.json
1297
1298
  - lib/us_core_test_kit/igs/us_core_311/StructureDefinition-bodytemp.json
@@ -1302,6 +1303,7 @@ files:
1302
1303
  - lib/us_core_test_kit/igs/us_core_400.tgz
1303
1304
  - lib/us_core_test_kit/igs/us_core_501.tgz
1304
1305
  - lib/us_core_test_kit/must_support_test.rb
1306
+ - lib/us_core_test_kit/provenance_validator.rb
1305
1307
  - lib/us_core_test_kit/read_test.rb
1306
1308
  - lib/us_core_test_kit/reference_resolution_test.rb
1307
1309
  - lib/us_core_test_kit/request_logger.rb