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
@@ -2,28 +2,30 @@ module HQMF
2
2
  # Represents an HQMF population criteria, also supports all the same methods as
3
3
  # HQMF::Precondition
4
4
  class PopulationCriteria
5
-
5
+
6
6
  include HQMF::Conversion::Utilities
7
7
 
8
8
  attr_reader :preconditions, :id, :type, :title, :hqmf_id, :comments
9
9
  attr_accessor :aggregator
10
-
10
+
11
11
  IPP = 'IPP'
12
12
  DENOM = 'DENOM'
13
13
  NUMER = 'NUMER'
14
+ NUMEX = 'NUMEX'
14
15
  DENEXCEP = 'DENEXCEP'
15
16
  DENEX = 'DENEX'
16
17
  MSRPOPL = 'MSRPOPL'
17
18
  OBSERV = 'OBSERV'
19
+ MSRPOPLEX = 'MSRPOPLEX'
18
20
 
19
21
  STRAT = 'STRAT'
20
-
21
- ALL_POPULATION_CODES = [STRAT, IPP, DENOM, DENEX, NUMER, DENEXCEP, MSRPOPL, OBSERV]
22
-
22
+
23
+ ALL_POPULATION_CODES = [STRAT, IPP, DENOM, DENEX, NUMER, NUMEX, DENEXCEP, MSRPOPL, OBSERV, MSRPOPLEX]
24
+
23
25
  # Create a new population criteria
24
26
  # @param [String] id
25
27
  # @param [String] hqmf_id
26
- # @param [Array#Precondition] preconditions
28
+ # @param [Array#Precondition] preconditions
27
29
  # @param [String] title (optional)
28
30
  def initialize(id, hqmf_id, type, preconditions, title='', aggregator=nil, comments=nil)
29
31
  @id = id
@@ -34,7 +36,7 @@ module HQMF
34
36
  @aggregator = aggregator
35
37
  @comments = comments
36
38
  end
37
-
39
+
38
40
  # Create a new population criteria from a JSON hash keyed off symbols
39
41
  def self.from_json(id, json)
40
42
  preconditions = json["preconditions"].map do |precondition|
@@ -45,21 +47,21 @@ module HQMF
45
47
  hqmf_id = json['hqmf_id']
46
48
  aggregator = json['aggregator']
47
49
  comments = json['comments']
48
-
50
+
49
51
  HQMF::PopulationCriteria.new(id, hqmf_id, type, preconditions, title, aggregator, comments)
50
52
  end
51
-
53
+
52
54
  def to_json
53
55
  {self.id.to_sym => base_json}
54
56
  end
55
-
57
+
56
58
  def base_json
57
59
  x = nil
58
60
  json = build_hash(self, [:conjunction?, :type, :title, :hqmf_id, :aggregator, :comments])
59
61
  json[:preconditions] = x if x = json_array(@preconditions)
60
62
  json
61
63
  end
62
-
64
+
63
65
  # Return true of this precondition represents a conjunction with nested preconditions
64
66
  # or false of this precondition is a reference to a data criteria
65
67
  # if it is an observation population criteria, then it is not a conjunction, it is instead doing a calculation
@@ -70,23 +72,23 @@ module HQMF
70
72
  # Get the conjunction code, e.g. allTrue, atLeastOneTrue
71
73
  # @return [String] conjunction code
72
74
  def conjunction_code
73
-
75
+
74
76
  case @type
75
77
  when IPP, STRAT, DENOM, NUMER, MSRPOPL
76
78
  HQMF::Precondition::ALL_TRUE
77
- when DENEXCEP, DENEX
79
+ when DENEXCEP, DENEX, MSRPOPLEX, NUMEX
78
80
  HQMF::Precondition::AT_LEAST_ONE_TRUE
79
81
  else
80
82
  raise "Unknown population type [#{@type}]"
81
83
  end
82
-
84
+
83
85
  end
84
-
86
+
85
87
  # Can't have negation on population so this is the same as conjunction_code
86
88
  def conjunction_code_with_negation
87
89
  conjunction_code
88
90
  end
89
-
91
+
90
92
  def referenced_data_criteria
91
93
  data_criteria_ids = []
92
94
  @preconditions.each do |precondition|
@@ -94,7 +96,7 @@ module HQMF
94
96
  end if @preconditions
95
97
  data_criteria_ids
96
98
  end
97
-
99
+
98
100
  end
99
-
101
+
100
102
  end
@@ -22,18 +22,19 @@ module HQMF
22
22
  }
23
23
 
24
24
  attr_reader :id, :preconditions, :reference, :conjunction_code
25
- attr_accessor :negation
25
+ attr_accessor :negation, :comments
26
26
 
27
27
  # Create a new population criteria
28
28
  # @param [Array#Precondition] preconditions
29
29
  # @param [Reference] reference
30
30
  # @param [String] conjunction_code
31
- def initialize(id, preconditions, reference, conjunction_code, negation)
31
+ def initialize(id, preconditions, reference, conjunction_code, negation, comments=nil)
32
32
  @preconditions = preconditions || []
33
33
  @reference = reference
34
34
  @conjunction_code = conjunction_code
35
35
  @negation = negation
36
36
  @id = id
37
+ @comments = comments
37
38
  end
38
39
 
39
40
  def conjunction_code_with_negation
@@ -52,8 +53,9 @@ module HQMF
52
53
  reference = Reference.new(json["reference"]) if json["reference"]
