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.
- checksums.yaml +4 -4
- data/Gemfile +7 -2
- data/Rakefile +2 -1
- data/lib/health-data-standards.rb +22 -1
- data/lib/health-data-standards/export/cat_1.rb +25 -6
- data/lib/health-data-standards/export/cat_1_r2.rb +8 -2
- data/lib/health-data-standards/export/cat_3.rb +8 -7
- data/lib/health-data-standards/export/exceptions.rb +13 -0
- data/lib/health-data-standards/export/helper/cat1_view_helper.rb +17 -11
- data/lib/health-data-standards/export/helper/html_view_helper.rb +13 -7
- data/lib/health-data-standards/export/helper/scooped_view_helper.rb +68 -25
- data/lib/health-data-standards/export/html.rb +9 -4
- data/lib/health-data-standards/export/qrda/entry_template_resolver.rb +29 -11
- data/lib/health-data-standards/export/qrda/hqmf-qrda-oids.json +89 -5
- data/lib/health-data-standards/export/rendering_context.rb +2 -2
- data/lib/health-data-standards/export/template_helper.rb +7 -2
- data/lib/health-data-standards/export/view_helper.rb +107 -39
- data/lib/health-data-standards/import/bulk_record_importer.rb +8 -5
- data/lib/health-data-standards/import/bundle/importer.rb +21 -14
- data/lib/health-data-standards/import/c32/care_goal_importer.rb +1 -1
- data/lib/health-data-standards/import/c32/immunization_importer.rb +1 -1
- data/lib/health-data-standards/import/cat1/clinical_trial_participant_importer.rb +20 -0
- data/lib/health-data-standards/import/cat1/device_order_importer.rb +20 -0
- data/lib/health-data-standards/import/cat1/diagnosis_active_importer.rb +4 -9
- data/lib/health-data-standards/import/cat1/diagnosis_importer.rb +15 -0
- data/lib/health-data-standards/import/cat1/diagnosis_inactive_importer.rb +1 -1
- data/lib/health-data-standards/import/cat1/diagnostic_study_order_importer.rb +6 -0
- data/lib/health-data-standards/import/cat1/encounter_order_act_importer.rb +19 -0
- data/lib/health-data-standards/import/cat1/encounter_performed_act_importer.rb +19 -0
- data/lib/health-data-standards/import/cat1/encounter_performed_importer.rb +16 -0
- data/lib/health-data-standards/import/cat1/immunization_administered_importer.rb +14 -0
- data/lib/health-data-standards/import/cat1/medication_dispensed_act_importer.rb +18 -0
- data/lib/health-data-standards/import/cat1/patient_importer.rb +44 -17
- data/lib/health-data-standards/import/cat1/procedure_order_importer.rb +4 -4
- data/lib/health-data-standards/import/cat1/procedure_performed_importer.rb +1 -0
- data/lib/health-data-standards/import/cat1/transfer_from_act_importer.rb +18 -0
- data/lib/health-data-standards/import/cat1/transfer_from_importer.rb +24 -0
- data/lib/health-data-standards/import/cat1/transfer_to_act_importer.rb +18 -0
- data/lib/health-data-standards/import/cat1/transfer_to_importer.rb +23 -0
- data/lib/health-data-standards/import/cda/allergy_importer.rb +1 -1
- data/lib/health-data-standards/import/cda/communication_importer.rb +55 -0
- data/lib/health-data-standards/import/cda/condition_importer.rb +17 -1
- data/lib/health-data-standards/import/cda/encounter_importer.rb +23 -21
- data/lib/health-data-standards/import/cda/medical_equipment_importer.rb +1 -0
- data/lib/health-data-standards/import/cda/medication_importer.rb +14 -4
- data/lib/health-data-standards/import/cda/procedure_importer.rb +4 -4
- data/lib/health-data-standards/import/cda/result_importer.rb +1 -1
- data/lib/health-data-standards/import/cda/section_importer.rb +59 -18
- data/lib/health-data-standards/models/assessment.rb +3 -0
- data/lib/health-data-standards/models/care_experience.rb +2 -0
- data/lib/health-data-standards/models/care_goal.rb +4 -0
- data/lib/health-data-standards/models/communication.rb +3 -0
- data/lib/health-data-standards/models/condition.rb +12 -9
- data/lib/health-data-standards/models/cqm/bundle.rb +2 -1
- data/lib/health-data-standards/models/cqm/measure.rb +2 -1
- data/lib/health-data-standards/models/cqm/patient_cache.rb +7 -3
- data/lib/health-data-standards/models/cqm/query_cache.rb +2 -0
- data/lib/health-data-standards/models/encounter.rb +14 -1
- data/lib/health-data-standards/models/encounter_principal_diagnosis.rb +36 -0
- data/lib/health-data-standards/models/entry.rb +5 -1
- data/lib/health-data-standards/models/family_history.rb +4 -0
- data/lib/health-data-standards/models/immunization.rb +1 -0
- data/lib/health-data-standards/models/lab_result.rb +10 -1
- data/lib/health-data-standards/models/medical_equipment.rb +2 -1
- data/lib/health-data-standards/models/medication.rb +19 -2
- data/lib/health-data-standards/models/patient_preference.rb +5 -0
- data/lib/health-data-standards/models/procedure.rb +16 -3
- data/lib/health-data-standards/models/provider.rb +17 -1
- data/lib/health-data-standards/models/provider_preference.rb +5 -0
- data/lib/health-data-standards/models/record.rb +8 -9
- data/lib/health-data-standards/models/reference.rb +1 -1
- data/lib/health-data-standards/models/svs/value_set.rb +28 -10
- data/lib/health-data-standards/models/transfer.rb +6 -1
- data/lib/health-data-standards/tasks/bundle.rake +5 -3
- data/lib/health-data-standards/util/hqmf_template_helper.rb +20 -14
- data/lib/health-data-standards/util/hqmfr2_template_oid_map.json +382 -0
- data/lib/health-data-standards/util/nlm_helper.rb +14 -0
- data/lib/health-data-standards/util/vs_api.rb +72 -54
- data/lib/health-data-standards/validate/measure_validator.rb +8 -3
- data/lib/health-data-standards/validate/performance_rate_validator.rb +1 -1
- data/lib/health-data-standards/validate/qrda_qdm_template_validator.rb +253 -0
- data/lib/health-data-standards/validate/reported_result_extractor.rb +5 -1
- data/lib/health-data-standards/validate/schematron_validator.rb +6 -0
- data/lib/health-data-standards/validate/validators.rb +49 -1
- data/lib/hqmf-generator/document.xml.erb +6 -5
- data/lib/hqmf-generator/field.xml.erb +1 -0
- data/lib/hqmf-generator/hqmf-generator.rb +85 -41
- data/lib/hqmf-generator/subset.xml.erb +15 -0
- data/lib/hqmf-generator/temporal_relationship.xml.erb +8 -3
- data/lib/hqmf-generator/temporal_relationship_attribute.xml.erb +10 -0
- data/lib/hqmf-generator/value.xml.erb +2 -2
- data/lib/hqmf-model/data_criteria.json +88 -17
- data/lib/hqmf-model/data_criteria.rb +144 -72
- data/lib/hqmf-model/population_criteria.rb +20 -18
- data/lib/hqmf-model/precondition.rb +6 -3
- data/lib/hqmf-model/types.rb +1 -1
- data/lib/hqmf-parser.rb +9 -0
- data/lib/hqmf-parser/1.0/utilities.rb +1 -1
- data/lib/hqmf-parser/2.0/data_criteria.rb +293 -319
- data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_base_extract.rb +80 -0
- data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_definition_from_template_or_type_extract.rb +201 -0
- data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_post_processing.rb +85 -0
- data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_specific_occurrences_and_source_data_criteria_extract.rb +117 -0
- data/lib/hqmf-parser/2.0/document.rb +246 -222
- data/lib/hqmf-parser/2.0/document_helpers/doc_population_helper.rb +175 -0
- data/lib/hqmf-parser/2.0/document_helpers/doc_utilities.rb +131 -0
- data/lib/hqmf-parser/2.0/field_value_helper.rb +251 -0
- data/lib/hqmf-parser/2.0/population_criteria.rb +101 -32
- data/lib/hqmf-parser/2.0/precondition.rb +61 -35
- data/lib/hqmf-parser/2.0/source_data_criteria_helper.rb +112 -0
- data/lib/hqmf-parser/2.0/types.rb +253 -73
- data/lib/hqmf-parser/2.0/utilities.rb +27 -12
- data/lib/hqmf-parser/2.0/value_set_helper.rb +101 -0
- data/lib/hqmf-parser/converter/pass1/data_criteria_converter.rb +6 -1
- data/lib/hqmf-parser/converter/pass1/population_criteria_converter.rb +34 -30
- data/lib/hqmf-parser/parser.rb +5 -5
- 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
- data/resources/schematron/qrda/cat_1_r3_1/HL7 QRDA Category I STU 3.1.sch +3573 -0
- data/resources/schematron/qrda/cat_1_r3_1/HL7 QRDA Category III STU 1.1.sch +464 -0
- data/resources/schematron/qrda/cat_1_r3_1/QRDA Category I STU Release 3.1.sch +5394 -0
- data/resources/schematron/qrda/cat_1_r3_1/voc.xml +1229 -0
- data/resources/schematron/qrda/cat_1_r4/HL7 QRDA Category I STU 4.sch +3526 -0
- data/resources/schematron/qrda/cat_1_r4/voc.xml +1186 -0
- data/resources/schematron/qrda/cat_3_r1_1/HL7 QRDA Category III STU 1.1.sch +528 -0
- data/resources/schematron/qrda/cat_3_r1_1/voc.xml +8 -0
- data/resources/schematron/qrda/cat_3_r2/HL7 QRDA Category III STU 2.sch +677 -0
- data/resources/schematron/qrda/cat_3_r2/voc.xml +1186 -0
- data/resources/schematron/qrda/cat_3_r2_1/HL7 QRDA Category III STU 2.1.sch +678 -0
- data/resources/schematron/qrda/cat_3_r2_1/voc.xml +1186 -0
- data/templates/c32/_medical_equipment.c32.erb +1 -1
- data/templates/c32/_vital_signs.c32.erb +1 -1
- 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
- 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
- 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
- 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
- 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
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.11.cat1.erb +88 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.12.cat1.erb +50 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.13.cat1.erb +54 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.135.cat1.erb +70 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.136.cat1.erb +52 -0
- 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
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.140.cat1.erb +39 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +23 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.18.cat1.erb +25 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.2.cat1.erb +29 -0
- 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
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.22.cat1.erb +22 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.23.cat1.erb +114 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.26.cat1.erb +20 -0
- 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
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.3.cat1.erb +25 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +23 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.32.cat1.erb +20 -0
- 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
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +22 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.38.cat1.erb +20 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.4.cat1.erb +29 -0
- 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
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.41.cat1.erb +46 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.42.cat1.erb +38 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.43.cat1.erb +24 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.44.cat1.erb +25 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.45.cat1.erb +26 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.46.cat1.erb +30 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +47 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.51.cat1.erb +14 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.54.cat1.erb +32 -0
- 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
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.57.cat1.erb +23 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.59.cat1.erb +22 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.62.cat1.erb +36 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.63.cat1.erb +21 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.64.cat1.erb +52 -0
- 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
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.69.cat1.erb +23 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.7.cat1.erb +33 -0
- 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
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.81.cat1.erb +23 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.82.cat1.erb +23 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.24.3.9.cat1.erb +64 -0
- data/templates/cat1/r2/_2.16.840.1.113883.10.20.28.3.6.cat1.erb +17 -0
- data/templates/cat1/{_address.cat1.erb → r2/_address.cat1.erb} +0 -0
- data/templates/cat1/{_author.cat1.erb → r2/_author.cat1.erb} +0 -0
- data/templates/cat1/r2/_fulfills.cat1.erb +14 -0
- data/templates/cat1/{_id.cat1.erb → r2/_id.cat1.erb} +0 -0
- data/templates/cat1/{_measures.cat1.erb → r2/_measures.cat1.erb} +1 -1
- data/templates/cat1/{_medication_details.cat1.erb → r2/_medication_details.cat1.erb} +3 -2
- data/templates/cat1/r2/_medication_dispense.cat1.erb +22 -0
- data/templates/cat1/{_ordinality.cat1.erb → r2/_ordinality.cat1.erb} +0 -0
- data/templates/cat1/{_organization.cat1.erb → r2/_organization.cat1.erb} +0 -0
- data/templates/cat1/{_patient_data.cat1.erb → r2/_patient_data.cat1.erb} +4 -1
- data/templates/cat1/r2/_patient_data_r3_1.cat1.erb +17 -0
- data/templates/cat1/r2/_providers.cat1.erb +76 -0
- data/templates/cat1/r2/_reason.cat1.erb +45 -0
- data/templates/cat1/{_record_target.cat1.erb → r2/_record_target.cat1.erb} +3 -0
- data/templates/cat1/r2/_reporting_parameters.cat1.erb +31 -0
- data/templates/cat1/{_result_value.cat1.erb → r2/_result_value.cat1.erb} +1 -1
- data/templates/cat1/{_telecom.cat1.erb → r2/_telecom.cat1.erb} +0 -0
- data/templates/cat1/{show.cat1.erb → r2/show.cat1.erb} +52 -5
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.1.cat1.erb +14 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.103.cat1.erb +17 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.105.cat1.erb +68 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.11.cat1.erb +58 -0
- 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
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.13.cat1.erb +39 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.14.cat1.erb +39 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +23 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.18.cat1.erb +25 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.2.cat1.erb +29 -0
- 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
- 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
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.26.cat1.erb +20 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.3.cat1.erb +25 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +23 -0
- 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
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +22 -0
- 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
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.4.cat1.erb +29 -0
- 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
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.42.cat1.erb +38 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.43.cat1.erb +24 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.44.cat1.erb +25 -0
- 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
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.46.cat1.erb +30 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +47 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.51.cat1.erb +14 -0
- 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
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.55.cat1.erb +18 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.57.cat1.erb +23 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.59.cat1.erb +22 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.62.cat1.erb +36 -0
- 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
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.64.cat1.erb +51 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.69.cat1.erb +23 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.7.cat1.erb +33 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.76.cat1.erb +19 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.81.cat1.erb +24 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.82.cat1.erb +24 -0
- data/templates/cat1/r3/_2.16.840.1.113883.10.20.24.3.9.cat1.erb +57 -0
- data/templates/cat1/r3/_address.cat1.erb +9 -0
- data/templates/{cat3/_author.cat3.erb → cat1/r3/_author.cat1.erb} +0 -0
- data/templates/cat1/{_fulfills.cat1.erb → r3/_fulfills.cat1.erb} +0 -0
- data/templates/{cat3/_id.cat3.erb → cat1/r3/_id.cat1.erb} +0 -0
- data/templates/cat1/r3/_measures.cat1.erb +93 -0
- data/templates/cat1/r3/_medication_details.cat1.erb +16 -0
- data/templates/cat1/{_medication_dispense.cat1.erb → r3/_medication_dispense.cat1.erb} +3 -3
- data/templates/cat1/r3/_ordinality.cat1.erb +10 -0
- data/templates/cat1/r3/_organization.cat1.erb +9 -0
- data/templates/cat1/r3/_patient_data.cat1.erb +17 -0
- data/templates/cat1/r3/_providers.cat1.erb +76 -0
- data/templates/cat1/r3/_reason.cat1.erb +34 -0
- data/templates/cat1/r3/_record_target.cat1.erb +56 -0
- data/templates/cat1/r3/_reporting_parameters.cat1.erb +31 -0
- data/templates/cat1/r3/_result_value.cat1.erb +28 -0
- data/templates/{cat3/_telecom.cat3.erb → cat1/r3/_telecom.cat1.erb} +0 -0
- data/templates/cat1/r3/show.cat1.erb +183 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.1.cat1.erb +14 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.103.cat1.erb +17 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.105.cat1.erb +68 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.12.cat1.erb +53 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.135.cat1.erb +71 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.136.cat1.erb +52 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.140.cat1.erb +39 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +23 -0
- 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
- 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
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.22.cat1.erb +30 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.23.cat1.erb +116 -0
- 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
- 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
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +24 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.32.cat1.erb +21 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +22 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.38.cat1.erb +21 -0
- 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
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.41.cat1.erb +45 -0
- 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
- 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
- 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
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.45.cat1.erb +35 -0
- 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
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +47 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.51.cat1.erb +14 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.54.cat1.erb +32 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.55.cat1.erb +18 -0
- 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
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.59.cat1.erb +22 -0
- 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
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.63.cat1.erb +21 -0
- 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
- 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
- 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
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.81.cat1.erb +33 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.82.cat1.erb +33 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.24.3.9.cat1.erb +41 -0
- data/templates/cat1/r3_1/_2.16.840.1.113883.10.20.28.3.6.cat1.erb +17 -0
- data/templates/cat1/r3_1/_address.cat1.erb +9 -0
- data/templates/cat1/r3_1/_author.cat1.erb +28 -0
- data/templates/cat1/r3_1/_fulfills.cat1.erb +14 -0
- data/templates/cat1/r3_1/_id.cat1.erb +1 -0
- data/templates/cat1/r3_1/_measures.cat1.erb +93 -0
- data/templates/cat1/r3_1/_medication_details.cat1.erb +16 -0
- data/templates/cat1/r3_1/_medication_dispense.cat1.erb +22 -0
- data/templates/cat1/r3_1/_ordinality.cat1.erb +10 -0
- data/templates/cat1/r3_1/_organization.cat1.erb +9 -0
- data/templates/cat1/r3_1/_patient_data.cat1.erb +17 -0
- data/templates/cat1/r3_1/_providers.cat1.erb +76 -0
- data/templates/cat1/r3_1/_reason.cat1.erb +34 -0
- data/templates/cat1/r3_1/_record_target.cat1.erb +56 -0
- data/templates/cat1/r3_1/_reporting_parameters.cat1.erb +31 -0
- data/templates/cat1/r3_1/_result_value.cat1.erb +28 -0
- data/templates/cat1/r3_1/_telecom.cat1.erb +1 -0
- data/templates/cat1/r3_1/show.cat1.erb +183 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.1.cat1.erb +14 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.103.cat1.erb +17 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.105.cat1.erb +68 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.12.cat1.erb +53 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.135.cat1.erb +75 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.136.cat1.erb +52 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.140.cat1.erb +39 -0
- 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
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.145.cat1.erb +24 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +23 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.18.cat1.erb +25 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.2.cat1.erb +29 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.22.cat1.erb +30 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.23.cat1.erb +116 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.3.cat1.erb +25 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +24 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.32.cat1.erb +21 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +22 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.38.cat1.erb +21 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.4.cat1.erb +29 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.41.cat1.erb +45 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.42.cat1.erb +38 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.43.cat1.erb +24 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.44.cat1.erb +25 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.45.cat1.erb +35 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.46.cat1.erb +30 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +47 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.51.cat1.erb +14 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.54.cat1.erb +32 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.55.cat1.erb +18 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.57.cat1.erb +23 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.59.cat1.erb +22 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.62.cat1.erb +36 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.63.cat1.erb +21 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.64.cat1.erb +52 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.7.cat1.erb +33 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.81.cat1.erb +33 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.82.cat1.erb +33 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.24.3.9.cat1.erb +41 -0
- data/templates/cat1/r4/_2.16.840.1.113883.10.20.28.3.6.cat1.erb +17 -0
- data/templates/cat1/r4/_address.cat1.erb +7 -0
- data/templates/cat1/r4/_author.cat1.erb +28 -0
- data/templates/cat1/r4/_fulfills.cat1.erb +14 -0
- data/templates/cat1/r4/_id.cat1.erb +1 -0
- data/templates/cat1/r4/_measures.cat1.erb +93 -0
- data/templates/cat1/r4/_medication_details.cat1.erb +16 -0
- data/templates/cat1/r4/_medication_dispense.cat1.erb +22 -0
- data/templates/cat1/r4/_ordinality.cat1.erb +10 -0
- data/templates/cat1/r4/_organization.cat1.erb +9 -0
- data/templates/cat1/r4/_patient_data.cat1.erb +17 -0
- data/templates/cat1/r4/_providers.cat1.erb +76 -0
- data/templates/cat1/r4/_reason.cat1.erb +34 -0
- data/templates/cat1/r4/_record_target.cat1.erb +54 -0
- data/templates/cat1/r4/_reporting_parameters.cat1.erb +31 -0
- data/templates/cat1/r4/_result_value.cat1.erb +28 -0
- data/templates/cat1/r4/_telecom.cat1.erb +1 -0
- data/templates/cat1/r4/show.cat1.erb +192 -0
- data/templates/cat3/{_address.cat3.erb → r1/_address.cat3.erb} +0 -0
- data/templates/cat3/r1/_author.cat3.erb +28 -0
- data/templates/cat3/{_continuous_variable_value.cat3.erb → r1/_continuous_variable_value.cat3.erb} +0 -0
- data/templates/cat3/r1/_id.cat3.erb +1 -0
- data/templates/cat3/{_measure_data.cat3.erb → r1/_measure_data.cat3.erb} +7 -6
- data/templates/cat3/{_organization.cat3.erb → r1/_organization.cat3.erb} +0 -0
- data/templates/cat3/{_performance_rate.cat3.erb → r1/_performance_rate.cat3.erb} +1 -3
- data/templates/cat3/{_providers.cat3.erb → r1/_providers.cat3.erb} +0 -0
- data/templates/cat3/{_reporting_parameters.cat3.erb → r1/_reporting_parameters.cat3.erb} +0 -0
- data/templates/cat3/{_supplemental_data.cat3.erb → r1/_supplemental_data.cat3.erb} +2 -0
- data/templates/cat3/r1/_telecom.cat3.erb +1 -0
- data/templates/cat3/{show.cat3.erb → r1/show.cat3.erb} +5 -5
- data/templates/cat3/r1_1/_address.cat3.erb +9 -0
- data/templates/cat3/r1_1/_author.cat3.erb +28 -0
- data/templates/cat3/r1_1/_continuous_variable_value.cat3.erb +20 -0
- data/templates/cat3/r1_1/_id.cat3.erb +1 -0
- data/templates/cat3/r1_1/_measure_data.cat3.erb +136 -0
- data/templates/cat3/r1_1/_organization.cat3.erb +6 -0
- data/templates/cat3/r1_1/_performance_rate.cat3.erb +18 -0
- data/templates/{cat1/_providers.cat1.erb → cat3/r1_1/_providers.cat3.erb} +18 -18
- data/templates/{cat1/_reporting_parameters.cat1.erb → cat3/r1_1/_reporting_parameters.cat3.erb} +5 -1
- data/templates/cat3/r1_1/_supplemental_data.cat3.erb +38 -0
- data/templates/cat3/r1_1/_telecom.cat3.erb +1 -0
- data/templates/cat3/r1_1/show.cat3.erb +150 -0
- data/templates/cat3/r2/_address.cat3.erb +9 -0
- data/templates/cat3/r2/_author.cat3.erb +28 -0
- data/templates/cat3/r2/_continuous_variable_value.cat3.erb +20 -0
- data/templates/cat3/r2/_id.cat3.erb +1 -0
- data/templates/cat3/r2/_measure_data.cat3.erb +136 -0
- data/templates/cat3/r2/_organization.cat3.erb +6 -0
- data/templates/cat3/r2/_performance_rate.cat3.erb +19 -0
- data/templates/cat3/r2/_providers.cat3.erb +57 -0
- data/templates/cat3/r2/_reporting_parameters.cat3.erb +29 -0
- data/templates/cat3/r2/_supplemental_data.cat3.erb +38 -0
- data/templates/cat3/r2/_telecom.cat3.erb +1 -0
- data/templates/cat3/r2/show.cat3.erb +150 -0
- data/templates/cat3/r2_1/_address.cat3.erb +9 -0
- data/templates/cat3/r2_1/_author.cat3.erb +28 -0
- data/templates/cat3/r2_1/_continuous_variable_value.cat3.erb +20 -0
- data/templates/cat3/r2_1/_id.cat3.erb +1 -0
- data/templates/cat3/r2_1/_measure_data.cat3.erb +136 -0
- data/templates/cat3/r2_1/_organization.cat3.erb +6 -0
- data/templates/cat3/r2_1/_performance_rate.cat3.erb +19 -0
- data/templates/cat3/r2_1/_providers.cat3.erb +57 -0
- data/templates/cat3/r2_1/_reporting_parameters.cat3.erb +20 -0
- data/templates/cat3/r2_1/_reporting_parameters_act.cat3.erb +10 -0
- data/templates/cat3/r2_1/_supplemental_data.cat3.erb +38 -0
- data/templates/cat3/r2_1/_telecom.cat3.erb +1 -0
- data/templates/cat3/r2_1/show.cat3.erb +153 -0
- data/templates/ccda/_medical_equipment.ccda.erb +1 -1
- data/templates/ccda/_social_history.ccda.erb +2 -2
- data/templates/ccda/_vital_signs.ccda.erb +1 -1
- data/templates/html/_entries_by_section.html.erb +1 -1
- metadata +425 -153
- data/lib/health-data-standards/import/cat1/procedure_importer.rb +0 -42
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.11.cat1.erb +0 -55
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.13.cat1.erb +0 -38
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +0 -22
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +0 -22
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +0 -20
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +0 -27
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.51.cat1.erb +0 -13
- data/templates/cat1/_reason.cat1.erb +0 -23
@@ -2,64 +2,133 @@ module HQMF2
|
|
2
2
|
# Represents an HQMF population criteria, also supports all the same methods as
|
3
3
|
# HQMF2::Precondition
|
4
4
|
class PopulationCriteria
|
5
|
-
|
6
5
|
include HQMF2::Utilities
|
7
|
-
|
6
|
+
|
8
7
|
attr_reader :preconditions, :id, :hqmf_id, :title, :aggregator, :comments
|
9
|
-
#need to do this to allow for setting the type to OBSERV for
|
8
|
+
# need to do this to allow for setting the type to OBSERV for
|
10
9
|
attr_accessor :type
|
11
10
|
# Create a new population criteria from the supplied HQMF entry
|
12
11
|
# @param [Nokogiri::XML::Element] the HQMF entry
|
13
|
-
def initialize(entry, doc)
|
12
|
+
def initialize(entry, doc, id_generator)
|
13
|
+
@id_generator = id_generator
|
14
14
|
@doc = doc
|
15
15
|
@entry = entry
|
16
|
-
|
17
|
-
|
16
|
+
setup_derived_entry_elements(id_generator)
|
17
|
+
# modify type to meet current expected population names
|
18
|
+
@type = 'IPP' if @type == 'IPOP' || @type == 'IPPOP'
|
19
|
+
@comments = nil if comments.empty?
|
20
|
+
# MEAN is handled in current code. Changed since it should have the same effect
|
21
|
+
@aggregator = 'MEAN' if @aggregator == 'AVERAGE'
|
22
|
+
@hqmf_id = @type unless @hqmf_id # The id extension is not required, if it's not provided use the code
|
23
|
+
handle_type(id_generator)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Handles how the code should deal with the type definition (aggregate vs non-aggregate)
|
27
|
+
def handle_type(id_generator)
|
28
|
+
if @type != 'AGGREGATE'
|
29
|
+
# Generate the precondition for this population
|
30
|
+
if @preconditions.length > 1 ||
|
31
|
+
(@preconditions.length == 1 && @preconditions[0].conjunction != conjunction_code)
|
32
|
+
@preconditions = [Precondition.new(id_generator.next_id, conjunction_code, @preconditions)]
|
33
|
+
end
|
34
|
+
else
|
35
|
+
# Extract the data criteria this population references
|
36
|
+
dc = handle_observation_criteria
|
37
|
+
@preconditions = [Precondition.new(id_generator.next_id, nil, nil, false, HQMF2::Reference.new(dc.id))]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Handles extracting elements from the entry
|
42
|
+
def setup_derived_entry_elements(id_generator)
|
43
|
+
@hqmf_id = attr_val('./*/cda:id/@root') || attr_val('./*/cda:typeId/@extension')
|
44
|
+
@title = attr_val('./*/cda:code/cda:displayName/@value').try(:titleize)
|
18
45
|
@type = attr_val('./*/cda:code/@code')
|
19
|
-
@
|
20
|
-
|
21
|
-
|
46
|
+
@comments = @entry.xpath('./*/cda:text/cda:xml/cda:qdmUserComments/cda:item/text()', HQMF2::Document::NAMESPACES)
|
47
|
+
.map(&:content)
|
48
|
+
handle_preconditions(id_generator)
|
22
49
|
obs_test = attr_val('./cda:measureObservationDefinition/@classCode')
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
50
|
+
# If there are no measure observations, or there is a title, then there are no aggregations to extract
|
51
|
+
return unless !@title && obs_test.to_s == 'OBS'
|
52
|
+
@title = attr_val('../cda:code/cda:displayName/@value')
|
53
|
+
@aggregator = attr_val('./cda:measureObservationDefinition/cda:methodCode/cda:item/@code')
|
54
|
+
end
|
55
|
+
|
56
|
+
# specifically handles extracting the preconditions for the population criteria
|
57
|
+
def handle_preconditions(id_generator)
|
58
|
+
# Nest multiple preconditions under a single root precondition
|
59
|
+
@preconditions = @entry.xpath('./*/cda:precondition[not(@nullFlavor)]', HQMF2::Document::NAMESPACES)
|
60
|
+
.collect do |pre|
|
61
|
+
precondition = Precondition.parse(pre, @doc, id_generator)
|
62
|
+
precondition.reference.nil? && precondition.preconditions.empty? ? nil : precondition
|
29
63
|
end
|
30
|
-
|
31
|
-
|
64
|
+
# Remove uneeded nils from the array
|
65
|
+
@preconditions.compact!
|
66
|
+
end
|
67
|
+
|
68
|
+
# extracts out any measure observation definitons, creating from them the proper criteria to generate a precondition
|
69
|
+
def handle_observation_criteria
|
70
|
+
exp = @entry.at_xpath('./cda:measureObservationDefinition/cda:value/cda:expression/@value',
|
71
|
+
HQMF2::Document::NAMESPACES)
|
72
|
+
# Measure Observations criteria rely on computed expressions. If it doesn't have one,
|
73
|
+
# then it is likely formatted improperly.
|
74
|
+
fail 'Measure Observations criteria is missing computed expression(s) ' if exp.nil?
|
75
|
+
parts = exp.to_s.split('-')
|
76
|
+
dc = parse_parts_to_dc(parts)
|
77
|
+
@doc.add_data_criteria(dc)
|
78
|
+
# Update reference_ids with any newly referenced data criteria
|
79
|
+
dc.children_criteria.each { |cc| @doc.add_reference_id(cc) } unless dc.children_criteria.nil?
|
80
|
+
dc
|
81
|
+
end
|
82
|
+
|
83
|
+
# generates the value given in an expression based on the number of criteria it references.
|
84
|
+
def parse_parts_to_dc(parts)
|
85
|
+
case parts.length
|
86
|
+
when 1
|
87
|
+
# If there is only one part, it is a reference to an existing data criteria's value
|
88
|
+
@doc.find_criteria_by_lvn(parts.first.strip.split('.')[0])
|
89
|
+
when 2
|
90
|
+
# If there are two parts, there is a computation performed, specifically time difference, on the two criteria
|
91
|
+
children = parts.collect { |p| @doc.find_criteria_by_lvn(p.strip.split('.')[0]).id }
|
92
|
+
id = "GROUP_TIMEDIFF_#{@id_generator.next_id}"
|
93
|
+
HQMF2::DataCriteriaWrapper.new(id: id,
|
94
|
+
title: id,
|
95
|
+
subset_operators: [HQMF::SubsetOperator.new('DATETIMEDIFF', nil)],
|
96
|
+
children_criteria: children,
|
97
|
+
derivation_operator: HQMF::DataCriteria::XPRODUCT,
|
98
|
+
type: 'derived',
|
99
|
+
definition: 'derived',
|
100
|
+
negation: false,
|
101
|
+
source_data_criteria: id
|
102
|
+
)
|
103
|
+
else
|
104
|
+
# If there are neither one or 2 parts, the code should fail
|
105
|
+
fail "No defined extraction method to handle #{parts.length} parts"
|
32
106
|
end
|
33
107
|
end
|
34
|
-
|
108
|
+
|
35
109
|
def create_human_readable_id(id)
|
36
110
|
@id = id
|
37
111
|
end
|
38
|
-
|
39
|
-
# Return true of this precondition represents a conjunction with nested preconditions
|
40
|
-
# or false of this precondition is a reference to a data criteria
|
41
|
-
def conjunction?
|
42
|
-
true
|
43
|
-
end
|
44
112
|
|
45
|
-
# Get the conjunction code,
|
113
|
+
# Get the conjunction code, ALL_TRUE or AT_LEAST_ONE_TRUE
|
46
114
|
# @return [String] conjunction code
|
47
115
|
def conjunction_code
|
48
116
|
case @type
|
49
|
-
when HQMF::PopulationCriteria::IPP, HQMF::PopulationCriteria::DENOM, HQMF::PopulationCriteria::NUMER,
|
117
|
+
when HQMF::PopulationCriteria::IPP, HQMF::PopulationCriteria::DENOM, HQMF::PopulationCriteria::NUMER,
|
118
|
+
HQMF::PopulationCriteria::MSRPOPL, HQMF::PopulationCriteria::STRAT
|
50
119
|
HQMF::Precondition::ALL_TRUE
|
51
|
-
when HQMF::PopulationCriteria::DENEXCEP, HQMF::PopulationCriteria::DENEX
|
120
|
+
when HQMF::PopulationCriteria::DENEXCEP, HQMF::PopulationCriteria::DENEX, HQMF::PopulationCriteria::MSRPOPLEX,
|
121
|
+
HQMF::PopulationCriteria::NUMEX
|
52
122
|
HQMF::Precondition::AT_LEAST_ONE_TRUE
|
53
123
|
else
|
54
|
-
|
124
|
+
fail "Unknown population type [#{@type}]"
|
55
125
|
end
|
56
126
|
end
|
57
|
-
|
127
|
+
|
128
|
+
# Generates this classes hqmf-model equivalent
|
58
129
|
def to_model
|
59
|
-
mps = preconditions.collect
|
130
|
+
mps = preconditions.collect(&:to_model)
|
60
131
|
HQMF::PopulationCriteria.new(id, hqmf_id, type, mps, title, aggregator, comments)
|
61
132
|
end
|
62
|
-
|
63
133
|
end
|
64
|
-
|
65
134
|
end
|
@@ -1,47 +1,73 @@
|
|
1
1
|
module HQMF2
|
2
|
-
|
2
|
+
# Represents the logic that defines grouping of criteria and actions done on it.
|
3
3
|
class Precondition
|
4
|
-
|
5
4
|
include HQMF2::Utilities
|
6
|
-
|
7
|
-
attr_reader :preconditions, :reference
|
8
|
-
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
|
6
|
+
attr_reader :preconditions, :reference, :conjunction, :id
|
7
|
+
|
8
|
+
def self.parse(entry, doc, id_generator)
|
9
|
+
doc = doc
|
10
|
+
entry = entry
|
11
|
+
aggregation = entry.at_xpath('./cda:allTrue | ./cda:atLeastOneTrue | ./cda:allFalse | ./cda:atLeastOneFalse',
|
12
|
+
HQMF2::Document::NAMESPACES)
|
13
|
+
|
14
|
+
# Sets the reference criteria for the precondition (if it exists)
|
15
|
+
reference_def = entry.at_xpath('./*/cda:id', HQMF2::Document::NAMESPACES)
|
16
|
+
reference_def ||= entry.at_xpath('./cda:join/cda:templateId/cda:item', HQMF2::Document::NAMESPACES)
|
17
|
+
reference = Reference.new(reference_def) if reference_def
|
18
|
+
|
19
|
+
# Unless there is an aggregator, no further actions are necessary.
|
20
|
+
return new(id_generator.next_id, nil, [], false, reference) unless aggregation
|
21
|
+
|
22
|
+
precondition_entries = entry.xpath('./*/cda:precondition', HQMF2::Document::NAMESPACES)
|
23
|
+
preconditions = precondition_entries.collect do |precondition|
|
24
|
+
precondition = Precondition.parse(precondition, doc, id_generator)
|
25
|
+
# There are cases where a precondition may contain no references or preconditions, and should be ignored.
|
26
|
+
precondition.reference.nil? && precondition.preconditions.empty? ? nil : precondition
|
14
27
|
end
|
15
|
-
|
16
|
-
|
17
|
-
reference_def = @entry.at_xpath('./cda:join/cda:templateId/cda:item', HQMF2::Document::NAMESPACES)
|
18
|
-
end
|
19
|
-
if reference_def
|
20
|
-
@reference = Reference.new(reference_def)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# Return true of this precondition represents a conjunction with nested preconditions
|
25
|
-
# or false of this precondition is a reference to a data criteria
|
26
|
-
def conjunction?
|
27
|
-
@preconditions.length>0
|
28
|
+
preconditions.compact!
|
29
|
+
handle_aggregation(id_generator, reference, preconditions, aggregation)
|
28
30
|
end
|
29
|
-
|
30
|
-
#
|
31
|
-
#
|
32
|
-
def
|
33
|
-
|
34
|
-
|
31
|
+
|
32
|
+
# "False" aggregators exist, and require special handling, so this manages that and returns the
|
33
|
+
# proper precondition.
|
34
|
+
def self.handle_aggregation(id_generator, reference, preconditions, aggregation, conjunction = nil)
|
35
|
+
negation = false
|
36
|
+
conjunction = aggregation.name
|
37
|
+
case conjunction
|
38
|
+
# DeMorgan's law is used to handle negated caes: e.g. to find if all are false, negate the "at least one true"
|
39
|
+
# check.
|
40
|
+
when 'allFalse'
|
41
|
+
negation = true
|
42
|
+
conjunction = 'atLeastOneTrue'
|
43
|
+
when 'atLeastOneFalse'
|
44
|
+
negation = true
|
45
|
+
conjunction = 'allTrue'
|
46
|
+
end
|
47
|
+
# Return the proper precondition given if a negation exists
|
48
|
+
if negation
|
49
|
+
# Wrap the negation in a seperate precondition which this will reference
|
50
|
+
precondition_wrapper = new(id_generator.next_id, conjunction, preconditions, true, reference)
|
51
|
+
new(id_generator.next_id, conjunction, [precondition_wrapper])
|
35
52
|
else
|
36
|
-
|
53
|
+
new(id_generator.next_id, conjunction, preconditions, false, reference)
|
37
54
|
end
|
38
55
|
end
|
39
|
-
|
56
|
+
|
57
|
+
def initialize(id, conjunction, preconditions = [], negation = false, reference = nil)
|
58
|
+
@preconditions = preconditions || []
|
59
|
+
@conjunction = conjunction
|
60
|
+
@reference = reference
|
61
|
+
@negation = negation
|
62
|
+
@id = id
|
63
|
+
end
|
64
|
+
|
65
|
+
# Generates this classes hqmf-model equivalent
|
40
66
|
def to_model
|
41
|
-
pcs = preconditions.collect
|
42
|
-
mr = reference ? reference.to_model : nil
|
43
|
-
|
67
|
+
pcs = @preconditions.collect(&:to_model)
|
68
|
+
mr = @reference ? @reference.to_model : nil
|
69
|
+
cc = @conjunction
|
70
|
+
HQMF::Precondition.new(@id, pcs, mr, cc, @negation)
|
44
71
|
end
|
45
72
|
end
|
46
|
-
|
47
73
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module HQMF2
|
2
|
+
# Generates the Source Data Criteria from the entries in the HQMF
|
3
|
+
class SourceDataCriteriaHelper
|
4
|
+
# Generates an identifier based on the leftover elements included in the source data criteria.
|
5
|
+
def self.identifier(criteria)
|
6
|
+
sha256 = ''
|
7
|
+
sha256 << "#{criteria.code_list_id}:"
|
8
|
+
sha256 << "#{criteria.definition}:"
|
9
|
+
sha256 << "#{criteria.status}:"
|
10
|
+
sha256 << "#{criteria.specific_occurrence}:"
|
11
|
+
sha256 << "#{criteria.specific_occurrence_const}:"
|
12
|
+
sha256 << "#{criteria.variable}:"
|
13
|
+
sha256 << (criteria.children_criteria.nil? ? '<nil>:' : "#{criteria.children_criteria.sort.join(',')}:")
|
14
|
+
|
15
|
+
Digest::SHA256.hexdigest sha256
|
16
|
+
end
|
17
|
+
|
18
|
+
# Rejects any derived elements as they should never be used as source.
|
19
|
+
def self.should_reject?(dc)
|
20
|
+
dc.definition == 'derived'
|
21
|
+
end
|
22
|
+
|
23
|
+
# Removes unnecessary elements from a data criteria to create a source data criteria
|
24
|
+
def self.strip_non_sc_elements(dc)
|
25
|
+
if [HQMF::DataCriteria::SATISFIES_ANY, HQMF::DataCriteria::SATISFIES_ALL].include? dc.definition
|
26
|
+
dc.instance_variable_set(:@definition, 'derived')
|
27
|
+
end
|
28
|
+
dc.instance_variable_set(:@source_data_criteria, dc.id)
|
29
|
+
dc.instance_variable_set(:@field_values, {})
|
30
|
+
dc.instance_variable_set(:@temporal_references, [])
|
31
|
+
dc.instance_variable_set(:@subset_operators, [])
|
32
|
+
dc.instance_variable_set(:@value, nil)
|
33
|
+
dc.instance_variable_set(:@negation, false)
|
34
|
+
dc.instance_variable_set(:@negation_code_list_id, nil)
|
35
|
+
dc
|
36
|
+
end
|
37
|
+
|
38
|
+
# determins if a data criteria has any non-SDC fields set (i.e., those fields need to be stripped)
|
39
|
+
def self.already_stripped?(dc)
|
40
|
+
dc.field_values.blank? && dc.temporal_references.blank? && dc.subset_operators.blank? && dc.value.blank? && dc.negation.blank? && dc.negation_code_list_id.blank?
|
41
|
+
end
|
42
|
+
|
43
|
+
# Creates a data criteria based on an entry xml, removes any unnecessary elements (for the source),
|
44
|
+
# and adds a data criteria reference if none exist
|
45
|
+
def self.as_source_data_criteria(entry, data_criteria_references = {}, occurrences_map = {})
|
46
|
+
dc = DataCriteria.new(entry, data_criteria_references, occurrences_map)
|
47
|
+
dc.original_id = dc.id
|
48
|
+
unless dc.definition == 'derived' # && dc.temporal_references.blank? && dc.subset_operators.blank? && dc.value.blank? && dc.field_values.blank?
|
49
|
+
# add "_source" to the id to differentiate from the non-source
|
50
|
+
dc.id = "#{dc.id}_source"
|
51
|
+
end
|
52
|
+
dc = SourceDataCriteriaHelper.strip_non_sc_elements(dc)
|
53
|
+
# add it as a reference
|
54
|
+
if dc && (data_criteria_references[dc.id].nil? || data_criteria_references[dc.id].code_list_id.nil?)
|
55
|
+
data_criteria_references[dc.original_id] = dc
|
56
|
+
end
|
57
|
+
|
58
|
+
dc
|
59
|
+
end
|
60
|
+
|
61
|
+
# Check if there is an existing entry in the source data criteria list that matches the candidate passed in
|
62
|
+
# this is used to prevent adding duplicate source data criteria entries when one already exists
|
63
|
+
def self.find_existing_source_data_criteria(list, candidate)
|
64
|
+
list.each do |sdc|
|
65
|
+
# check if we have an exact match on an existing SDC
|
66
|
+
return sdc if SourceDataCriteriaHelper.identifier(sdc) == SourceDataCriteriaHelper.identifier(candidate)
|
67
|
+
# we have another existing copy of the specific occurrence (identified via the constant and occurrence lettering), use that rather than duplicating... there will not be an
|
68
|
+
# exact match for variables since a new child will have been generated
|
69
|
+
return sdc if !sdc.specific_occurrence_const.nil? && sdc.specific_occurrence_const == candidate.specific_occurrence_const && sdc.specific_occurrence == candidate.specific_occurrence
|
70
|
+
end
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
|
74
|
+
# Given a list of criteria obtained from the XML, generate most of the source data criteria (since no explicit
|
75
|
+
# sources are given). After generating the source data criteria, filter the list to not include repeated,
|
76
|
+
# unnecessary sources, but maintain and return map of those that have been removed to those that they were replaced
|
77
|
+
# with.
|
78
|
+
def self.get_source_data_criteria_list(full_criteria_list, data_criteria_references = {}, occurrences_map = {})
|
79
|
+
# currently, this will erase the sources if the ids are the same, but will not correct references later on
|
80
|
+
source_data_criteria = full_criteria_list.map do |entry|
|
81
|
+
SourceDataCriteriaHelper.as_source_data_criteria(entry, data_criteria_references, occurrences_map)
|
82
|
+
end
|
83
|
+
|
84
|
+
collapsed_source_data_criteria_map = {}
|
85
|
+
uniq_source_data_criteria = {}
|
86
|
+
source_data_criteria.each do |sdc|
|
87
|
+
identifier = SourceDataCriteriaHelper.identifier(sdc)
|
88
|
+
if uniq_source_data_criteria.key? identifier
|
89
|
+
collapsed_source_data_criteria_map[sdc.original_id] = uniq_source_data_criteria[identifier].id
|
90
|
+
else
|
91
|
+
uniq_source_data_criteria[identifier] = sdc
|
92
|
+
end
|
93
|
+
end
|
94
|
+
unique = uniq_source_data_criteria.values.reject { |dc| SourceDataCriteriaHelper.should_reject?(dc) }
|
95
|
+
|
96
|
+
# we need an empty data criteria in source that acts as the target for the specific occurrence
|
97
|
+
# the data criteria that we are duplicating will eventually get turned into a specific occurrence
|
98
|
+
occurrences = unique.select {|dc| occurrences_map[dc.id] && dc.definition != 'derived' }
|
99
|
+
occurrences.each do |occurrence|
|
100
|
+
# do not create a nonspecific SDC for variables
|
101
|
+
unless occurrence.variable
|
102
|
+
dc = SourceDataCriteriaHelper.as_source_data_criteria(occurrence.entry)
|
103
|
+
dc.id = "#{dc.id}_nonSpecific"
|
104
|
+
dc.instance_variable_set(:@source_data_criteria, dc.id)
|
105
|
+
unique << dc unless SourceDataCriteriaHelper.find_existing_source_data_criteria(unique, dc)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
[unique, collapsed_source_data_criteria_map]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -3,35 +3,88 @@ module HQMF2
|
|
3
3
|
# don't specify any restrictions on that value
|
4
4
|
class AnyValue
|
5
5
|
attr_reader :type
|
6
|
-
|
7
|
-
def initialize(type='ANYNonNull')
|
8
|
-
@type = type
|
6
|
+
|
7
|
+
def initialize(type = 'ANYNonNull')
|
8
|
+
@type = type
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
|
+
# Generates this classes hqmf-model equivalent
|
11
12
|
def to_model
|
12
13
|
HQMF::AnyValue.new(@type)
|
13
|
-
end
|
14
|
+
end
|
14
15
|
end
|
15
|
-
|
16
|
+
|
16
17
|
# Represents a bound within a HQMF pauseQuantity, has a value, a unit and an
|
17
18
|
# inclusive/exclusive indicator
|
18
19
|
class Value
|
19
20
|
include HQMF2::Utilities
|
20
|
-
|
21
|
+
|
21
22
|
attr_reader :type, :unit, :value
|
22
|
-
|
23
|
-
def initialize(entry, default_type='PQ', force_inclusive=false)
|
23
|
+
|
24
|
+
def initialize(entry, default_type = 'PQ', force_inclusive = false, _parent = nil)
|
24
25
|
@entry = entry
|
25
26
|
@type = attr_val('./@xsi:type') || default_type
|
26
27
|
@unit = attr_val('./@unit')
|
27
28
|
@value = attr_val('./@value')
|
28
29
|
@force_inclusive = force_inclusive
|
30
|
+
|
31
|
+
# FIXME: Remove below when lengthOfStayQuantity unit is fixed
|
32
|
+
@unit = 'd' if @unit == 'days'
|
29
33
|
end
|
30
|
-
|
34
|
+
|
31
35
|
def inclusive?
|
32
|
-
|
36
|
+
# If the high and low value are at any time the same, then it must be an inclusive value.
|
37
|
+
equivalent = attr_val('../cda:low/@value') == attr_val('../cda:high/@value')
|
38
|
+
|
39
|
+
# If and inclusivity value is set for any specific value, then mark the value as inclusive.
|
40
|
+
# IDEA: This could be limited in future iterations by including the parent type (temporal reference, subset code,
|
41
|
+
# etc.)
|
42
|
+
inclusive_temporal_ref? || inclusive_length_of_stay? || inclusive_basic_values? || inclusive_subsets? ||
|
43
|
+
equivalent || @force_inclusive
|
33
44
|
end
|
34
|
-
|
45
|
+
|
46
|
+
# Check whether the temporal reference should be marked as inclusive
|
47
|
+
def inclusive_temporal_ref?
|
48
|
+
# FIXME: NINF is used instead of 0 sometimes...? (not in the IG)
|
49
|
+
# FIXME: Given nullFlavor, but IG uses it and nullValue everywhere...
|
50
|
+
less_than_equal_tr = attr_val('../@highClosed') == 'true' &&
|
51
|
+
(attr_val('../cda:low/@value') == '0' || attr_val('../cda:low/@nullFlavor') == 'NINF')
|
52
|
+
greater_than_equal_tr = attr_val('../cda:high/@nullFlavor') == 'PINF' &&
|
53
|
+
attr_val('../cda:low/@value')
|
54
|
+
# Both less and greater require lowClosed to be set to true
|
55
|
+
(less_than_equal_tr || greater_than_equal_tr) && attr_val('../@lowClosed') == 'true'
|
56
|
+
end
|
57
|
+
|
58
|
+
# Check whether the length of stay should be inclusive.
|
59
|
+
def inclusive_length_of_stay?
|
60
|
+
# lengthOfStay - EH111, EH108
|
61
|
+
less_than_equal_los = attr_val('../cda:low/@nullFlavor') == 'NINF' &&
|
62
|
+
attr_val('../@highClosed') != 'false'
|
63
|
+
|
64
|
+
greater_than_equal_los = attr_val('../cda:high/@nullFlavor') == 'PINF' &&
|
65
|
+
attr_val('../@lowClosed') != 'false'
|
66
|
+
# Both less and greater require that the type is PQ
|
67
|
+
(less_than_equal_los || greater_than_equal_los) && attr_val('@xsi:type') == 'PQ'
|
68
|
+
end
|
69
|
+
|
70
|
+
# Check is the basic values should be marked as inclusive, currently only checks for greater than case
|
71
|
+
def inclusive_basic_values?
|
72
|
+
# Basic values - EP65, EP9, and more
|
73
|
+
attr_val('../cda:high/@nullFlavor') == 'PINF' &&
|
74
|
+
attr_val('../cda:low/@value') &&
|
75
|
+
attr_val('../@lowClosed') != 'false' &&
|
76
|
+
attr_val('../@xsi:type') == 'IVL_PQ'
|
77
|
+
end
|
78
|
+
|
79
|
+
# Check if subset values should be marked as inclusive. Currently only handles greater than
|
80
|
+
def inclusive_subsets?
|
81
|
+
# subset - EP128, EH108
|
82
|
+
attr_val('../cda:low/@value') != '0' &&
|
83
|
+
!attr_val('../cda:high/@value') &&
|
84
|
+
attr_val('../@lowClosed') != 'false' &&
|
85
|
+
!attr_val('../../../../../qdm:subsetCode/@code').nil?
|
86
|
+
end
|
87
|
+
|
35
88
|
def derived?
|
36
89
|
case attr_val('./@nullFlavor')
|
37
90
|
when 'DER'
|
@@ -40,7 +93,7 @@ module HQMF2
|
|
40
93
|
false
|
41
94
|
end
|
42
95
|
end
|
43
|
-
|
96
|
+
|
44
97
|
def expression
|
45
98
|
if !derived?
|
46
99
|
nil
|
@@ -48,53 +101,81 @@ module HQMF2
|
|
48
101
|
attr_val('./cda:expression/@value')
|
49
102
|
end
|
50
103
|
end
|
51
|
-
|
104
|
+
|
105
|
+
# Generates this classes hqmf-model equivalent
|
52
106
|
def to_model
|
53
|
-
HQMF::Value.new(type,unit,value,inclusive?,derived?,expression)
|
107
|
+
HQMF::Value.new(type, unit, value, inclusive?, derived?, expression)
|
54
108
|
end
|
55
109
|
end
|
56
|
-
|
110
|
+
|
57
111
|
# Represents a HQMF physical quantity which can have low and high bounds
|
58
112
|
class Range
|
59
113
|
include HQMF2::Utilities
|
60
114
|
attr_accessor :low, :high, :width
|
61
|
-
|
62
|
-
def initialize(entry, type=nil)
|
115
|
+
|
116
|
+
def initialize(entry, type = nil)
|
63
117
|
@type = type
|
64
118
|
@entry = entry
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
119
|
+
return unless @entry
|
120
|
+
@low = optional_value("#{default_element_name}/cda:low", default_bounds_type)
|
121
|
+
@high = optional_value("#{default_element_name}/cda:high", default_bounds_type)
|
122
|
+
# Unset low bound to resolve verbose value bounds descriptions
|
123
|
+
@low = nil if (@high.try(:value) && @high.value.to_i > 0) && (@low.try(:value) && @low.value.try(:to_i) == 0)
|
124
|
+
@width = optional_value("#{default_element_name}/cda:width", 'PQ')
|
70
125
|
end
|
71
|
-
|
126
|
+
|
72
127
|
def type
|
73
128
|
@type || attr_val('./@xsi:type')
|
74
129
|
end
|
75
|
-
|
130
|
+
|
131
|
+
# Generates this classes hqmf-model equivalent
|
76
132
|
def to_model
|
77
|
-
lm = low
|
78
|
-
hm = high
|
79
|
-
wm = width
|
133
|
+
lm = low.try(:to_model)
|
134
|
+
hm = high.try(:to_model)
|
135
|
+
wm = width.try(:to_model)
|
80
136
|
model_type = type
|
81
137
|
if @entry.at_xpath('./cda:uncertainRange', HQMF2::Document::NAMESPACES)
|
82
138
|
model_type = 'IVL_PQ'
|
83
139
|
end
|
84
|
-
|
140
|
+
|
141
|
+
if generate_any_value?(lm, hm)
|
142
|
+
# Generate AnyValue if the only elements in the range are AnyValues.
|
143
|
+
HQMF::AnyValue.new
|
144
|
+
elsif generate_value?(lm, hm)
|
145
|
+
# Generate a singel value if both low and high are the same
|
146
|
+
HQMF::Value.new(lm.type, nil, lm.value, lm.inclusive?, lm.derived?, lm.expression)
|
147
|
+
else
|
148
|
+
HQMF::Range.new(model_type, lm, hm, wm)
|
149
|
+
end
|
85
150
|
end
|
86
|
-
|
151
|
+
|
152
|
+
# Check if are only AnyValue elements for low and high
|
153
|
+
def generate_any_value?(lm, hm)
|
154
|
+
(lm.nil? || lm.is_a?(HQMF::AnyValue)) && (hm.nil? || hm.is_a?(HQMF::AnyValue))
|
155
|
+
end
|
156
|
+
|
157
|
+
# Check if the value for the range should actually produce a single value instead of a range (if low and high are
|
158
|
+
# the same)
|
159
|
+
def generate_value?(lm, hm)
|
160
|
+
!lm.nil? && lm.try(:value) == hm.try(:value) && lm.try(:unit).nil? && hm.try(:unit).nil?
|
161
|
+
end
|
162
|
+
|
87
163
|
private
|
88
|
-
|
164
|
+
|
165
|
+
# Either derives a value from a specific path or generates a new value (or returns nil if none found)
|
89
166
|
def optional_value(xpath, type)
|
90
167
|
value_def = @entry.at_xpath(xpath, HQMF2::Document::NAMESPACES)
|
91
|
-
|
92
|
-
|
168
|
+
return unless value_def
|
169
|
+
if value_def['flavorId'] == 'ANY.NONNULL'
|
170
|
+
AnyValue.new
|
93
171
|
else
|
94
|
-
|
172
|
+
created_value = Value.new(value_def, type)
|
173
|
+
# Return nil if no value was parsed
|
174
|
+
created_value if created_value.try(:value)
|
95
175
|
end
|
96
176
|
end
|
97
177
|
|
178
|
+
# Defines how the time based element should be described
|
98
179
|
def default_element_name
|
99
180
|
case type
|
100
181
|
when 'IVL_PQ'
|
@@ -105,7 +186,8 @@ module HQMF2
|
|
105
186
|
'cda:uncertainRange'
|
106
187
|
end
|
107
188
|
end
|
108
|
-
|
189
|
+
|
190
|
+
# Sets up the default bound type as either time based or a physical quantity
|
109
191
|
def default_bounds_type
|
110
192
|
case type
|
111
193
|
when 'IVL_TS'
|
@@ -115,38 +197,38 @@ module HQMF2
|
|
115
197
|
end
|
116
198
|
end
|
117
199
|
end
|
118
|
-
|
119
|
-
# Represents
|
200
|
+
|
201
|
+
# Represents an HQMF effective time which is a specialization of an interval
|
120
202
|
class EffectiveTime < Range
|
121
203
|
def initialize(entry)
|
122
204
|
super
|
123
205
|
end
|
124
|
-
|
206
|
+
|
125
207
|
def type
|
126
208
|
'IVL_TS'
|
127
209
|
end
|
128
210
|
end
|
129
|
-
|
211
|
+
|
130
212
|
# Represents a HQMF CD value which has a code and codeSystem
|
131
213
|
class Coded
|
132
214
|
include HQMF2::Utilities
|
133
|
-
|
215
|
+
|
134
216
|
def initialize(entry)
|
135
217
|
@entry = entry
|
136
218
|
end
|
137
|
-
|
219
|
+
|
138
220
|
def type
|
139
221
|
attr_val('./@xsi:type') || 'CD'
|
140
222
|
end
|
141
|
-
|
223
|
+
|
142
224
|
def system
|
143
225
|
attr_val('./@codeSystem')
|
144
226
|
end
|
145
|
-
|
227
|
+
|
146
228
|
def code
|
147
229
|
attr_val('./@code')
|
148
230
|
end
|
149
|
-
|
231
|
+
|
150
232
|
def code_list_id
|
151
233
|
attr_val('./@valueSet')
|
152
234
|
end
|
@@ -166,103 +248,201 @@ module HQMF2
|
|
166
248
|
def unit
|
167
249
|
nil
|
168
250
|
end
|
169
|
-
|
251
|
+
|
252
|
+
# Generates this classes hqmf-model equivalent
|
170
253
|
def to_model
|
171
254
|
HQMF::Coded.new(type, system, code, code_list_id, title)
|
172
255
|
end
|
173
|
-
|
174
256
|
end
|
175
|
-
|
257
|
+
# Represents a subset of a specific group (the first in the group, the sum of the group, etc.)
|
176
258
|
class SubsetOperator
|
177
259
|
include HQMF2::Utilities
|
178
260
|
|
179
261
|
attr_reader :type, :value
|
262
|
+
ORDER_SUBSETS = %w(FIRST SECOND THIRD FOURTH FIFTH)
|
263
|
+
LAST_SUBSETS = %w(LAST RECENT)
|
264
|
+
TIME_SUBSETS = %w(DATEDIFF TIMEDIFF)
|
265
|
+
QDM_TYPE_MAP = { 'QDM_LAST:' => 'RECENT', 'QDM_SUM:SUM' => 'COUNT' }
|
180
266
|
|
181
267
|
def initialize(entry)
|
182
268
|
@entry = entry
|
183
|
-
|
269
|
+
|
270
|
+
sequence_number = attr_val('./cda:sequenceNumber/@value')
|
271
|
+
qdm_subset_code = attr_val('./qdm:subsetCode/@code')
|
272
|
+
subset_code = attr_val('./cda:subsetCode/@code')
|
273
|
+
if sequence_number
|
274
|
+
@type = ORDER_SUBSETS[sequence_number.to_i - 1]
|
275
|
+
else
|
276
|
+
@type = translate_type(subset_code, qdm_subset_code)
|
277
|
+
end
|
278
|
+
|
279
|
+
value_def = handle_value_definition
|
280
|
+
@value = HQMF2::Range.new(value_def, 'IVL_PQ') if value_def && !@value
|
281
|
+
end
|
282
|
+
|
283
|
+
# Return the value definition (what to calculate it on) associated with this subset.
|
284
|
+
# Other values, such as type and value, may be modified depending on this value.
|
285
|
+
def handle_value_definition
|
184
286
|
value_def = @entry.at_xpath('./*/cda:repeatNumber', HQMF2::Document::NAMESPACES)
|
185
|
-
|
287
|
+
unless value_def
|
288
|
+
# TODO: HQMF needs better differentiation between SUM & COUNT...
|
289
|
+
# currently using presence of repeatNumber...
|
290
|
+
@type = 'SUM' if @type == 'COUNT'
|
186
291
|
value_def = @entry.at_xpath('./*/cda:value', HQMF2::Document::NAMESPACES)
|
187
292
|
end
|
293
|
+
|
294
|
+
# TODO: Resolve extracting values embedded in criteria within outboundRel's
|
295
|
+
if @type == 'SUM'
|
296
|
+
value_def = @entry.at_xpath('./*/*/*/cda:value', HQMF2::Document::NAMESPACES)
|
297
|
+
end
|
298
|
+
|
188
299
|
if value_def
|
189
300
|
value_type = value_def.at_xpath('./@xsi:type', HQMF2::Document::NAMESPACES)
|
190
|
-
if String.try_convert(value_type) ==
|
191
|
-
@value = HQMF2::AnyValue.new()
|
192
|
-
end
|
301
|
+
@value = HQMF2::AnyValue.new if String.try_convert(value_type) == 'ANY'
|
193
302
|
end
|
194
303
|
|
195
|
-
|
196
|
-
|
304
|
+
value_def
|
305
|
+
end
|
306
|
+
|
307
|
+
# Take a qdm type code to map it to a subset operator, or failing at finding that, return the given subset code.
|
308
|
+
def translate_type(subset_code, qdm_subset_code)
|
309
|
+
combined = "#{qdm_subset_code}:#{subset_code}"
|
310
|
+
if QDM_TYPE_MAP[combined]
|
311
|
+
QDM_TYPE_MAP[combined]
|
312
|
+
else
|
313
|
+
subset_code
|
197
314
|
end
|
198
315
|
end
|
199
316
|
|
317
|
+
# Generates this classes hqmf-model equivalent
|
200
318
|
def to_model
|
201
319
|
vm = value ? value.to_model : nil
|
202
320
|
HQMF::SubsetOperator.new(type, vm)
|
203
321
|
end
|
204
322
|
end
|
205
|
-
|
323
|
+
|
324
|
+
# Represents a time bounded reference. Wraps the "Range" class
|
206
325
|
class TemporalReference
|
207
326
|
include HQMF2::Utilities
|
208
|
-
|
327
|
+
|
209
328
|
attr_reader :type, :reference, :range
|
210
329
|
|
330
|
+
# Use updated mappings to HDS temporal reference types (as used in SimpleXML Parser)
|
331
|
+
# https://github.com/projecttacoma/simplexml_parser/blob/fa0f589d98059b88d77dc3cb465b62184df31671/lib/model/types.rb#L167
|
332
|
+
UPDATED_TYPES = {
|
333
|
+
'EAOCW' => 'EACW',
|
334
|
+
'EAEORECW' => 'EACW',
|
335
|
+
'EAOCWSO' => 'EACWS',
|
336
|
+
'EASORECWS' => 'EACWS',
|
337
|
+
'EBOCW' => 'EBCW',
|
338
|
+
'EBEORECW' => 'EBCW',
|
339
|
+
'EBOCWSO' => 'EBCWS',
|
340
|
+
'EBSORECWS' => 'EBCWS',
|
341
|
+
'ECWSO' => 'ECWS',
|
342
|
+
'SAOCWEO' => 'SACWE',
|
343
|
+
'SAEORSCWE' => 'SACWE',
|
344
|
+
'SAOCW' => 'SACW',
|
345
|
+
'SASORSCW' => 'SACW',
|
346
|
+
'SBOCWEO' => 'SBCWE',
|
347
|
+
'SBEORSCWE' => 'SBCWE',
|
348
|
+
'SBOCW' => 'SBCW',
|
349
|
+
'SBSORSCW' => 'SBCW',
|
350
|
+
'SCWEO' => 'SCWE',
|
351
|
+
'OVERLAPS' => 'OVERLAP'
|
352
|
+
}
|
353
|
+
|
211
354
|
def initialize(entry)
|
212
355
|
@entry = entry
|
213
|
-
@type = attr_val('./@typeCode')
|
356
|
+
@type = UPDATED_TYPES[attr_val('./@typeCode')] || attr_val('./@typeCode')
|
214
357
|
@reference = Reference.new(@entry.at_xpath('./*/cda:id', HQMF2::Document::NAMESPACES))
|
215
|
-
range_def = @entry.at_xpath('./
|
216
|
-
if range_def
|
217
|
-
@range = HQMF2::Range.new(range_def, 'PQ')
|
218
|
-
end
|
358
|
+
range_def = @entry.at_xpath('./qdm:temporalInformation/qdm:delta', HQMF2::Document::NAMESPACES)
|
359
|
+
@range = HQMF2::Range.new(range_def, 'IVL_PQ') if range_def
|
219
360
|
end
|
220
|
-
|
361
|
+
|
362
|
+
# Generates this classes hqmf-model equivalent
|
221
363
|
def to_model
|
222
364
|
rm = range ? range.to_model : nil
|
223
365
|
HQMF::TemporalReference.new(type, reference.to_model, rm)
|
224
|
-
end
|
366
|
+
end
|
225
367
|
end
|
226
368
|
|
227
|
-
# Represents a HQMF reference to a data criteria that has a given type
|
369
|
+
# Represents a HQMF reference to a data criteria that has a given type
|
228
370
|
class TypedReference
|
229
371
|
include HQMF2::Utilities
|
230
372
|
attr_accessor :id, :type, :mood
|
231
373
|
|
232
374
|
# Create a new HQMF::Reference
|
233
375
|
# @param [String] id
|
234
|
-
def initialize(entry)
|
376
|
+
def initialize(entry, type = nil, verbose = false)
|
235
377
|
@entry = entry
|
236
378
|
@type = type || attr_val('./@classCode')
|
237
379
|
@mood = attr_val('./@moodCode')
|
238
380
|
@entry = entry.elements.first unless entry.at_xpath('./@extension')
|
381
|
+
@verbose = verbose
|
239
382
|
end
|
240
383
|
|
384
|
+
# Generate the reference for the typed reference to use
|
241
385
|
def reference
|
242
|
-
attr_val('./@extension')
|
386
|
+
value = "#{attr_val('./@extension')}_#{attr_val('./@root')}"
|
387
|
+
strip_tokens(value)
|
243
388
|
end
|
244
389
|
|
390
|
+
# Generates this classes hqmf-model equivalent
|
245
391
|
def to_model
|
246
|
-
HQMF::TypedReference.new(reference
|
392
|
+
HQMF::TypedReference.new(reference, @type, @mood)
|
247
393
|
end
|
248
|
-
|
249
394
|
end
|
250
395
|
|
251
396
|
# Represents a HQMF reference from a precondition to a data criteria
|
252
397
|
class Reference
|
253
398
|
include HQMF2::Utilities
|
254
|
-
|
399
|
+
|
255
400
|
def initialize(entry)
|
256
401
|
@entry = entry
|
257
402
|
end
|
258
|
-
|
403
|
+
|
404
|
+
# Generates the id to use for a reference
|
259
405
|
def id
|
260
|
-
|
406
|
+
if @entry.is_a? String
|
407
|
+
@entry
|
408
|
+
else
|
409
|
+
id = strip_tokens("#{attr_val('./@extension')}_#{attr_val('./@root')}")
|
410
|
+
# Handle MeasurePeriod references for calculation code
|
411
|
+
id = 'MeasurePeriod' if id.try(:start_with?, 'measureperiod')
|
412
|
+
id
|
413
|
+
end
|
261
414
|
end
|
262
|
-
|
415
|
+
|
416
|
+
# Generates this classes hqmf-model equivalent
|
263
417
|
def to_model
|
264
418
|
HQMF::Reference.new(id)
|
265
419
|
end
|
266
420
|
end
|
267
|
-
|
421
|
+
|
422
|
+
# Creates a Data Criteria given a map of options, and is used when full
|
423
|
+
# criteria parsing is not necessary.
|
424
|
+
class DataCriteriaWrapper
|
425
|
+
attr_accessor :status, :value, :effective_time
|
426
|
+
attr_accessor :temporal_references, :subset_operators, :children_criteria
|
427
|
+
attr_accessor :derivation_operator, :negation, :negation_code_list_id, :description
|
428
|
+
attr_accessor :field_values, :source_data_criteria, :specific_occurrence_const
|
429
|
+
attr_accessor :specific_occurrence, :comments
|
430
|
+
attr_accessor :id, :title, :definition, :variable, :code_list_id, :value, :inline_code_list
|
431
|
+
|
432
|
+
def initialize(opts = {})
|
433
|
+
opts.each { |k, v| instance_variable_set("@#{k}", v) }
|
434
|
+
end
|
435
|
+
|
436
|
+
# Generates this classes hqmf-model equivalent
|
437
|
+
def to_model
|
438
|
+
mv = @value ? @value.to_model : nil
|
439
|
+
met = @effective_time ? @effective_time.to_model : nil
|
440
|
+
mtr = @temporal_references
|
441
|
+
mso = @subset_operators
|
442
|
+
HQMF::DataCriteria.new(@id, @title, nil, @description, @code_list_id, @children_criteria,
|
443
|
+
@derivation_operator, @definition, @status, mv, field_values, met, @inline_code_list,
|
444
|
+
@negation, @negation_code_list_id, mtr, mso, @specific_occurrence,
|
445
|
+
@specific_occurrence_const, @source_data_criteria, @comments, @variable)
|
446
|
+
end
|
447
|
+
end
|
268
448
|
end
|