health-data-standards 3.6.1 → 3.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (434) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +7 -2
  3. data/Rakefile +2 -1
  4. data/lib/health-data-standards.rb +22 -1
  5. data/lib/health-data-standards/export/cat_1.rb +25 -6
  6. data/lib/health-data-standards/export/cat_1_r2.rb +8 -2
  7. data/lib/health-data-standards/export/cat_3.rb +8 -7
  8. data/lib/health-data-standards/export/exceptions.rb +13 -0
  9. data/lib/health-data-standards/export/helper/cat1_view_helper.rb +17 -11
  10. data/lib/health-data-standards/export/helper/html_view_helper.rb +13 -7
  11. data/lib/health-data-standards/export/helper/scooped_view_helper.rb +68 -25
  12. data/lib/health-data-standards/export/html.rb +9 -4
  13. data/lib/health-data-standards/export/qrda/entry_template_resolver.rb +29 -11
  14. data/lib/health-data-standards/export/qrda/hqmf-qrda-oids.json +89 -5
  15. data/lib/health-data-standards/export/rendering_context.rb +2 -2
  16. data/lib/health-data-standards/export/template_helper.rb +7 -2
  17. data/lib/health-data-standards/export/view_helper.rb +107 -39
  18. data/lib/health-data-standards/import/bulk_record_importer.rb +8 -5
  19. data/lib/health-data-standards/import/bundle/importer.rb +21 -14
  20. data/lib/health-data-standards/import/c32/care_goal_importer.rb +1 -1
  21. data/lib/health-data-standards/import/c32/immunization_importer.rb +1 -1
  22. data/lib/health-data-standards/import/cat1/clinical_trial_participant_importer.rb +20 -0
  23. data/lib/health-data-standards/import/cat1/device_order_importer.rb +20 -0
  24. data/lib/health-data-standards/import/cat1/diagnosis_active_importer.rb +4 -9
  25. data/lib/health-data-standards/import/cat1/diagnosis_importer.rb +15 -0
  26. data/lib/health-data-standards/import/cat1/diagnosis_inactive_importer.rb +1 -1
  27. data/lib/health-data-standards/import/cat1/diagnostic_study_order_importer.rb +6 -0
  28. data/lib/health-data-standards/import/cat1/encounter_order_act_importer.rb +19 -0
  29. data/lib/health-data-standards/import/cat1/encounter_performed_act_importer.rb +19 -0
  30. data/lib/health-data-standards/import/cat1/encounter_performed_importer.rb +16 -0
  31. data/lib/health-data-standards/import/cat1/immunization_administered_importer.rb +14 -0
  32. data/lib/health-data-standards/import/cat1/medication_dispensed_act_importer.rb +18 -0
  33. data/lib/health-data-standards/import/cat1/patient_importer.rb +44 -17
  34. data/lib/health-data-standards/import/cat1/procedure_order_importer.rb +4 -4
  35. data/lib/health-data-standards/import/cat1/procedure_performed_importer.rb +1 -0
  36. data/lib/health-data-standards/import/cat1/transfer_from_act_importer.rb +18 -0
  37. data/lib/health-data-standards/import/cat1/transfer_from_importer.rb +24 -0
  38. data/lib/health-data-standards/import/cat1/transfer_to_act_importer.rb +18 -0
  39. data/lib/health-data-standards/import/cat1/transfer_to_importer.rb +23 -0
  40. data/lib/health-data-standards/import/cda/allergy_importer.rb +1 -1
  41. data/lib/health-data-standards/import/cda/communication_importer.rb +55 -0
  42. data/lib/health-data-standards/import/cda/condition_importer.rb +17 -1
  43. data/lib/health-data-standards/import/cda/encounter_importer.rb +23 -21
  44. data/lib/health-data-standards/import/cda/medical_equipment_importer.rb +1 -0
  45. data/lib/health-data-standards/import/cda/medication_importer.rb +14 -4
  46. data/lib/health-data-standards/import/cda/procedure_importer.rb +4 -4
  47. data/lib/health-data-standards/import/cda/result_importer.rb +1 -1
  48. data/lib/health-data-standards/import/cda/section_importer.rb +59 -18
  49. data/lib/health-data-standards/models/assessment.rb +3 -0
  50. data/lib/health-data-standards/models/care_experience.rb +2 -0
  51. data/lib/health-data-standards/models/care_goal.rb +4 -0
  52. data/lib/health-data-standards/models/communication.rb +3 -0
  53. data/lib/health-data-standards/models/condition.rb +12 -9
  54. data/lib/health-data-standards/models/cqm/bundle.rb +2 -1
  55. data/lib/health-data-standards/models/cqm/measure.rb +2 -1
  56. data/lib/health-data-standards/models/cqm/patient_cache.rb +7 -3
  57. data/lib/health-data-standards/models/cqm/query_cache.rb +2 -0
  58. data/lib/health-data-standards/models/encounter.rb +14 -1
  59. data/lib/health-data-standards/models/encounter_principal_diagnosis.rb +36 -0
  60. data/lib/health-data-standards/models/entry.rb +5 -1
  61. data/lib/health-data-standards/models/family_history.rb +4 -0
  62. data/lib/health-data-standards/models/immunization.rb +1 -0
  63. data/lib/health-data-standards/models/lab_result.rb +10 -1
  64. data/lib/health-data-standards/models/medical_equipment.rb +2 -1
  65. data/lib/health-data-standards/models/medication.rb +19 -2
  66. data/lib/health-data-standards/models/patient_preference.rb +5 -0
  67. data/lib/health-data-standards/models/procedure.rb +16 -3
  68. data/lib/health-data-standards/models/provider.rb +17 -1
  69. data/lib/health-data-standards/models/provider_preference.rb +5 -0
  70. data/lib/health-data-standards/models/record.rb +8 -9
  71. data/lib/health-data-standards/models/reference.rb +1 -1
  72. data/lib/health-data-standards/models/svs/value_set.rb +28 -10
  73. data/lib/health-data-standards/models/transfer.rb +6 -1
  74. data/lib/health-data-standards/tasks/bundle.rake +5 -3
  75. data/lib/health-data-standards/util/hqmf_template_helper.rb +20 -14
  76. data/lib/health-data-standards/util/hqmfr2_template_oid_map.json +382 -0
  77. data/lib/health-data-standards/util/nlm_helper.rb +14 -0
  78. data/lib/health-data-standards/util/vs_api.rb +72 -54
  79. data/lib/health-data-standards/validate/measure_validator.rb +8 -3
  80. data/lib/health-data-standards/validate/performance_rate_validator.rb +1 -1
  81. data/lib/health-data-standards/validate/qrda_qdm_template_validator.rb +253 -0
  82. data/lib/health-data-standards/validate/reported_result_extractor.rb +5 -1
  83. data/lib/health-data-standards/validate/schematron_validator.rb +6 -0
  84. data/lib/health-data-standards/validate/validators.rb +49 -1
  85. data/lib/hqmf-generator/document.xml.erb +6 -5
  86. data/lib/hqmf-generator/field.xml.erb +1 -0
  87. data/lib/hqmf-generator/hqmf-generator.rb +85 -41
  88. data/lib/hqmf-generator/subset.xml.erb +15 -0
  89. data/lib/hqmf-generator/temporal_relationship.xml.erb +8 -3
  90. data/lib/hqmf-generator/temporal_relationship_attribute.xml.erb +10 -0
  91. data/lib/hqmf-generator/value.xml.erb +2 -2
  92. data/lib/hqmf-model/data_criteria.json +88 -17
  93. data/lib/hqmf-model/data_criteria.rb +144 -72
  94. data/lib/hqmf-model/population_criteria.rb +20 -18
  95. data/lib/hqmf-model/precondition.rb +6 -3
  96. data/lib/hqmf-model/types.rb +1 -1
  97. data/lib/hqmf-parser.rb +9 -0
  98. data/lib/hqmf-parser/1.0/utilities.rb +1 -1
  99. data/lib/hqmf-parser/2.0/data_criteria.rb +293 -319
  100. data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_base_extract.rb +80 -0
  101. data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_definition_from_template_or_type_extract.rb +201 -0
  102. data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_post_processing.rb +85 -0
  103. data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_specific_occurrences_and_source_data_criteria_extract.rb +117 -0
  104. data/lib/hqmf-parser/2.0/document.rb +246 -222
  105. data/lib/hqmf-parser/2.0/document_helpers/doc_population_helper.rb +175 -0
  106. data/lib/hqmf-parser/2.0/document_helpers/doc_utilities.rb +131 -0
  107. data/lib/hqmf-parser/2.0/field_value_helper.rb +251 -0
  108. data/lib/hqmf-parser/2.0/population_criteria.rb +101 -32
  109. data/lib/hqmf-parser/2.0/precondition.rb +61 -35
  110. data/lib/hqmf-parser/2.0/source_data_criteria_helper.rb +112 -0
  111. data/lib/hqmf-parser/2.0/types.rb +253 -73
  112. data/lib/hqmf-parser/2.0/utilities.rb +27 -12
  113. data/lib/hqmf-parser/2.0/value_set_helper.rb +101 -0
  114. data/lib/hqmf-parser/converter/pass1/data_criteria_converter.rb +6 -1
  115. data/lib/hqmf-parser/converter/pass1/population_criteria_converter.rb +34 -30
  116. data/lib/hqmf-parser/parser.rb +5 -5
  117. data/resources/schematron/qrda/cat_1/{CDAR2_QRDA_I_R1_D3_2015MAY_Schematron.sch → HL7_CDAR2_QRDA_Category_I_2_12_16.sch} +4692 -4675
  118. data/resources/schematron/qrda/cat_1_r3_1/HL7 QRDA Category I STU 3.1.sch +3573 -0
  119. data/resources/schematron/qrda/cat_1_r3_1/HL7 QRDA Category III STU 1.1.sch +464 -0
  120. data/resources/schematron/qrda/cat_1_r3_1/QRDA Category I STU Release 3.1.sch +5394 -0
  121. data/resources/schematron/qrda/cat_1_r3_1/voc.xml +1229 -0
  122. data/resources/schematron/qrda/cat_1_r4/HL7 QRDA Category I STU 4.sch +3526 -0
  123. data/resources/schematron/qrda/cat_1_r4/voc.xml +1186 -0
  124. data/resources/schematron/qrda/cat_3_r1_1/HL7 QRDA Category III STU 1.1.sch +528 -0
  125. data/resources/schematron/qrda/cat_3_r1_1/voc.xml +8 -0
  126. data/resources/schematron/qrda/cat_3_r2/HL7 QRDA Category III STU 2.sch +677 -0
  127. data/resources/schematron/qrda/cat_3_r2/voc.xml +1186 -0
  128. data/resources/schematron/qrda/cat_3_r2_1/HL7 QRDA Category III STU 2.1.sch +678 -0
  129. data/resources/schematron/qrda/cat_3_r2_1/voc.xml +1186 -0
  130. data/templates/c32/_medical_equipment.c32.erb +1 -1
  131. data/templates/c32/_vital_signs.c32.erb +1 -1
  132. data/templates/cat1/{_2.16.840.1.113883.10.20.22.4.85.cat1.erb → r2/_2.16.840.1.113883.10.20.22.4.85.cat1.erb} +1 -1
  133. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.1.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.1.cat1.erb} +3 -3
  134. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.101.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.101.cat1.erb} +1 -1
  135. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.103.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.103.cat1.erb} +9 -5
  136. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.105.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.105.cat1.erb} +18 -10
  137. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.11.cat1.erb +88 -0
  138. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.12.cat1.erb +50 -0
  139. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.13.cat1.erb +54 -0
  140. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.135.cat1.erb +70 -0
  141. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.136.cat1.erb +52 -0
  142. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.14.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.14.cat1.erb} +24 -6
  143. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.140.cat1.erb +39 -0
  144. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +23 -0
  145. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.18.cat1.erb +25 -0
  146. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.2.cat1.erb +29 -0
  147. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.20.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.20.cat1.erb} +4 -4
  148. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.22.cat1.erb +22 -0
  149. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.23.cat1.erb +114 -0
  150. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.26.cat1.erb +20 -0
  151. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.28.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.28.cat1.erb} +2 -2
  152. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.3.cat1.erb +25 -0
  153. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +23 -0
  154. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.32.cat1.erb +20 -0
  155. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.34.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.34.cat1.erb} +6 -6
  156. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +22 -0
  157. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.38.cat1.erb +20 -0
  158. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.4.cat1.erb +29 -0
  159. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.40.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.40.cat1.erb} +3 -3
  160. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.41.cat1.erb +46 -0
  161. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.42.cat1.erb +38 -0
  162. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.43.cat1.erb +24 -0
  163. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.44.cat1.erb +25 -0
  164. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.45.cat1.erb +26 -0
  165. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.46.cat1.erb +30 -0
  166. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +47 -0
  167. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.51.cat1.erb +14 -0
  168. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.54.cat1.erb +32 -0
  169. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.55.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.55.cat1.erb} +0 -0
  170. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.57.cat1.erb +23 -0
  171. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.59.cat1.erb +22 -0
  172. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.62.cat1.erb +36 -0
  173. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.63.cat1.erb +21 -0
  174. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.64.cat1.erb +52 -0
  175. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.66.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.66.cat1.erb} +6 -6
  176. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.69.cat1.erb +23 -0
  177. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.7.cat1.erb +33 -0
  178. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.76.cat1.erb → r2/_2.16.840.1.113883.10.20.24.3.76.cat1.erb} +5 -3
  179. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.81.cat1.erb +23 -0
  180. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.82.cat1.erb +23 -0
  181. data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.9.cat1.erb +64 -0
  182. data/templates/cat1/r2/_2.16.840.1.113883.10.20.28.3.6.cat1.erb +17 -0
  183. data/templates/cat1/{_address.cat1.erb → r2/_address.cat1.erb} +0 -0
  184. data/templates/cat1/{_author.cat1.erb → r2/_author.cat1.erb} +0 -0
  185. data/templates/cat1/r2/_fulfills.cat1.erb +14 -0
  186. data/templates/cat1/{_id.cat1.erb → r2/_id.cat1.erb} +0 -0
  187. data/templates/cat1/{_measures.cat1.erb → r2/_measures.cat1.erb} +1 -1
  188. data/templates/cat1/{_medication_details.cat1.erb → r2/_medication_details.cat1.erb} +3 -2
  189. data/templates/cat1/r2/_medication_dispense.cat1.erb +22 -0
  190. data/templates/cat1/{_ordinality.cat1.erb → r2/_ordinality.cat1.erb} +0 -0
  191. data/templates/cat1/{_organization.cat1.erb → r2/_organization.cat1.erb} +0 -0
  192. data/templates/cat1/{_patient_data.cat1.erb → r2/_patient_data.cat1.erb} +4 -1
  193. data/templates/cat1/r2/_patient_data_r3_1.cat1.erb +17 -0
  194. data/templates/cat1/r2/_providers.cat1.erb +76 -0
  195. data/templates/cat1/r2/_reason.cat1.erb +45 -0
  196. data/templates/cat1/{_record_target.cat1.erb → r2/_record_target.cat1.erb} +3 -0
  197. data/templates/cat1/r2/_reporting_parameters.cat1.erb +31 -0
  198. data/templates/cat1/{_result_value.cat1.erb → r2/_result_value.cat1.erb} +1 -1
  199. data/templates/cat1/{_telecom.cat1.erb → r2/_telecom.cat1.erb} +0 -0
  200. data/templates/cat1/{show.cat1.erb → r2/show.cat1.erb} +52 -5
  201. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.1.cat1.erb +14 -0
  202. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.103.cat1.erb +17 -0
  203. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.105.cat1.erb +68 -0
  204. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.11.cat1.erb +58 -0
  205. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.12.cat1.erb → r3/_2.16.840.1.113883.10.20.24.3.12.cat1.erb} +4 -5
  206. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.13.cat1.erb +39 -0
  207. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.14.cat1.erb +39 -0
  208. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +23 -0
  209. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.18.cat1.erb +25 -0
  210. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.2.cat1.erb +29 -0
  211. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.22.cat1.erb → r3/_2.16.840.1.113883.10.20.24.3.22.cat1.erb} +6 -5
  212. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.23.cat1.erb → r3/_2.16.840.1.113883.10.20.24.3.23.cat1.erb} +26 -30
  213. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.26.cat1.erb +20 -0
  214. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.3.cat1.erb +25 -0
  215. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +23 -0
  216. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.32.cat1.erb → r3/_2.16.840.1.113883.10.20.24.3.32.cat1.erb} +4 -4
  217. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +22 -0
  218. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.38.cat1.erb → r3/_2.16.840.1.113883.10.20.24.3.38.cat1.erb} +3 -3
  219. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.4.cat1.erb +29 -0
  220. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.41.cat1.erb → r3/_2.16.840.1.113883.10.20.24.3.41.cat1.erb} +8 -10
  221. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.42.cat1.erb +38 -0
  222. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.43.cat1.erb +24 -0
  223. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.44.cat1.erb +25 -0
  224. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.45.cat1.erb → r3/_2.16.840.1.113883.10.20.24.3.45.cat1.erb} +5 -5
  225. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.46.cat1.erb +30 -0
  226. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +47 -0
  227. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.51.cat1.erb +14 -0
  228. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.54.cat1.erb → r3/_2.16.840.1.113883.10.20.24.3.54.cat1.erb} +4 -4
  229. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.55.cat1.erb +18 -0
  230. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.57.cat1.erb +23 -0
  231. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.59.cat1.erb +22 -0
  232. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.62.cat1.erb +36 -0
  233. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.63.cat1.erb → r3/_2.16.840.1.113883.10.20.24.3.63.cat1.erb} +6 -8
  234. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.64.cat1.erb +51 -0
  235. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.69.cat1.erb +23 -0
  236. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.7.cat1.erb +33 -0
  237. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.76.cat1.erb +19 -0
  238. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.81.cat1.erb +24 -0
  239. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.82.cat1.erb +24 -0
  240. data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.9.cat1.erb +57 -0
  241. data/templates/cat1/r3/_address.cat1.erb +9 -0
  242. data/templates/{cat3/_author.cat3.erb → cat1/r3/_author.cat1.erb} +0 -0
  243. data/templates/cat1/{_fulfills.cat1.erb → r3/_fulfills.cat1.erb} +0 -0
  244. data/templates/{cat3/_id.cat3.erb → cat1/r3/_id.cat1.erb} +0 -0
  245. data/templates/cat1/r3/_measures.cat1.erb +93 -0
  246. data/templates/cat1/r3/_medication_details.cat1.erb +16 -0
  247. data/templates/cat1/{_medication_dispense.cat1.erb → r3/_medication_dispense.cat1.erb} +3 -3
  248. data/templates/cat1/r3/_ordinality.cat1.erb +10 -0
  249. data/templates/cat1/r3/_organization.cat1.erb +9 -0
  250. data/templates/cat1/r3/_patient_data.cat1.erb +17 -0
  251. data/templates/cat1/r3/_providers.cat1.erb +76 -0
  252. data/templates/cat1/r3/_reason.cat1.erb +34 -0
  253. data/templates/cat1/r3/_record_target.cat1.erb +56 -0
  254. data/templates/cat1/r3/_reporting_parameters.cat1.erb +31 -0
  255. data/templates/cat1/r3/_result_value.cat1.erb +28 -0
  256. data/templates/{cat3/_telecom.cat3.erb → cat1/r3/_telecom.cat1.erb} +0 -0
  257. data/templates/cat1/r3/show.cat1.erb +183 -0
  258. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.1.cat1.erb +14 -0
  259. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.103.cat1.erb +17 -0
  260. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.105.cat1.erb +68 -0
  261. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.12.cat1.erb +53 -0
  262. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.135.cat1.erb +71 -0
  263. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.136.cat1.erb +52 -0
  264. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.140.cat1.erb +39 -0
  265. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +23 -0
  266. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.18.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.18.cat1.erb} +3 -3
  267. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.2.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.2.cat1.erb} +2 -2
  268. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.22.cat1.erb +30 -0
  269. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.23.cat1.erb +116 -0
  270. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.26.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.26.cat1.erb} +4 -2
  271. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.3.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.3.cat1.erb} +2 -2
  272. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +24 -0
  273. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.32.cat1.erb +21 -0
  274. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +22 -0
  275. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.38.cat1.erb +21 -0
  276. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.4.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.4.cat1.erb} +2 -2
  277. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.41.cat1.erb +45 -0
  278. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.42.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.42.cat1.erb} +4 -4
  279. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.43.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.43.cat1.erb} +3 -3
  280. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.44.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.44.cat1.erb} +3 -3
  281. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.45.cat1.erb +35 -0
  282. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.46.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.46.cat1.erb} +4 -4
  283. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +47 -0
  284. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.51.cat1.erb +14 -0
  285. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.54.cat1.erb +32 -0
  286. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.55.cat1.erb +18 -0
  287. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.57.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.57.cat1.erb} +3 -3
  288. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.59.cat1.erb +22 -0
  289. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.62.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.62.cat1.erb} +5 -5
  290. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.63.cat1.erb +21 -0
  291. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.64.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.64.cat1.erb} +7 -7
  292. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.69.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.69.cat1.erb} +2 -2
  293. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.7.cat1.erb → r3_1/_2.16.840.1.113883.10.20.24.3.7.cat1.erb} +12 -9
  294. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.81.cat1.erb +33 -0
  295. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.82.cat1.erb +33 -0
  296. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.9.cat1.erb +41 -0
  297. data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.28.3.6.cat1.erb +17 -0
  298. data/templates/cat1/r3_1/_address.cat1.erb +9 -0
  299. data/templates/cat1/r3_1/_author.cat1.erb +28 -0
  300. data/templates/cat1/r3_1/_fulfills.cat1.erb +14 -0
  301. data/templates/cat1/r3_1/_id.cat1.erb +1 -0
  302. data/templates/cat1/r3_1/_measures.cat1.erb +93 -0
  303. data/templates/cat1/r3_1/_medication_details.cat1.erb +16 -0
  304. data/templates/cat1/r3_1/_medication_dispense.cat1.erb +22 -0
  305. data/templates/cat1/r3_1/_ordinality.cat1.erb +10 -0
  306. data/templates/cat1/r3_1/_organization.cat1.erb +9 -0
  307. data/templates/cat1/r3_1/_patient_data.cat1.erb +17 -0
  308. data/templates/cat1/r3_1/_providers.cat1.erb +76 -0
  309. data/templates/cat1/r3_1/_reason.cat1.erb +34 -0
  310. data/templates/cat1/r3_1/_record_target.cat1.erb +56 -0
  311. data/templates/cat1/r3_1/_reporting_parameters.cat1.erb +31 -0
  312. data/templates/cat1/r3_1/_result_value.cat1.erb +28 -0
  313. data/templates/cat1/r3_1/_telecom.cat1.erb +1 -0
  314. data/templates/cat1/r3_1/show.cat1.erb +183 -0
  315. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.1.cat1.erb +14 -0
  316. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.103.cat1.erb +17 -0
  317. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.105.cat1.erb +68 -0
  318. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.12.cat1.erb +53 -0
  319. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.135.cat1.erb +75 -0
  320. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.136.cat1.erb +52 -0
  321. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.140.cat1.erb +39 -0
  322. data/templates/cat1/{_2.16.840.1.113883.10.20.24.3.59.cat1.erb → r4/_2.16.840.1.113883.10.20.24.3.144.cat1.erb} +6 -6
  323. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.145.cat1.erb +24 -0
  324. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +23 -0
  325. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.18.cat1.erb +25 -0
  326. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.2.cat1.erb +29 -0
  327. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.22.cat1.erb +30 -0
  328. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.23.cat1.erb +116 -0
  329. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.3.cat1.erb +25 -0
  330. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +24 -0
  331. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.32.cat1.erb +21 -0
  332. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +22 -0
  333. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.38.cat1.erb +21 -0
  334. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.4.cat1.erb +29 -0
  335. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.41.cat1.erb +45 -0
  336. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.42.cat1.erb +38 -0
  337. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.43.cat1.erb +24 -0
  338. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.44.cat1.erb +25 -0
  339. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.45.cat1.erb +35 -0
  340. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.46.cat1.erb +30 -0
  341. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +47 -0
  342. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.51.cat1.erb +14 -0
  343. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.54.cat1.erb +32 -0
  344. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.55.cat1.erb +18 -0
  345. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.57.cat1.erb +23 -0
  346. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.59.cat1.erb +22 -0
  347. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.62.cat1.erb +36 -0
  348. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.63.cat1.erb +21 -0
  349. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.64.cat1.erb +52 -0
  350. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.7.cat1.erb +33 -0
  351. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.81.cat1.erb +33 -0
  352. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.82.cat1.erb +33 -0
  353. data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.9.cat1.erb +41 -0
  354. data/templates/cat1/r4/_2.16.840.1.113883.10.20.28.3.6.cat1.erb +17 -0
  355. data/templates/cat1/r4/_address.cat1.erb +7 -0
  356. data/templates/cat1/r4/_author.cat1.erb +28 -0
  357. data/templates/cat1/r4/_fulfills.cat1.erb +14 -0
  358. data/templates/cat1/r4/_id.cat1.erb +1 -0
  359. data/templates/cat1/r4/_measures.cat1.erb +93 -0
  360. data/templates/cat1/r4/_medication_details.cat1.erb +16 -0
  361. data/templates/cat1/r4/_medication_dispense.cat1.erb +22 -0
  362. data/templates/cat1/r4/_ordinality.cat1.erb +10 -0
  363. data/templates/cat1/r4/_organization.cat1.erb +9 -0
  364. data/templates/cat1/r4/_patient_data.cat1.erb +17 -0
  365. data/templates/cat1/r4/_providers.cat1.erb +76 -0
  366. data/templates/cat1/r4/_reason.cat1.erb +34 -0
  367. data/templates/cat1/r4/_record_target.cat1.erb +54 -0
  368. data/templates/cat1/r4/_reporting_parameters.cat1.erb +31 -0
  369. data/templates/cat1/r4/_result_value.cat1.erb +28 -0
  370. data/templates/cat1/r4/_telecom.cat1.erb +1 -0
  371. data/templates/cat1/r4/show.cat1.erb +192 -0
  372. data/templates/cat3/{_address.cat3.erb → r1/_address.cat3.erb} +0 -0
  373. data/templates/cat3/r1/_author.cat3.erb +28 -0
  374. data/templates/cat3/{_continuous_variable_value.cat3.erb → r1/_continuous_variable_value.cat3.erb} +0 -0
  375. data/templates/cat3/r1/_id.cat3.erb +1 -0
  376. data/templates/cat3/{_measure_data.cat3.erb → r1/_measure_data.cat3.erb} +7 -6
  377. data/templates/cat3/{_organization.cat3.erb → r1/_organization.cat3.erb} +0 -0
  378. data/templates/cat3/{_performance_rate.cat3.erb → r1/_performance_rate.cat3.erb} +1 -3
  379. data/templates/cat3/{_providers.cat3.erb → r1/_providers.cat3.erb} +0 -0
  380. data/templates/cat3/{_reporting_parameters.cat3.erb → r1/_reporting_parameters.cat3.erb} +0 -0
  381. data/templates/cat3/{_supplemental_data.cat3.erb → r1/_supplemental_data.cat3.erb} +2 -0
  382. data/templates/cat3/r1/_telecom.cat3.erb +1 -0
  383. data/templates/cat3/{show.cat3.erb → r1/show.cat3.erb} +5 -5
  384. data/templates/cat3/r1_1/_address.cat3.erb +9 -0
  385. data/templates/cat3/r1_1/_author.cat3.erb +28 -0
  386. data/templates/cat3/r1_1/_continuous_variable_value.cat3.erb +20 -0
  387. data/templates/cat3/r1_1/_id.cat3.erb +1 -0
  388. data/templates/cat3/r1_1/_measure_data.cat3.erb +136 -0
  389. data/templates/cat3/r1_1/_organization.cat3.erb +6 -0
  390. data/templates/cat3/r1_1/_performance_rate.cat3.erb +18 -0
  391. data/templates/{cat1/_providers.cat1.erb → cat3/r1_1/_providers.cat3.erb} +18 -18
  392. data/templates/{cat1/_reporting_parameters.cat1.erb → cat3/r1_1/_reporting_parameters.cat3.erb} +5 -1
  393. data/templates/cat3/r1_1/_supplemental_data.cat3.erb +38 -0
  394. data/templates/cat3/r1_1/_telecom.cat3.erb +1 -0
  395. data/templates/cat3/r1_1/show.cat3.erb +150 -0
  396. data/templates/cat3/r2/_address.cat3.erb +9 -0
  397. data/templates/cat3/r2/_author.cat3.erb +28 -0
  398. data/templates/cat3/r2/_continuous_variable_value.cat3.erb +20 -0
  399. data/templates/cat3/r2/_id.cat3.erb +1 -0
  400. data/templates/cat3/r2/_measure_data.cat3.erb +136 -0
  401. data/templates/cat3/r2/_organization.cat3.erb +6 -0
  402. data/templates/cat3/r2/_performance_rate.cat3.erb +19 -0
  403. data/templates/cat3/r2/_providers.cat3.erb +57 -0
  404. data/templates/cat3/r2/_reporting_parameters.cat3.erb +29 -0
  405. data/templates/cat3/r2/_supplemental_data.cat3.erb +38 -0
  406. data/templates/cat3/r2/_telecom.cat3.erb +1 -0
  407. data/templates/cat3/r2/show.cat3.erb +150 -0
  408. data/templates/cat3/r2_1/_address.cat3.erb +9 -0
  409. data/templates/cat3/r2_1/_author.cat3.erb +28 -0
  410. data/templates/cat3/r2_1/_continuous_variable_value.cat3.erb +20 -0
  411. data/templates/cat3/r2_1/_id.cat3.erb +1 -0
  412. data/templates/cat3/r2_1/_measure_data.cat3.erb +136 -0
  413. data/templates/cat3/r2_1/_organization.cat3.erb +6 -0
  414. data/templates/cat3/r2_1/_performance_rate.cat3.erb +19 -0
  415. data/templates/cat3/r2_1/_providers.cat3.erb +57 -0
  416. data/templates/cat3/r2_1/_reporting_parameters.cat3.erb +20 -0
  417. data/templates/cat3/r2_1/_reporting_parameters_act.cat3.erb +10 -0
  418. data/templates/cat3/r2_1/_supplemental_data.cat3.erb +38 -0
  419. data/templates/cat3/r2_1/_telecom.cat3.erb +1 -0
  420. data/templates/cat3/r2_1/show.cat3.erb +153 -0
  421. data/templates/ccda/_medical_equipment.ccda.erb +1 -1
  422. data/templates/ccda/_social_history.ccda.erb +2 -2
  423. data/templates/ccda/_vital_signs.ccda.erb +1 -1
  424. data/templates/html/_entries_by_section.html.erb +1 -1
  425. metadata +425 -153
  426. data/lib/health-data-standards/import/cat1/procedure_importer.rb +0 -42
  427. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.11.cat1.erb +0 -55
  428. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.13.cat1.erb +0 -38
  429. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +0 -22
  430. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +0 -22
  431. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +0 -20
  432. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +0 -27
  433. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.51.cat1.erb +0 -13
  434. data/templates/cat1/_reason.cat1.erb +0 -23