53
54
  conjunction_code = json["conjunction_code"] if json["conjunction_code"]
54
55
  negation = json["negation"] if json["negation"]
56
+ comments = json['comments'] if json['comments']
55
57
 
56
- HQMF::Precondition.new(id, preconditions, reference, conjunction_code, negation)
58
+ HQMF::Precondition.new(id, preconditions, reference, conjunction_code, negation, comments)
57
59
  end
58
60
 
59
61
  def to_json
@@ -64,6 +66,7 @@ module HQMF
64
66
  json[:preconditions] = x if x = json_array(@preconditions)
65
67
  json[:conjunction_code] = self.conjunction_code if self.conjunction_code && self.preconditions.length > 0
66
68
  json[:negation] = self.negation if self.negation
69
+ json[:comments] = self.comments if self.comments
67
70
  json
68
71
  end
69
72
 
@@ -264,7 +264,7 @@ module HQMF
264
264
  class SubsetOperator
265
265
  include HQMF::Conversion::Utilities
266
266
 
267
- TYPES = ['COUNT', 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'FIFTH', 'RECENT', 'LAST', 'MIN', 'MAX', 'DATEDIFF', 'TIMEDIFF', 'MEDIAN', 'MEAN']
267
+ TYPES = ['COUNT', 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'FIFTH', 'RECENT', 'LAST', 'MIN', 'MAX', 'DATEDIFF', 'TIMEDIFF', 'DATETIMEDIFF', 'MEDIAN', 'MEAN', 'SUM']
268
268
 
269
269
  attr_accessor :type, :value
270
270
  # @param [String] type
@@ -22,7 +22,16 @@ require_relative 'hqmf-parser/1.0/expression'
22
22
 
23
23
  require_relative 'hqmf-parser/2.0/utilities'
24
24
  require_relative 'hqmf-parser/2.0/types'
25
+ require_relative 'hqmf-parser/2.0/document_helpers/doc_population_helper'
26
+ require_relative 'hqmf-parser/2.0/document_helpers/doc_utilities'
25
27
  require_relative 'hqmf-parser/2.0/document'
28
+ require_relative 'hqmf-parser/2.0/field_value_helper'
29
+ require_relative 'hqmf-parser/2.0/value_set_helper'
30
+ require_relative 'hqmf-parser/2.0/source_data_criteria_helper'
31
+ require_relative 'hqmf-parser/2.0/data_criteria_helpers/dc_definition_from_template_or_type_extract'
32
+ require_relative 'hqmf-parser/2.0/data_criteria_helpers/dc_specific_occurrences_and_source_data_criteria_extract'
33
+ require_relative 'hqmf-parser/2.0/data_criteria_helpers/dc_post_processing'
34
+ require_relative 'hqmf-parser/2.0/data_criteria_helpers/dc_base_extract'
26
35
  require_relative 'hqmf-parser/2.0/data_criteria'
27
36
  require_relative 'hqmf-parser/2.0/population_criteria'
28
37
  require_relative 'hqmf-parser/2.0/precondition'
@@ -43,7 +43,7 @@ module HQMF1
43
43
  bad_precondition = @preconditions.first
44
44
  if (bad_precondition.restrictions.empty? && bad_precondition.subset.nil? && bad_precondition.expression.nil?)
45
45
  @preconditions = @preconditions.first.preconditions
46
- puts "\t FIXED PRECONDITION WITHOUT CONJUNCTION"
46
+ #puts "\t FIXED PRECONDITION WITHOUT CONJUNCTION"
47
47
  else
48
48
  puts "\t PRECONDITION WITHOUT CONJUNCTION: Cannot be fixed"
49
49
  end
@@ -1,395 +1,369 @@
1
1
  module HQMF2
2
2
  # Represents a data criteria specification
3
3
  class DataCriteria
4
-
5
- include HQMF2::Utilities
6
-
4
+ include HQMF2::Utilities, HQMF2::DataCriteriaTypeAndDefinitionExtraction, HQMF2::DataCriteriaPostProcessing
5
+
6
+ attr_accessor :id
7
+ attr_accessor :original_id
7
8
  attr_reader :property, :type, :status, :value, :effective_time, :section
8
- attr_reader :temporal_references, :subset_operators, :children_criteria
9
+ attr_reader :temporal_references, :subset_operators, :children_criteria
9
10
  attr_reader :derivation_operator, :negation, :negation_code_list_id, :description
10
11
  attr_reader :field_values, :source_data_criteria, :specific_occurrence_const
11
- attr_reader :specific_occurrence, :is_source_data_criteria, :comments
12
-
13
- VARIABLE_TEMPLATE = "0.1.2.3.4.5.6.7.8.9.1"
14
- SATISFIES_ANY_TEMPLATE = "0.1.2.3.4.5.6.7.8.9.2"
15
- SATISFIES_ALL_TEMPLATE = "0.1.2.3.4.5.6.7.8.9.3"
12
+ attr_reader :specific_occurrence, :comments, :is_derived_specific_occurrence_variable
13
+ attr_reader :entry, :definition, :variable, :local_variable_name
16
14
 
17
- CONJUNCTION_CODE_TO_DERIVATION_OP = {
18
- 'OR' => 'UNION',
19
- 'AND' => 'XPRODUCT'
20
- }
21
-
22
15
  CRITERIA_GLOB = "*[substring(name(),string-length(name())-7) = \'Criteria\']"
23
16
 
24
17
  # Create a new instance based on the supplied HQMF entry
25
18
  # @param [Nokogiri::XML::Element] entry the parsed HQMF entry
26
- def initialize(entry)
19
+ def initialize(entry, data_criteria_references = {}, occurrences_map = {})
27
20
  @entry = entry
28
- @local_variable_name = extract_local_variable_name
29
- @status = attr_val('./*/cda:statusCode/@code')
30
- @description = attr_val("./#{CRITERIA_GLOB}/cda:text/@value")
31
- extract_negation()
32
- extract_specific_or_source()
33
- @effective_time = extract_effective_time
34
- @temporal_references = extract_temporal_references
35
- @derivation_operator = extract_derivation_operator
36
- @field_values = extract_field_values
37
- @subset_operators = extract_subset_operators
38
- @children_criteria = extract_child_criteria
39
- @id_xpath = './*/cda:id/@extension'
40
- @code_list_xpath = './*/cda:code'
41
- @value_xpath = './*/cda:value'
42
- @comments = @entry.xpath("./#{CRITERIA_GLOB}/cda:text/cda:xml/cda:qdmUserComments/cda:item/text()", HQMF2::Document::NAMESPACES).map{ |v| v.content }
43
- @variable = false
44
-
45
- # Try to determine what kind of data criteria we are dealing with
46
- # First we look for a template id and if we find one just use the definition
47
- # status and negation associated with that
48
- if !extract_type_from_template_id()
49
- # If no template id or not one we recognize then try to determine type from
50
- # the definition element
51
- extract_type_from_definition()
52
- end
53
-
54
- patch_xpaths_for_criteria_type()
21
+ @data_criteria_references = data_criteria_references
22
+ @occurrences_map = occurrences_map
23
+ basic_setup
24
+ @variable = DataCriteriaMethods.extract_variable(@local_variable_name, @id)
25
+ @field_values = DataCriteriaMethods.extract_field_values(@entry, @negation)
26
+ @description = extract_description
27
+ obtain_specific_and_source = SpecificOccurrenceAndSource.new(@entry, @id, @local_variable_name,
28
+ @data_criteria_references, @occurrences_map)
29
+ # Pulling these 5 variables out via destructing
30
+ @source_data_criteria,
31
+ @source_data_criteria_root,
32
+ @source_data_criteria_extension,
33
+ @specific_occurrence,
34
+ @specific_occurrence_const = obtain_specific_and_source.extract_specific_occurrences_and_source_data_criteria
35
+ extract_definition_from_template_or_type
36
+ post_processing
55
37
  end
56
38
 
57
- def patch_xpaths_for_criteria_type
58
- # Patch xpaths when necessary, HQMF data criteria are irregular in structure so
59
- # the same information is found in different places depending on the type of
60
- # criteria
61
- # Assumes @definition and @status are already set
62
- case @definition
63
- when 'transfer_to', 'transfer_from'
64
- @code_list_xpath = './cda:observationCriteria/cda:value'
65
- when 'diagnosis', 'diagnosis_family_history'
66
- @code_list_xpath = './cda:observationCriteria/cda:value'
67
- when 'physical_exam', 'risk_category_assessment', 'procedure_result', 'laboratory_test', 'diagnostic_study_result', 'functional_status_result', 'intervention_result'
68
- @value = extract_value
69
- when 'medication'
70
- case @status
71
- when 'dispensed', 'ordered'
72
- @code_list_xpath = './cda:supplyCriteria/cda:participation/cda:role/cda:code'
73
- else # active or administered
74
- @code_list_xpath = './cda:substanceAdministrationCriteria/cda:participation/cda:role/cda:code'
75
- end
76
- when 'patient_characteristic', 'patient_characteristic_birthdate', 'patient_characteristic_clinical_trial_participant', 'patient_characteristic_expired', 'patient_characteristic_gender', 'patient_characteristic_age', 'patient_characteristic_languages', 'patient_characteristic_marital_status', 'patient_characteristic_race'
77
- @value = extract_value
78
- when 'variable'
79
- @value = extract_value
80
- end
81
- end
82
-
83
- def extract_local_variable_name
84
- lvn = @entry.at_xpath("./cda:localVariableName")
85
- lvn["value"] if lvn
86
- end
87
-
88
- def extract_type_from_definition
89
- if @entry.at_xpath("./cda:grouperCriteria")
90
- if @local_variable_name && @local_variable_name.match(/qdm_/)
91
- @variable = true
92
- end
93
- @definition = 'derived'
94
- return
95
- end
96
- # See if we can find a match for the entry definition value and status.
97
- entry_type = attr_val('./*/cda:definition/*/cda:id/@extension')
98
- begin
99
- settings = HQMF::DataCriteria.get_settings_for_definition(entry_type, @status)
100
- @definition = entry_type
101
- rescue
102
- # if no exact match then try a string match just using entry definition value
103
- case entry_type
104
- when 'Problem', 'Problems'
105
- @definition = 'diagnosis'
106
- when 'Encounter', 'Encounters'
107
- @definition = 'encounter'
108
- when 'LabResults', 'Results'
109
- @definition = 'laboratory_test'
110
- when 'Procedure', 'Procedures'
111
- @definition = 'procedure'
112
- when 'Medication', 'Medications'
113
- @definition = 'medication'
114
- if !@status
115
- @status = 'active'
116
- end
117
- when 'RX'
118
- @definition = 'medication'
119
- if !@status
120
- @status = 'dispensed'
121
- end
122
- when 'Demographics'
123
- @definition = definition_for_demographic
124
- when 'Derived'
125
- @definition = 'derived'
126
- when nil
127
- @definition = 'variable'
128
- else
129
- raise "Unknown data criteria template identifier [#{entry_type}]"
130
- end
131
- end
132
- end
133
-
134
- def extract_type_from_template_id
135
- template_ids = @entry.xpath('./*/cda:templateId/cda:item', HQMF2::Document::NAMESPACES).collect do |template_def|
136
- HQMF2::Utilities.attr_val(template_def, '@root')
137
- end
138
- if template_ids.include?(HQMF::DataCriteria::SOURCE_DATA_CRITERIA_TEMPLATE_ID)
139
- @is_source_data_criteria = true
140
- end
141
- found = false
142
- template_ids.each do |template_id|
143
- defs = HQMF::DataCriteria.definition_for_template_id(template_id)
144
-
145
- if defs
146
- @definition = defs['definition']
147
- @status = defs['status'].length > 0 ? defs['status'] : nil
148
- @negation = defs['negation']
149
- found ||= true
150
- elsif template_id == VARIABLE_TEMPLATE
151
- @derivation_operator = HQMF::DataCriteria::INTERSECT if @derivation_operator == HQMF::DataCriteria::XPRODUCT
152
- @definition ||= 'derived'
153
- @negation = false
154
- @variable = true
155
- found ||= true
156
- elsif template_id == SATISFIES_ANY_TEMPLATE
157
- @definition = HQMF::DataCriteria::SATISFIES_ANY
158
- @negation = false
159
- return true
160
- elsif template_id == SATISFIES_ALL_TEMPLATE
161
- @definition = HQMF::DataCriteria::SATISFIES_ALL
162
- @derivation_operator = HQMF::DataCriteria::INTERSECT
163
- @negation = false
164
- found ||= true
165
- end
166
- end
167
- found
168
- end
169
-
170
39
  def to_s