@@ -1,280 +1,304 @@
1
1
  module HQMF2
2
2
  # Class representing an HQMF document
3
3
  class Document
4
+ include HQMF2::Utilities, HQMF2::DocumentUtilities
5
+ NAMESPACES = { 'cda' => 'urn:hl7-org:v3',
6
+ 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
7
+ 'qdm' => 'urn:hhs-qdm:hqmf-r2-extensions:v1' }
4
8
 
5
- include HQMF2::Utilities
6
- NAMESPACES = {'cda' => 'urn:hl7-org:v3', 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance'}
9
+ attr_reader :measure_period, :id, :hqmf_set_id, :hqmf_version_number, :populations, :attributes,
10
+ :source_data_criteria
7
11
 
8
- attr_reader :measure_period, :id, :hqmf_set_id, :hqmf_version_number, :populations, :attributes, :source_data_criteria
9
-
10
- # Create a new HQMF2::Document instance by parsing at file at the supplied path
11
- # @param [String] path the path to the HQMF document
12
- def initialize(hqmf_contents)
13
- @doc = @entry = Document.parse(hqmf_contents)
14
- @id = attr_val('cda:QualityMeasureDocument/cda:id/@extension')
15
- @hqmf_set_id = attr_val('cda:QualityMeasureDocument/cda:setId/@extension')
16
- @hqmf_version_number = attr_val('cda:QualityMeasureDocument/cda:versionNumber/@value').to_i
17
- measure_period_def = @doc.at_xpath('cda:QualityMeasureDocument/cda:controlVariable/cda:measurePeriod/cda:value', NAMESPACES)
18
- if measure_period_def
19
- @measure_period = EffectiveTime.new(measure_period_def)
20
- end
21
-
22
- # Extract measure attributes
23
- @attributes = @doc.xpath('/cda:QualityMeasureDocument/cda:subjectOf/cda:measureAttribute', NAMESPACES).collect do |attribute|
24
- id = attribute.at_xpath('./cda:id/@root', NAMESPACES).try(:value)
25
- code = attribute.at_xpath('./cda:code/@code', NAMESPACES).try(:value)
26
- name = attribute.at_xpath('./cda:code/cda:displayName/@value', NAMESPACES).try(:value)
27
- value = attribute.at_xpath('./cda:value/@value', NAMESPACES).try(:value)
28
-
29
- id_obj = nil
30
- if attribute.at_xpath('./cda:id', NAMESPACES)
31
- id_obj = HQMF::Identifier.new(attribute.at_xpath('./cda:id/@xsi:type', NAMESPACES).try(:value), id, attribute.at_xpath('./cda:id/@extension', NAMESPACES).try(:value))
32
- end
33
-
34
- code_obj = nil;
35
- if attribute.at_xpath('./cda:code', NAMESPACES)
36
- nullFlavor = attribute.at_xpath('./cda:code/@nullFlavor', NAMESPACES).try(:value)
37
- oText = attribute.at_xpath('./cda:code/cda:originalText', NAMESPACES) ? attribute.at_xpath('./cda:code/cda:originalText/@value', NAMESPACES).try(:value) : nil
38
- code_obj = HQMF::Coded.new(attribute.at_xpath('./cda:code/@xsi:type', NAMESPACES).try(:value) || 'CD',
39
- attribute.at_xpath('./cda:code/@codeSystem', NAMESPACES).try(:value),
40
- code,
41
- attribute.at_xpath('./cda:code/@valueSet', NAMESPACES).try(:value),
42
- name,
43
- nullFlavor,
44
- oText)
45
-
46
-
47
- # Mapping for nil values to align with 1.0 parsing
48
- if code == nil
49
- code = nullFlavor
50
- end
51
-
52
- if name == nil
53
- name = oText
54
- end
55
-
56
- end
12
+ # Create a new HQMF2::Document instance by parsing the given HQMF contents
13
+ # @param [String] containing the HQMF contents to be parsed
14
+ def initialize(hqmf_contents, use_default_measure_period = true)
15
+ setup_default_values(hqmf_contents, use_default_measure_period)
57
16
 
58
- value_obj = nil
59
- if attribute.at_xpath('./cda:value', NAMESPACES)
60
- type = attribute.at_xpath('./cda:value/@xsi:type', NAMESPACES).try(:value)
61
- case type
62
- when 'II'
63
- value_obj = HQMF::Identifier.new(type, attribute.at_xpath('./cda:value/@root', NAMESPACES).try(:value), attribute.at_xpath('./cda:value/@extension', NAMESPACES).try(:value))
64
- if value == nil
65
- value = attribute.at_xpath('./cda:value/@extension', NAMESPACES).try(:value)
66
- end
67
- when 'ED'
68
- value_obj = HQMF::ED.new(type, value, attribute.at_xpath('./cda:value/@mediaType', NAMESPACES).try(:value))
69
- when 'CD'
70
- value_obj = HQMF::Coded.new('CD', attribute.at_xpath('./cda:value/@codeSystem', NAMESPACES).try(:value), attribute.at_xpath('./cda:value/@code', NAMESPACES).try(:value), attribute.at_xpath('./cda:value/@valueSet', NAMESPACES).try(:value), attribute.at_xpath('./cda:value/cda:displayName/@value', NAMESPACES).try(:value))
71
- else
72
- value_obj = value.present? ? HQMF::GenericValueContainer.new(type, value) : HQMF::AnyValue.new(type)
73
- end
74
- end
75
-
76
- # Handle the cms_id
77
- if name == "eMeasure Identifier"
78
- @cms_id = "CMS#{value}v#{@hqmf_version_number}"
79
- end
17
+ extract_criteria
80
18
 
81
- HQMF::Attribute.new(id, code, value, nil, name, id_obj, code_obj, value_obj)
82
- end
83
-
84
- # Extract the data criteria
85
- @data_criteria = []
86
- @source_data_criteria = []
87
- @doc.xpath('cda:QualityMeasureDocument/cda:component/cda:dataCriteriaSection/cda:entry', NAMESPACES).each do |entry|
88
- criteria = DataCriteria.new(entry)
89
- if criteria.is_source_data_criteria
90
- @source_data_criteria << criteria
91
- else
92
- @data_criteria << criteria
93
- end
94
- end
95
-
96
19
  # Extract the population criteria and population collections
97
- @populations = []
98
- @population_criteria = []
99
-
100
- population_counters = {}
101
- ids_by_hqmf_id = {}
102
-
103
- @doc.xpath('cda:QualityMeasureDocument/cda:component/cda:populationCriteriaSection', NAMESPACES).each_with_index do |population_def, population_index|
104
- population = {}
105
-
106
- stratifier_id_def = population_def.at_xpath('cda:templateId/cda:item[@root="'+HQMF::Document::STRATIFIED_POPULATION_TEMPLATE_ID+'"]/@controlInformationRoot', NAMESPACES)
107
- population['stratification'] = stratifier_id_def.value if stratifier_id_def
108
-
109
- {
110
- HQMF::PopulationCriteria::IPP => 'initialPopulationCriteria',
111
- HQMF::PopulationCriteria::DENOM => 'denominatorCriteria',
112
- HQMF::PopulationCriteria::NUMER => 'numeratorCriteria',
113
- HQMF::PopulationCriteria::DENEXCEP => 'denominatorExceptionCriteria',
114
- HQMF::PopulationCriteria::DENEX => 'denominatorExclusionCriteria',
115
- HQMF::PopulationCriteria::STRAT => 'stratifierCriteria',
116
- HQMF::PopulationCriteria::MSRPOPL => 'measurePopulationCriteria'
117
- }.each_pair do |criteria_id, criteria_element_name|
118
- criteria_def = population_def.at_xpath("cda:component[cda:#{criteria_element_name}]", NAMESPACES)
119
-
120
- if criteria_def
121
-
122
- criteria = PopulationCriteria.new(criteria_def, self)
123
-
124
- # check to see if we have an identical population criteria.
125
- # this can happen since the hqmf 2.0 will export a DENOM, NUMER, etc for each population, even if identical.
126
- # if we have identical, just re-use it rather than creating DENOM_1, NUMER_1, etc.
127
- identical = @population_criteria.select {|pc| pc.to_model.base_json.to_json == criteria.to_model.base_json.to_json}
128
-
129
- if (identical.empty?)
130
- # this section constructs a human readable id. The first IPP will be IPP, the second will be IPP_1, etc. This allows the populations to be
131
- # more readable. The alternative would be to have the hqmf ids in the populations, which would work, but is difficult to read the populations.
132
- if ids_by_hqmf_id["#{criteria.hqmf_id}-#{population['stratification']}"]
133
- criteria.create_human_readable_id(ids_by_hqmf_id[criteria.hqmf_id])
134
- else
135
- if population_counters[criteria_id]
136
- population_counters[criteria_id] += 1
137
- criteria.create_human_readable_id("#{criteria_id}_#{population_counters[criteria_id]}")
138
- else
139
- population_counters[criteria_id] = 0
140
- criteria.create_human_readable_id(criteria_id)
141
- end
142
- ids_by_hqmf_id["#{criteria.hqmf_id}-#{population['stratification']}"] = criteria.id
143
- end
144
-
145
-
146
- @population_criteria << criteria
147
- population[criteria_id] = criteria.id
148
- else
149
- population[criteria_id] = identical.first.id
150
- end
151
- end
152
- end
153
-
154
-
155
- id_def = population_def.at_xpath('cda:id/@extension', NAMESPACES)
156
- population['id'] = id_def ? id_def.value : "Population#{population_index}"
157
- title_def = population_def.at_xpath('cda:title/@value', NAMESPACES)
158
- population['title'] = title_def ? title_def.value : "Population #{population_index}"
159
- observation_section = @doc.xpath('cda:QualityMeasureDocument/cda:component/cda:measureObservationsSection', NAMESPACES)
160
- if !observation_section.empty?
161
- population['OBSERV'] = 'OBSERV'
162
- end
163
- @populations << population
164
- end
20
+ pop_helper = HQMF2::DocumentPopulationHelper.new(@entry, @doc, self, @id_generator, @reference_ids)
21
+ @populations, @population_criteria = pop_helper.extract_populations_and_criteria
165
22
 
166
-
167
- #look for observation data in separate section but create a population for it if it exists
168
- observation_section = @doc.xpath('cda:QualityMeasureDocument/cda:component/cda:measureObservationsSection', NAMESPACES)
169
- if !observation_section.empty?
170
- observation_section.xpath("cda:definition",NAMESPACES).each do |criteria_def|
171
- criteria_id = "OBSERV"
172
- population = {}
173
- criteria = PopulationCriteria.new(criteria_def, self)
174
- criteria.type="OBSERV"
175
- # this section constructs a human readable id. The first IPP will be IPP, the second will be IPP_1, etc. This allows the populations to be
176
- # more readable. The alternative would be to have the hqmf ids in the populations, which would work, but is difficult to read the populations.
177
- if ids_by_hqmf_id["#{criteria.hqmf_id}"]
178
- criteria.create_human_readable_id(ids_by_hqmf_id[criteria.hqmf_id])
179
- else
180
- if population_counters[criteria_id]
181
- population_counters[criteria_id] += 1
182
- criteria.create_human_readable_id("#{criteria_id}_#{population_counters[criteria_id]}")
183
- else
184
- population_counters[criteria_id] = 0
185
- criteria.create_human_readable_id(criteria_id)
186
- end
187
- ids_by_hqmf_id["#{criteria.hqmf_id}"] = criteria.id
188
- end
189
-
190
- @population_criteria << criteria
191
-
192
- population[criteria_id] = criteria.id
193
- @populations << population
194
- end
23
+ # Remove any data criteria from the main data criteria list that already has an equivalent member
24
+ # and no references to it. The goal of this is to remove any data criteria that should not
25
+ # be purely a source.
26
+ @data_criteria.reject! do |dc|
27
+ criteria_covered_by_criteria?(dc)
195
28
  end
196
-
197
29
  end
198
-
30
+
199
31
  # Get the title of the measure
200
32
  # @return [String] the title
201
33
  def title
202
34
  @doc.at_xpath('cda:QualityMeasureDocument/cda:title/@value', NAMESPACES).inner_text
203
35
  end
204
-
36
+
205
37
  # Get the description of the measure
206
38
  # @return [String] the description
207
39
  def description
208
40
  description = @doc.at_xpath('cda:QualityMeasureDocument/cda:text/@value', NAMESPACES)
209
- description==nil ? '' : description.inner_text
41
+ description.nil? ? '' : description.inner_text
210
42
  end
211
-
43
+
212
44
  # Get all the population criteria defined by the measure
213
45
  # @return [Array] an array of HQMF2::PopulationCriteria
214
46
  def all_population_criteria
215
47
  @population_criteria
216
48
  end
217
-
49
+
218
50
  # Get a specific population criteria by id.
219
51
  # @param [String] id the population identifier
220
52
  # @return [HQMF2::PopulationCriteria] the matching criteria, raises an Exception if not found
221
53
  def population_criteria(id)
222
54
  find(@population_criteria, :id, id)
223
55
  end
224
-
56
+
225
57
  # Get all the data criteria defined by the measure
226
58
  # @return [Array] an array of HQMF2::DataCriteria describing the data elements used by the measure
227
59
  def all_data_criteria
228
60
  @data_criteria
229
61
  end
230
-
62
+
231
63
  # Get a specific data criteria by id.
232
64
  # @param [String] id the data criteria identifier
233
65
  # @return [HQMF2::DataCriteria] the matching data criteria, raises an Exception if not found
234
66
  def data_criteria(id)
235
67
  find(@data_criteria, :id, id)
236
68
  end
237
-
238
- # Parse an XML document from the supplied contents
69
+
70
+ # Adds data criteria to the Document's criteria list
71
+ # needed so data criteria can be added to a document from other objects
72
+ def add_data_criteria(dc)
73
+ @data_criteria << dc
74
+ end
75
+
76
+ # Finds a data criteria by it's local variable name
77
+ def find_criteria_by_lvn(local_variable_name)
78
+ find(@data_criteria, :local_variable_name, local_variable_name)
79
+ end
80
+
81
+ # Get ids of data criteria directly referenced by others
82
+ # @return [Array] an array of ids of directly referenced data criteria
83
+ def all_reference_ids
84
+ @reference_ids
85
+ end
86
+
87
+ # Adds id of a data criteria to the list of reference ids
88
+ def add_reference_id(id)
89
+ @reference_ids << id
90
+ end
91
+
92
+ # Parse an XML document from the supplied contents
239
93
  # @return [Nokogiri::XML::Document]
240
94
  def self.parse(hqmf_contents)
241
- doc = hqmf_contents.kind_of?(Nokogiri::XML::Document) ? hqmf_contents : Nokogiri::XML(hqmf_contents)
95
+ doc = hqmf_contents.is_a?(Nokogiri::XML::Document) ? hqmf_contents : Nokogiri::XML(hqmf_contents)
242
96
  doc.root.add_namespace_definition('cda', 'urn:hl7-org:v3')
243
97
  doc
244
98
  end
245
-
246
- def to_model
247
99
 
248
- dcs = all_data_criteria.collect {|dc| dc.to_model}
249
- pcs = all_population_criteria.collect {|pc| pc.to_model}
250
- sdc = source_data_criteria.collect{|dc| dc.to_model}
251
- dcs = update_data_criteria(dcs, sdc)
252
- HQMF::Document.new(id, id, hqmf_set_id, hqmf_version_number, @cms_id, title, description, pcs, dcs, sdc, attributes, measure_period.to_model, populations)
100
+ # Generates this classes hqmf-model equivalent
101
+ def to_model
102
+ dcs = all_data_criteria.collect(&:to_model)
103
+ pcs = all_population_criteria.collect(&:to_model)
104
+ sdc = source_data_criteria.collect(&:to_model)
105
+ HQMF::Document.new(@id, @id, @hqmf_set_id, @hqmf_version_number, @cms_id,
106
+ title, description, pcs, dcs, sdc,
107
+ @attributes, @measure_period, @populations)
253
108
  end
254
109
 
255
- # Update the data criteria to handle variables properly
256
- def update_data_criteria(data_criteria, source_data_criteria)
257
- # step through each criteria and look for groupers (type derived) with one child
258
- data_criteria.map do |criteria|
259
- if criteria.type == "derived".to_sym && criteria.children_criteria.length == 1
260
- source_data_criteria.each do |source_criteria|
261
- if source_criteria.title == criteria.children_criteria[0]
262
- criteria.children_criteria = source_criteria.children_criteria
263
- #if criteria.is_same_type?(source_criteria)
264
- criteria.update_copy( source_criteria.hard_status, source_criteria.title, source_criteria.description,
265
- source_criteria.derivation_operator, source_criteria.definition )#, occur_letter )
266
- end
267
- end
268
- end
269
- criteria
270
- end
110
+ # Finds an element within the collection given that has an instance variable or method of "attribute" with a value
111
+ # of "value"
112
+ def find(collection, attribute, value)
113
+ collection.find { |e| e.send(attribute) == value }
271
114
  end
272
115
 
273
-
274
116
  private
117
+
118
+ # Handles setup of the base values of the document, defined here as ones that are either
119
+ # obtained from the xml directly or with limited parsing
120
+ def setup_default_values(hqmf_contents, use_default_measure_period)
121
+ @id_generator = IdGenerator.new
122
+ @doc = @entry = Document.parse(hqmf_contents)
123
+
124
+ @id = attr_val('cda:QualityMeasureDocument/cda:id/@extension') ||
125
+ attr_val('cda:QualityMeasureDocument/cda:id/@root').upcase
126
+ @hqmf_set_id = attr_val('cda:QualityMeasureDocument/cda:setId/@extension') ||
127
+ attr_val('cda:QualityMeasureDocument/cda:setId/@root').upcase
128
+ @hqmf_version_number = attr_val('cda:QualityMeasureDocument/cda:versionNumber/@value')
129
+
130
+ # TODO: -- figure out if this is the correct thing to do -- probably not, but is
131
+ # necessary to get the bonnie comparison to work. Currently
132
+ # defaulting measure period to a period of 1 year from 2012 to 2013 this is overriden during
133
+ # calculation with correct year information . Need to investigate parsing mp from meaures.
134
+ @measure_period = extract_measure_period_or_default(use_default_measure_period)
135
+
136
+ # Extract measure attributes
137
+ # TODO: Review
138
+ @attributes = @doc.xpath('/cda:QualityMeasureDocument/cda:subjectOf/cda:measureAttribute', NAMESPACES)
139
+ .collect do |attribute|
140
+ read_attribute(attribute)
141
+ end
142
+
143
+ @data_criteria = []
144
+ @source_data_criteria = []
145
+ @data_criteria_references = {}
146
+ @occurrences_map = {}
147
+
148
+ # Used to keep track of referenced data criteria ids
149
+ @reference_ids = []
150
+ end
151
+
152
+ # Extracts a measure period from the document or returns the default measure period
153
+ # (if the default value is set to true).
154
+ def extract_measure_period_or_default(default)
155
+ if default
156
+ mp_low = HQMF::Value.new('TS', nil, '201201010000', nil, nil, nil)
157
+ mp_high = HQMF::Value.new('TS', nil, '201212312359', nil, nil, nil)
158
+ mp_width = HQMF::Value.new('PQ', 'a', '1', nil, nil, nil)
159
+ HQMF::EffectiveTime.new(mp_low, mp_high, mp_width)
160
+ else
161
+ measure_period_def = @doc.at_xpath('cda:QualityMeasureDocument/cda:controlVariable/cda:measurePeriod/cda:value',
162
+ NAMESPACES)
163
+ EffectiveTime.new(measure_period_def).to_model if measure_period_def
164
+ end
165
+ end
166
+
167
+ # Handles parsing the attributes of the document
168
+ def read_attribute(attribute)
169
+ id = attribute.at_xpath('./cda:id/@root', NAMESPACES).try(:value)
170
+ code = attribute.at_xpath('./cda:code/@code', NAMESPACES).try(:value)
171
+ name = attribute.at_xpath('./cda:code/cda:displayName/@value', NAMESPACES).try(:value)
172
+ value = attribute.at_xpath('./cda:value/@value', NAMESPACES).try(:value)
173
+
174
+ id_obj = nil
175
+ if attribute.at_xpath('./cda:id', NAMESPACES)
176
+ id_obj = HQMF::Identifier.new(attribute.at_xpath('./cda:id/@xsi:type', NAMESPACES).try(:value),
177
+ id,
178
+ attribute.at_xpath('./cda:id/@extension', NAMESPACES).try(:value))
179
+ end
180
+
181
+ code_obj = nil
182
+ if attribute.at_xpath('./cda:code', NAMESPACES)
183
+ code_obj, null_flavor, o_text = handle_attribute_code(attribute, code, name)
184
+
185
+ # Mapping for nil values to align with 1.0 parsing
186
+ code = null_flavor if code.nil?
187
+ name = o_text if name.nil?
188
+
189
+ end
190
+
191
+ value_obj = nil
192
+ value_obj = handle_attribute_value(attribute, value) if attribute.at_xpath('./cda:value', NAMESPACES)
193
+
194
+ # Handle the cms_id
195
+ @cms_id = "CMS#{value}v#{@hqmf_version_number.to_i}" if name.include? 'eMeasure Identifier'
196
+
197
+ HQMF::Attribute.new(id, code, value, nil, name, id_obj, code_obj, value_obj)
198
+ end
199
+
200
+ # Extracts the code used by a particular attribute
201
+ def handle_attribute_code(attribute, code, name)
202
+ null_flavor = attribute.at_xpath('./cda:code/@nullFlavor', NAMESPACES).try(:value)
203
+ o_text = attribute.at_xpath('./cda:code/cda:originalText/@value', NAMESPACES).try(:value)
204
+ code_obj = HQMF::Coded.new(attribute.at_xpath('./cda:code/@xsi:type', NAMESPACES).try(:value) || 'CD',
205
+ attribute.at_xpath('./cda:code/@codeSystem', NAMESPACES).try(:value),
206
+ code,
207
+ attribute.at_xpath('./cda:code/@valueSet', NAMESPACES).try(:value),
208
+ name,
209
+ null_flavor,
210
+ o_text)
211
+ [code_obj, null_flavor, o_text]
212
+ end
213
+
214
+ # Extracts the value used by a particular attribute
215
+ def handle_attribute_value(attribute, value)
216
+ type = attribute.at_xpath('./cda:value/@xsi:type', NAMESPACES).try(:value)
217
+ case type
218
+ when 'II'
219
+ if value.nil?
220
+ value = attribute.at_xpath('./cda:value/@extension', NAMESPACES).try(:value)
221
+ end
222
+ HQMF::Identifier.new(type,
223
+ attribute.at_xpath('./cda:value/@root', NAMESPACES).try(:value),
224
+ attribute.at_xpath('./cda:value/@extension', NAMESPACES).try(:value))
225
+ when 'ED'
226
+ HQMF::ED.new(type, value, attribute.at_xpath('./cda:value/@mediaType', NAMESPACES).try(:value))
227
+ when 'CD'
228
+ HQMF::Coded.new('CD',
229
+ attribute.at_xpath('./cda:value/@codeSystem', NAMESPACES).try(:value),
230
+ attribute.at_xpath('./cda:value/@code', NAMESPACES).try(:value),
231
+ attribute.at_xpath('./cda:value/@valueSet', NAMESPACES).try(:value),
232
+ attribute.at_xpath('./cda:value/cda:displayName/@value', NAMESPACES).try(:value))
233
+ else
234
+ value.present? ? HQMF::GenericValueContainer.new(type, value) : HQMF::AnyValue.new(type)
235
+ end
236
+ end
237
+
238
+ def extract_criteria
239
+ # Extract the data criteria
240
+ extracted_criteria = []
241
+ @doc.xpath('cda:QualityMeasureDocument/cda:component/cda:dataCriteriaSection/cda:entry', NAMESPACES)
242
+ .each do |entry|
243
+ extracted_criteria << entry
244
+ end
245
+
246
+ # Extract the source data criteria from data criteria
247
+ @source_data_criteria, collapsed_source_data_criteria = SourceDataCriteriaHelper.get_source_data_criteria_list(
248
+ extracted_criteria, @data_criteria_references, @occurrences_map)
249
+
250
+ extracted_criteria.each do |entry|
251
+ criteria = DataCriteria.new(entry, @data_criteria_references, @occurrences_map)
252
+ handle_data_criteria(criteria, collapsed_source_data_criteria)
253
+ @data_criteria << criteria
254
+ end
255
+ end
256
+
257
+ def handle_data_criteria(criteria, collapsed_source_data_criteria)
258
+ # Sometimes there are multiple criteria with the same ID, even though they're different; in the HQMF
259
+ # criteria refer to parent criteria via outboundRelationship, using an extension (aka ID) and a root;
260
+ # we use just the extension to follow the reference, and build the lookup hash using that; since they
261
+ # can repeat, we wind up overwriting some content. This becomes important when we want, for example,
262
+ # the code_list_id and we overwrite the parent with the code_list_id with a child with the same ID
263
+ # without the code_list_id. As a temporary approach, we only overwrite a data criteria reference if
264
+ # it doesn't have a code_list_id. As a longer term approach we may want to use the root for lookups.
265
+ if criteria && (@data_criteria_references[criteria.id].try(:code_list_id).nil?)
266
+ @data_criteria_references[criteria.id] = criteria
267
+ end
268
+ if collapsed_source_data_criteria.key?(criteria.id)
269
+ candidate = find(all_data_criteria, :id, collapsed_source_data_criteria[criteria.id])
270
+ # derived criteria should not be collapsed... they do not have enough info to be collapsed and may cross into the wrong criteria
271
+ # only add the collapsed as a source for derived if it is stripped of any temporal references, fields, etc. to make sure we don't cross into an incorrect source
272
+ if ((criteria.definition != 'derived') || (!candidate.nil? && SourceDataCriteriaHelper.already_stripped?(candidate)))
273
+ criteria.instance_variable_set(:@source_data_criteria, collapsed_source_data_criteria[criteria.id])
274
+ end
275
+ end
276
+
277
+ handle_variable(criteria, collapsed_source_data_criteria) if criteria.variable
278
+ handle_specific_source_data_criteria_reference(criteria)
279
+ @reference_ids.concat(criteria.children_criteria)
280
+ if criteria.temporal_references
281
+ criteria.temporal_references.each do |tr|
282
+ @reference_ids << tr.reference.id if tr.reference.id != HQMF::Document::MEASURE_PERIOD_ID
283
+ end
284
+ end
285
+ end
275
286
 
276
- def find(collection, attribute, value)
277
- collection.find {|e| e.send(attribute)==value}
287
+ # For specific occurrence data criteria, make sure the source data criteria reference points
288
+ # to the correct source data criteria.
289
+ def handle_specific_source_data_criteria_reference(criteria)
290
+ original_sdc = find(@source_data_criteria, :id, criteria.source_data_criteria)
291
+ updated_sdc = find(@source_data_criteria, :id, criteria.id)
292
+ if !updated_sdc.nil? && !criteria.specific_occurrence.nil? && (original_sdc.nil? || original_sdc.specific_occurrence.nil?)
293
+ criteria.instance_variable_set(:@source_data_criteria, criteria.id)
294
+ end
295
+ return if original_sdc.nil?
296
+ if (criteria.specific_occurrence && !original_sdc.specific_occurrence)
297
+ original_sdc.instance_variable_set(:@specific_occurrence, criteria.specific_occurrence)
298
+ original_sdc.instance_variable_set(:@specific_occurrence_const, criteria.specific_occurrence_const)
299
+ original_sdc.instance_variable_set(:@code_list_id, criteria.code_list_id)
300
+ end
278
301
  end
302
+
279
303
  end
280
304
  end