171
40
  props = {
172
- :property => property,
173
- :type => type,
174
- :status => status,
175
- :section => section
41
+ property: property,
42
+ type: type,
43
+ status: status,
44
+ section: section
176
45
  }
177
- "DataCriteria#{props.to_s}"
46
+ "DataCriteria#{props}"
178
47
  end
179
-
48
+
49
+ # TODO: Remove id method if id attribute is sufficient
180
50
  # Get the identifier of the criteria, used elsewhere within the document for referencing
181
51
  # @return [String] the identifier of this data criteria
182
- def id
183
- attr_val(@id_xpath)
184
- end
185
-
52
+ # def id
53
+ # attr_val(@id_xpath)
54
+ # end
55
+
186
56
  # Get the title of the criteria, provides a human readable description
187
57
  # @return [String] the title of this data criteria
188
58
  def title
189
- dispValue = attr_val("#{@code_list_xpath}/cda:displayName/@value")
190
- desc = nil
191
- if @description && (@description.include? ":")
192
- desc = @description.match(/.*:\s+(.+)/)[1]
193
- end
194
- dispValue || desc || id
59
+ disp_value = attr_val("#{@code_list_xpath}/cda:displayName/@value")
60
+ @title || disp_value || @description || id # allow defined titles to take precedence
195
61
  end
196
-
62
+
197
63
  # Get the code list OID of the criteria, used as an index to the code list database
198
64
  # @return [String] the code list identifier of this data criteria
199
65
  def code_list_id
200
- attr_val("#{@code_list_xpath}/@valueSet")
66
+ @code_list_id || attr_val("#{@code_list_xpath}/@valueSet")
67
+ end
68
+
69
+ # Generates this classes hqmf-model equivalent
70
+ def to_model
71
+ mv = value.try(:to_model)
72
+ met = effective_time.try(:to_model)
73
+ mtr = temporal_references.collect(&:to_model)
74
+ mso = subset_operators.collect(&:to_model)
75
+ field_values = retrieve_field_values_model_for_model
76
+
77
+ retrieve_title_and_description_for_model unless @variable || @derivation_operator
78
+
79
+ @code_list_id = nil if @derivation_operator
80
+
81
+ # prevent json model generation of empty children and comments
82
+ cc = children_criteria.present? ? children_criteria : nil
83
+ comments = @comments.present? ? @comments : nil
84
+
85
+ HQMF::DataCriteria.new(id, title, nil, description, @code_list_id, cc, derivation_operator, @definition, status,
86
+ mv, field_values, met, retrieve_code_system_for_model, @negation, @negation_code_list_id,
87
+ mtr, mso, @specific_occurrence, @specific_occurrence_const, @source_data_criteria,
88
+ comments, @variable)
89
+ end
90
+
91
+ # Return a new DataCriteria instance with only grouper attributes set.
92
+ # A grouper criteria allows multiple data criteria events to be contained in a single
93
+ # logical set (a union or intersection of these multiple events - i.e. A during (B or C or D)).
94
+ # Grouper criteria also provide a way to combine multiple criteria that reference a specific
95
+ # occurrence of an event.
96
+ def extract_variable_grouper
97
+ return unless @variable
98
+ @variable = false
99
+ @id = "GROUP_#{@id}"
100
+ if @children_criteria.length == 1 && @children_criteria[0] =~ /GROUP_/
101
+ reference_criteria = @data_criteria_references[@children_criteria.first]
102
+ return if reference_criteria.nil?
103
+ duplicate_child_info(reference_criteria)
104
+ @definition = reference_criteria.definition
105
+ @status = reference_criteria.status
106
+ @children_criteria = []
107
+ end
108
+ @specific_occurrence = nil
109
+ @specific_occurrence_const = nil
110
+ # set the source data criteria id to the id for variables
111
+ @source_data_criteria = @id
112
+ DataCriteria.new(@entry, @data_criteria_references, @occurrences_map).extract_as_grouper
113
+ end
114
+
115
+ # Extract this data criteria as a grouper data criteria
116
+ # SHOULD only be called on a variable data criteria instance
117
+ def extract_as_grouper
118
+ @field_values = {}
119
+ @temporal_references = []
120
+ @subset_operators = []
121
+ @derivation_operator = HQMF::DataCriteria::UNION
122
+ @definition = 'derived'
123
+ @status = nil
124
+ @children_criteria = ["GROUP_#{@id}"]
125
+ @source_data_criteria = @id
126
+ self
127
+ end
128
+
129
+ # Handle elements that are marked as variable groupers that should not be turned into a "holding element"
130
+ # (defined as a data criteria that encapsulates the calculation material for other data criteria elements,
131
+ # where the other data criteria elements reference the holding element as a child element)
132
+ def handle_derived_specific_occurrence_variable
133
+ # If the first child is all the exists, and it has been marked as a "group" element, switch this over to map to
134
+ # the new element.
135
+ if !@data_criteria_references["GROUP_#{@children_criteria.first}"].nil? && @children_criteria.length == 1
136
+ @children_criteria[0] = "GROUP_#{@children_criteria.first}"
137
+ # If the group element is not found, extract the information from the child and force it into the variable.
138
+ elsif @children_criteria.length == 1 && @children_criteria.first.present?
139
+ reference_criteria = @data_criteria_references[@children_criteria.first]
140
+ return if reference_criteria.nil?
141
+ duplicate_child_info(reference_criteria)
142
+ @children_criteria = reference_criteria.children_criteria
143
+ end
201
144
  end
202
-
203
- def inline_code_list
204
- codeSystem = attr_val("#{@code_list_xpath}/@codeSystem")
205
- if codeSystem
206
- codeSystemName = HealthDataStandards::Util::CodeSystemHelper.code_system_for(codeSystem)
145
+
146
+ # clone method. This is needed because we need to extract a new source data criteria for variables
147
+ # typically "cloning" is done by re-parsing the xml entry, however with post processing that does
148
+ # not give us the correct SDC data when we are trying to recreate since we are looping back through
149
+ # the same data criteria before it has finished processing: See: DocUtilities.extract_source_data_criteria
150
+ def clone
151
+ other = DataCriteria.new(@entry, @data_criteria_references, @occurrences_map)
152
+ other.instance_variable_set(:@id, @id)
153
+ other.instance_variable_set(:@original_id, @original_id)
154
+ other.instance_variable_set(:@property, @property)
155
+ other.instance_variable_set(:@type, @type)
156
+ other.instance_variable_set(:@status, @status)
157
+ other.instance_variable_set(:@code_list_id, @code_list_id)
158
+ other.instance_variable_set(:@value, @value)
159
+ other.instance_variable_set(:@effective_time, @effective_time)
160
+ other.instance_variable_set(:@section, @section)
161
+ other.instance_variable_set(:@temporal_references, @temporal_references)
162
+ other.instance_variable_set(:@subset_operators, @subset_operators)
163
+ other.instance_variable_set(:@children_criteria, @children_criteria)
164
+ other.instance_variable_set(:@derivation_operator, @derivation_operator)
165
+ other.instance_variable_set(:@negation, @negation)
166
+ other.instance_variable_set(:@negation_code_list_id, @negation_code_list_id)
167
+ other.instance_variable_set(:@description, @description)
168
+ other.instance_variable_set(:@field_values, @field_values)
169
+ other.instance_variable_set(:@source_data_criteria, @source_data_criteria)
170
+ other.instance_variable_set(:@specific_occurrence_const, @specific_occurrence_const)
171
+ other.instance_variable_set(:@specific_occurrence, @specific_occurrence)
172
+ other.instance_variable_set(:@comments, @comments)
173
+ other.instance_variable_set(:@is_derived_specific_occurrence_variable, @is_derived_specific_occurrence_variable)
174
+ other.instance_variable_set(:@entry, @entry)
175
+ other.instance_variable_set(:@definition, @definition)
176
+ other.instance_variable_set(:@variable, @variable)
177
+ other.instance_variable_set(:@local_variable_name, @local_variable_name)
178
+ other
179
+ end
180
+
181
+ private
182
+
183
+ # Handles elments that can be extracted directly from the xml. Utilises the "BaseExtractions" class.
184
+ def basic_setup
185
+ @status = attr_val('./*/cda:statusCode/@code')
186
+ @id_xpath = './*/cda:id/@extension'
187
+ @id = "#{attr_val('./*/cda:id/@extension')}_#{attr_val('./*/cda:id/@root')}"
188
+ @comments = @entry.xpath("./#{CRITERIA_GLOB}/cda:text/cda:xml/cda:qdmUserComments/cda:item/text()",
189
+ HQMF2::Document::NAMESPACES).map(&:content)
190
+ @code_list_xpath = './*/cda:code'
191
+ @value_xpath = './*/cda:value'
192
+ @is_derived_specific_occurrence_variable = false
193
+ simple_extractions = DataCriteriaBaseExtractions.new(@entry)
194
+ @template_ids = simple_extractions.extract_template_ids
195
+ @local_variable_name = simple_extractions.extract_local_variable_name
196
+ @temporal_references = simple_extractions.extract_temporal_references
197
+ @derivation_operator = simple_extractions.extract_derivation_operator
198
+ @children_criteria = simple_extractions.extract_child_criteria
199
+ @subset_operators = simple_extractions.extract_subset_operators
200
+ @negation, @negation_code_list_id = simple_extractions.extract_negation
201
+ end
202
+
203
+ # Extract the description (with some special handling if this is a variable). The MAT has added an encoded
204
+ # form of the variable name in the localVariableName field which is used if available. If not, fall back
205
+ # to the extension.
206
+ def extract_description
207
+ if @variable
208
+ encoded_name = attr_val('./cda:localVariableName/@value')
209
+ encoded_name = DataCriteriaMethods.extract_description_for_variable(encoded_name) if encoded_name
210
+ return encoded_name if encoded_name.present?
211
+ attr_val("./#{CRITERIA_GLOB}/cda:id/@extension")
207
212
  else
208
- codeSystemName = attr_val("#{@code_list_xpath}/@codeSystemName")
213
+ attr_val("./#{CRITERIA_GLOB}/cda:text/@value") ||
214
+ attr_val("./#{CRITERIA_GLOB}/cda:title/@value") ||
215
+ attr_val("./#{CRITERIA_GLOB}/cda:id/@extension")
209
216
  end
210
- codeValue = attr_val("#{@code_list_xpath}/@code")
211
- if codeSystemName && codeValue
212
- {codeSystemName => [codeValue]}
217
+ end
218
+
219
+ # Extract the code system from the xml taht the document should use
220
+ def retrieve_code_system_for_model
221
+ code_system = attr_val("#{@code_list_xpath}/@codeSystem")
222
+ if code_system
223
+ code_system_name = HealthDataStandards::Util::CodeSystemHelper.code_system_for(code_system)
213
224
  else
214
- nil
225
+ code_system_name = attr_val("#{@code_list_xpath}/@codeSystemName")
215
226
  end
227
+ code_value = attr_val("#{@code_list_xpath}/@code")
228
+ { code_system_name => [code_value] } if code_system_name && code_value
229
+ end
230
+
231
+ # Duplicates information from a child element to this data criteria if none exits.
232
+ # If the duplication requires that come values should be overwritten, do so only in the function calling this.
233
+ def duplicate_child_info(child_ref)
234
+ @title ||= child_ref.title
235
+ @type ||= child_ref.subset_operators
236
+ @definition ||= child_ref.definition
237
+ @status ||= child_ref.status
238
+ @code_list_id ||= child_ref.code_list_id
239
+ @temporal_references = child_ref.temporal_references if @temporal_references.empty?
240
+ @subset_operators ||= child_ref.subset_operators
241
+ @variable ||= child_ref.variable
242
+ @value ||= child_ref.value
216
243
  end
217
-
218
- def to_model
219
244
 
220
- mv = value ? value.to_model : nil
221
- met = effective_time ? effective_time.to_model : nil
222
- mtr = temporal_references.collect {|ref| ref.to_model}
223
- mso = subset_operators.collect {|opr| opr.to_model}
245
+ # Generate the models of the field values
246
+ def retrieve_field_values_model_for_model
224
247
  field_values = {}
225
248
  @field_values.each_pair do |id, val|
226
249
  field_values[id] = val.to_model
227
250
  end
251
+ @code_list_id ||= code_list_id
228
252
 
229
253
  # Model transfers as a field
230
- if ['transfer_to', 'transfer_from'].include? @definition
231
- field_values ||= {}
254
+ if %w(transfer_to transfer_from).include? @definition
232
255
  field_code_list_id = @code_list_id
233
- if !field_code_list_id
256
+ @code_list_id = nil
257
+ unless field_code_list_id
234
258
  field_code_list_id = attr_val("./#{CRITERIA_GLOB}/cda:outboundRelationship/#{CRITERIA_GLOB}/cda:value/@valueSet")
235
259
  end
236
260
  field_values[@definition.upcase] = HQMF::Coded.for_code_list(field_code_list_id, title)
237
261
  end
238
262
 
239
- field_values = nil if field_values.empty?
240
-
241
- HQMF::DataCriteria.new(id, title, nil, description, code_list_id, children_criteria,
242
- derivation_operator, @definition, status, mv, field_values, met, inline_code_list,
243
- @negation, @negation_code_list_id, mtr, mso, @specific_occurrence,
244
- @specific_occurrence_const, @source_data_criteria, @comments, @variable)
245
- end
246
-
247
- private
248
-
249
- def extract_negation
250
- negation = attr_val('./*/@actionNegationInd')
251
- @negation = (negation=='true')
252
- if @negation
253
- @negation_code_list_id = attr_val('./*/cda:reasonCode/cda:item/@valueSet')
254
- else
255
- @negation_code_list_id = nil
256
- end
257
- end
258
-
259
- def extract_child_criteria
260
- @entry.xpath("./*/cda:outboundRelationship[@typeCode='COMP']/cda:criteriaReference/cda:id", HQMF2::Document::NAMESPACES).collect do |ref|
261
- Reference.new(ref).id
262
- end.compact
263
- end
264
-
265
- def extract_effective_time
266
- effective_time_def = @entry.at_xpath('./*/cda:effectiveTime', HQMF2::Document::NAMESPACES)
267
- if effective_time_def
268
- EffectiveTime.new(effective_time_def)
269
- else
270
- nil
271
- end
272
- end
273
-
274
- def all_subset_operators
275
- @entry.xpath('./*/cda:excerpt', HQMF2::Document::NAMESPACES).collect do |subset_operator|
276
- SubsetOperator.new(subset_operator)
277
- end
278
- end
279
-
280
- def extract_derivation_operator
281
- codes = @entry.xpath("./*/cda:outboundRelationship[@typeCode='COMP']/cda:conjunctionCode/@code", HQMF2::Document::NAMESPACES)
282
- codes.inject(nil) do | d_op, code |
283
- raise "More than one derivation operator in data criteria" if d_op && d_op != CONJUNCTION_CODE_TO_DERIVATION_OP[code.value]
284
- CONJUNCTION_CODE_TO_DERIVATION_OP[code.value]
285
- end
263
+ return field_values unless field_values.empty?
286
264
  end
287
-
288
- def extract_subset_operators
289
- all_subset_operators.select do |operator|
290
- operator.type != 'UNION' && operator.type != 'XPRODUCT'
291
- end
292
- end
293
-
294
- def extract_specific_or_source
295
- specific_def = @entry.at_xpath('./*/cda:outboundRelationship[@typeCode="OCCR"]', HQMF2::Document::NAMESPACES)
296
- source_def = @entry.at_xpath('./*/cda:outboundRelationship[cda:subsetCode/@code="SOURCE"]', HQMF2::Document::NAMESPACES)
297
- if specific_def
298
- @source_data_criteria = HQMF2::Utilities.attr_val(specific_def, './cda:criteriaReference/cda:id/@extension')
299
- @specific_occurrence_const = HQMF2::Utilities.attr_val(specific_def, './cda:localVariableName/@controlInformationRoot')
300
- @specific_occurrence = HQMF2::Utilities.attr_val(specific_def, './cda:localVariableName/@controlInformationExtension')
301
- if !@specific_occurrence
302
- @specific_occurrence = "A"
303
- @specific_occurrence_const = @source_data_criteria.upcase
304
- end
305
- elsif source_def
306
- @source_data_criteria = HQMF2::Utilities.attr_val(source_def, './cda:criteriaReference/cda:id/@extension')
307
- end
265
+
266
+ # Generate the title and description used when producing the model
267
+ def retrieve_title_and_description_for_model
268
+ # drop "* Value Set" from titles
269
+ exact_desc = title.split(' ')[0...-3].join(' ')
270
+ # don't drop anything for patient characterstic titles
271
+ exact_desc = title if @definition.start_with?('patient_characteristic') && !title.end_with?('Value Set')
272
+
273
+ # remove * Value Set from title
274
+ title_match = title.match(/(.*) \w+ [Vv]alue [Ss]et/)
275
+ @title = title_match[1] if title_match && title_match.length > 1
276
+
277
+ @description = "#{@description}: #{exact_desc}"
308
278
  end
309
-
310
- def extract_field_values
279
+ end
280
+
281
+ # Holds methods not tied to the data criteria's instance variables
282
+ class DataCriteriaMethods
283
+ # Given an entry, and whether or not it's negated, extract out the proper field values for the data criteria.
284
+ def self.extract_field_values(entry, negation)
311
285
  fields = {}
312
286
  # extract most fields which use the same structure
313
- @entry.xpath('./*/cda:outboundRelationship[*/cda:code]', HQMF2::Document::NAMESPACES).each do |field|
287
+ entry.xpath('./*/cda:outboundRelationship[*/cda:code]', HQMF2::Document::NAMESPACES).each do |field|
314
288
  code = HQMF2::Utilities.attr_val(field, './*/cda:code/@code')
315
289
  code_id = HQMF::DataCriteria::VALUE_FIELDS[code]
316
- value = DataCriteria.parse_value(field, './*/cda:value')
317
- fields[code_id] = value if value && code_id
290
+ # No need to run if there is no code id
291
+ next if (negation && code_id == 'REASON') || code_id.nil?
292
+ value = DataCriteriaMethods.parse_value(field, './*/cda:value')
293
+ value ||= DataCriteriaMethods.parse_value(field, './*/cda:effectiveTime')
294
+ fields[code_id] = value
318
295
  end
319
296
  # special case for facility location which uses a very different structure
320
- @entry.xpath('./*/cda:outboundRelationship[*/cda:participation]', HQMF2::Document::NAMESPACES).each do |field|
297
+ entry.xpath('./*/cda:outboundRelationship[*/cda:participation]', HQMF2::Document::NAMESPACES).each do |field|
321
298
  code = HQMF2::Utilities.attr_val(field, './*/cda:participation/cda:role/@classCode')
322
299
  code_id = HQMF::DataCriteria::VALUE_FIELDS[code]
300
+ next if code_id.nil?
323
301
  value = Coded.new(field.at_xpath('./*/cda:participation/cda:role/cda:code', HQMF2::Document::NAMESPACES))
324
- fields[code_id] = value if value && code_id
302
+ fields[code_id] = value
325
303
  end
326
304
 
305
+ fields.merge! HQMF2::FieldValueHelper.parse_field_values(entry)
327
306
  # special case for fulfills operator. assuming there is only a possibility of having one of these
328
- fulfils = @entry.at_xpath('./*/cda:outboundRelationship[@typeCode="FLFS"]/cda:criteriaReference', HQMF2::Document::NAMESPACES)
329
- if fulfils
330
- # grab the child element if we don't have a reference
331
- fields["FLFS"] = TypedReference.new(fulfils)
332
- end
307
+ fulfills = entry.at_xpath('./*/cda:outboundRelationship[@typeCode="FLFS"]/cda:criteriaReference',
308
+ HQMF2::Document::NAMESPACES)
309
+ # grab the child element if we don't have a reference
310
+ fields['FLFS'] = TypedReference.new(fulfills) if fulfills
333
311
  fields
334
312
  end
335
-
336
- def extract_temporal_references
337
- @entry.xpath('./*/cda:temporallyRelatedInformation', HQMF2::Document::NAMESPACES).collect do |temporal_reference|
338
- TemporalReference.new(temporal_reference)
313
+
314
+ # Use the new MAT feature to extract the human generated (or computer generated) variable names from the xml.
315
+ def self.extract_description_for_variable(encoded_name)
316
+ if encoded_name.match(/^qdm_var_/)
317
+ # Strip out initial qdm_var_ string, trailing _*, and possible occurrence reference
318
+ encoded_name.gsub!(/^qdm_var_|/, '')
319
+ encoded_name.gsub!(/Occurrence[A-Z]of/, '')
320
+ # This code needs to handle measures created before the MAT added variable name hints; for those, don't strip
321
+ # the final identifier
322
+ unless encoded_name.match(/^(SATISFIES ALL|SATISFIES ANY|UNION|INTERSECTION)/)
323
+ encoded_name.gsub!(/_[^_]+$/, '')
324
+ end
325
+ encoded_name
326
+ elsif encoded_name.match(/^localVar_/)
327
+ encoded_name.gsub!(/^localVar_/, '')
328
+ encoded_name
339
329
  end
340
330
  end
341
-
342
- def extract_value()
343
- DataCriteria.parse_value(@entry, @value_xpath)
344
- end
345
-
331
+
332
+ # Parses the value for a given xpath
346
333
  def self.parse_value(node, xpath)
347
- value = nil
348
334
  value_def = node.at_xpath(xpath, HQMF2::Document::NAMESPACES)
349
335
  if value_def
336
+ return AnyValue.new if value_def.at_xpath('@flavorId') == 'ANY.NONNULL'
350
337
  value_type_def = value_def.at_xpath('@xsi:type', HQMF2::Document::NAMESPACES)
351
- if value_type_def
352
- value_type = value_type_def.value
353
- case value_type
354
- when 'PQ'
355
- value = Value.new(value_def, 'PQ', true)
356
- when 'TS'
357
- value = Value.new(value_def)
358
- when 'IVL_PQ', 'IVL_INT'
359
- value = Range.new(value_def)
360
- when 'CD'
361
- value = Coded.new(value_def)
362
- when 'ANY'
363
- value = AnyValue.new()
364
- else
365
- raise "Unknown value type [#{value_type}]"
366
- end
367
- end
338
+ return handle_value_type(value_type_def, value_def) if value_type_def
368
339
  end
369
- value
370
340
  end
371
-
372
- def definition_for_demographic
373
- demographic_type = attr_val('./cda:observationCriteria/cda:code/@code')
374
- case demographic_type
375
- when '21112-8'
376
- "patient_characteristic_birthdate"
377
- when '424144002'
378
- "patient_characteristic_age"
379
- when '263495000'
380
- "patient_characteristic_gender"
381
- when '102902016'
382
- "patient_characteristic_languages"
383
- when '125680007'
384
- "patient_characteristic_marital_status"
385
- when '103579009'
386
- "patient_characteristic_race"
341
+
342
+ # Derives the type associated with a specific value
343
+ def self.handle_value_type(value_type_def, value_def)
344
+ value_type = value_type_def.value
345
+ case value_type
346
+ when 'PQ'
347
+ Value.new(value_def, 'PQ', true)
348
+ when 'TS'
349
+ Value.new(value_def)
350
+ when 'IVL_PQ', 'IVL_INT'
351
+ Range.new(value_def)
352
+ when 'CD'
353
+ Coded.new(value_def)
354
+ when 'ANY', 'IVL_TS'
355
+ # FIXME: (10/26/2015) IVL_TS should be able to handle other values, not just AnyValue
356
+ AnyValue.new
387
357
  else
388
- raise "Unknown demographic identifier [#{demographic_type}]"
358
+ fail "Unknown value type [#{value_type}]"
389
359
  end
390
-
391
360
  end
392
361
 
362
+ # Determine if this instance is a qdm variable
363
+ def self.extract_variable(local_variable_name, id)
364
+ variable = (local_variable_name =~ /.*qdm_var_/).present? unless local_variable_name.blank?
365
+ variable ||= (id =~ /.*qdm_var_/).present? unless id.blank?
366
+ variable
367
+ end
393
368
  end
394
-
395
369
  end