health-data-standards 2.2.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +5 -0
- data/lib/health-data-standards.rb +55 -12
- data/lib/health-data-standards/export/c32.rb +7 -6
- data/lib/health-data-standards/export/cat_1.rb +18 -0
- data/lib/health-data-standards/export/ccda.rb +8 -8
- data/lib/health-data-standards/export/green_c32/entry.rb +8 -5
- data/lib/health-data-standards/export/green_c32/export_generator.rb +1 -1
- data/lib/health-data-standards/export/green_c32/record.rb +10 -7
- data/lib/health-data-standards/export/hdata/metadata.rb +7 -6
- data/lib/health-data-standards/export/helper/cat1_view_helper.rb +133 -0
- data/lib/health-data-standards/export/helper/gc32_view_helper.rb +39 -0
- data/lib/health-data-standards/export/helper/html_view_helper.rb +23 -0
- data/lib/health-data-standards/export/html.rb +22 -10
- data/lib/health-data-standards/export/qrda/entry_template_resolver.rb +31 -0
- data/lib/health-data-standards/export/qrda/hqmf-qrda-oids.json +638 -0
- data/lib/health-data-standards/export/rendering_context.rb +37 -3
- data/lib/health-data-standards/export/template_helper.rb +20 -23
- data/lib/health-data-standards/export/view_helper.rb +8 -42
- data/lib/health-data-standards/import/bundle/importer.rb +148 -0
- data/lib/health-data-standards/import/c32/care_goal_importer.rb +14 -26
- data/lib/health-data-standards/import/c32/condition_importer.rb +12 -51
- data/lib/health-data-standards/import/c32/immunization_importer.rb +9 -27
- data/lib/health-data-standards/import/c32/insurance_provider_importer.rb +24 -21
- data/lib/health-data-standards/import/c32/patient_importer.rb +27 -34
- data/lib/health-data-standards/import/cat1/diagnosis_active_importer.rb +19 -0
- data/lib/health-data-standards/import/cat1/diagnosis_inactive_importer.rb +19 -0
- data/lib/health-data-standards/import/cat1/diagnostic_study_order_importer.rb +24 -0
- data/lib/health-data-standards/import/cat1/encounter_order_importer.rb +24 -0
- data/lib/health-data-standards/import/cat1/entry_package.rb +25 -0
- data/lib/health-data-standards/import/cat1/gestational_age_importer.rb +42 -0
- data/lib/health-data-standards/import/cat1/lab_order_importer.rb +24 -0
- data/lib/health-data-standards/import/cat1/medication_dispensed_importer.rb +13 -0
- data/lib/health-data-standards/import/cat1/patient_importer.rb +104 -0
- data/lib/health-data-standards/import/cat1/procedure_intolerance_importer.rb +13 -0
- data/lib/health-data-standards/import/cat1/procedure_order_importer.rb +38 -0
- data/lib/health-data-standards/import/cat1/tobacco_use_importer.rb +19 -0
- data/lib/health-data-standards/import/ccda/allergy_importer.rb +2 -8
- data/lib/health-data-standards/import/ccda/care_goal_importer.rb +1 -1
- data/lib/health-data-standards/import/ccda/condition_importer.rb +2 -3
- data/lib/health-data-standards/import/ccda/encounter_importer.rb +2 -5
- data/lib/health-data-standards/import/ccda/immunization_importer.rb +1 -3
- data/lib/health-data-standards/import/ccda/insurance_provider_importer.rb +1 -1
- data/lib/health-data-standards/import/ccda/medical_equipment_importer.rb +2 -4
- data/lib/health-data-standards/import/ccda/medication_importer.rb +2 -4
- data/lib/health-data-standards/import/ccda/patient_importer.rb +1 -1
- data/lib/health-data-standards/import/ccda/procedure_importer.rb +2 -6
- data/lib/health-data-standards/import/ccda/result_importer.rb +2 -5
- data/lib/health-data-standards/import/ccda/vital_sign_importer.rb +2 -3
- data/lib/health-data-standards/import/cda/allergy_importer.rb +32 -0
- data/lib/health-data-standards/import/cda/condition_importer.rb +51 -0
- data/lib/health-data-standards/import/{c32 → cda}/encounter_importer.rb +9 -35
- data/lib/health-data-standards/import/cda/entry_finder.rb +22 -0
- data/lib/health-data-standards/import/{c32 → cda}/locatable_import_utils.rb +2 -3
- data/lib/health-data-standards/import/cda/medical_equipment_importer.rb +24 -0
- data/lib/health-data-standards/import/{c32 → cda}/medication_importer.rb +13 -15
- data/lib/health-data-standards/import/cda/narrative_reference_handler.rb +35 -0
- data/lib/health-data-standards/import/{c32 → cda}/organization_importer.rb +1 -1
- data/lib/health-data-standards/import/cda/procedure_importer.rb +35 -0
- data/lib/health-data-standards/import/{c32 → cda}/provider_importer.rb +4 -8
- data/lib/health-data-standards/import/cda/result_importer.rb +31 -0
- data/lib/health-data-standards/import/{c32 → cda}/section_importer.rb +26 -48
- data/lib/health-data-standards/import/{c32 → cda}/vital_sign_importer.rb +2 -3
- data/lib/health-data-standards/import/green_c32/section_importer.rb +8 -6
- data/lib/health-data-standards/import/provider_import_utils.rb +2 -2
- data/lib/health-data-standards/models/address.rb +1 -1
- data/lib/health-data-standards/models/condition.rb +7 -6
- data/lib/health-data-standards/models/cqm/bundle.rb +45 -0
- data/lib/health-data-standards/models/cqm/measure.rb +36 -0
- data/lib/health-data-standards/models/guarantor.rb +1 -0
- data/lib/health-data-standards/models/insurance_provider.rb +2 -0
- data/lib/health-data-standards/models/order_information.rb +2 -0
- data/lib/health-data-standards/models/record.rb +6 -5
- data/lib/health-data-standards/models/svs/value_set.rb +1 -1
- data/lib/health-data-standards/railtie.rb +11 -0
- data/lib/health-data-standards/tasks/bundle.rake +107 -0
- data/lib/health-data-standards/util/code_system_helper.rb +9 -1
- data/lib/hqmf-generator/attribute.xml.erb +11 -0
- data/lib/hqmf-generator/characteristic_criteria.xml.erb +21 -0
- data/lib/hqmf-generator/code.xml.erb +13 -0
- data/lib/hqmf-generator/condition_criteria.xml.erb +22 -0
- data/lib/hqmf-generator/derivation.xml.erb +6 -0
- data/lib/hqmf-generator/description.xml.erb +1 -0
- data/lib/hqmf-generator/document.xml.erb +63 -0
- data/lib/hqmf-generator/effective_time.xml.erb +4 -0
- data/lib/hqmf-generator/encounter_criteria.xml.erb +21 -0
- data/lib/hqmf-generator/field.xml.erb +28 -0
- data/lib/hqmf-generator/hqmf-generator.rb +292 -0
- data/lib/hqmf-generator/observation_criteria.xml.erb +25 -0
- data/lib/hqmf-generator/population_criteria.xml.erb +23 -0
- data/lib/hqmf-generator/precondition.xml.erb +14 -0
- data/lib/hqmf-generator/procedure_criteria.xml.erb +22 -0
- data/lib/hqmf-generator/reason.xml.erb +3 -0
- data/lib/hqmf-generator/reference.xml.erb +3 -0
- data/lib/hqmf-generator/source.xml.erb +6 -0
- data/lib/hqmf-generator/specific_occurrence.xml.erb +7 -0
- data/lib/hqmf-generator/subset.xml.erb +8 -0
- data/lib/hqmf-generator/substance_criteria.xml.erb +26 -0
- data/lib/hqmf-generator/supply_criteria.xml.erb +26 -0
- data/lib/hqmf-generator/template_id.xml.erb +5 -0
- data/lib/hqmf-generator/temporal_relationship.xml.erb +6 -0
- data/lib/hqmf-generator/value.xml.erb +24 -0
- data/lib/hqmf-generator/variable_criteria.xml.erb +12 -0
- data/lib/hqmf-model/attribute.rb +35 -0
- data/lib/hqmf-model/data_criteria.json +1123 -0
- data/lib/hqmf-model/data_criteria.rb +344 -0
- data/lib/hqmf-model/document.rb +178 -0
- data/lib/hqmf-model/population_criteria.rb +96 -0
- data/lib/hqmf-model/precondition.rb +91 -0
- data/lib/hqmf-model/types.rb +319 -0
- data/lib/hqmf-model/utilities.rb +52 -0
- data/lib/hqmf-parser.rb +56 -0
- data/lib/hqmf-parser/1.0/attribute.rb +68 -0
- data/lib/hqmf-parser/1.0/comparison.rb +34 -0
- data/lib/hqmf-parser/1.0/data_criteria.rb +92 -0
- data/lib/hqmf-parser/1.0/data_criteria_oid_xpath.json +91 -0
- data/lib/hqmf-parser/1.0/document.rb +203 -0
- data/lib/hqmf-parser/1.0/expression.rb +58 -0
- data/lib/hqmf-parser/1.0/observation.rb +61 -0
- data/lib/hqmf-parser/1.0/population_criteria.rb +75 -0
- data/lib/hqmf-parser/1.0/precondition.rb +89 -0
- data/lib/hqmf-parser/1.0/range.rb +65 -0
- data/lib/hqmf-parser/1.0/restriction.rb +160 -0
- data/lib/hqmf-parser/1.0/utilities.rb +41 -0
- data/lib/hqmf-parser/2.0/data_criteria.rb +319 -0
- data/lib/hqmf-parser/2.0/document.rb +165 -0
- data/lib/hqmf-parser/2.0/population_criteria.rb +53 -0
- data/lib/hqmf-parser/2.0/precondition.rb +44 -0
- data/lib/hqmf-parser/2.0/types.rb +223 -0
- data/lib/hqmf-parser/2.0/utilities.rb +30 -0
- data/lib/hqmf-parser/converter/pass1/data_criteria_converter.rb +252 -0
- data/lib/hqmf-parser/converter/pass1/document_converter.rb +185 -0
- data/lib/hqmf-parser/converter/pass1/population_criteria_converter.rb +165 -0
- data/lib/hqmf-parser/converter/pass1/precondition_converter.rb +173 -0
- data/lib/hqmf-parser/converter/pass1/precondition_extractor.rb +188 -0
- data/lib/hqmf-parser/converter/pass1/simple_data_criteria.rb +26 -0
- data/lib/hqmf-parser/converter/pass1/simple_operator.rb +89 -0
- data/lib/hqmf-parser/converter/pass1/simple_population_criteria.rb +10 -0
- data/lib/hqmf-parser/converter/pass1/simple_precondition.rb +51 -0
- data/lib/hqmf-parser/converter/pass1/simple_restriction.rb +64 -0
- data/lib/hqmf-parser/converter/pass2/comparison_converter.rb +112 -0
- data/lib/hqmf-parser/converter/pass2/operator_converter.rb +102 -0
- data/lib/hqmf-parser/parser.rb +54 -0
- data/lib/hqmf-parser/value_sets/value_set_parser.rb +241 -0
- data/lib/util/counter.rb +20 -0
- data/templates/{_allergies.c32.erb → c32/_allergies.c32.erb} +0 -0
- data/templates/{_allergies_no_current.c32.erb → c32/_allergies_no_current.c32.erb} +0 -0
- data/templates/{_care_goals.c32.erb → c32/_care_goals.c32.erb} +0 -0
- data/templates/{_code_with_reference.c32.erb → c32/_code_with_reference.c32.erb} +0 -0
- data/templates/{_conditions.c32.erb → c32/_conditions.c32.erb} +0 -0
- data/templates/{_conditions_no_current.c32.erb → c32/_conditions_no_current.c32.erb} +0 -0
- data/templates/{_encounters.c32.erb → c32/_encounters.c32.erb} +0 -0
- data/templates/{_immunizations.c32.erb → c32/_immunizations.c32.erb} +0 -0
- data/templates/{_medical_equipment.c32.erb → c32/_medical_equipment.c32.erb} +0 -0
- data/templates/{_medications.c32.erb → c32/_medications.c32.erb} +0 -0
- data/templates/{_medications_no_current.c32.erb → c32/_medications_no_current.c32.erb} +0 -0
- data/templates/{_narrative_block.c32.erb → c32/_narrative_block.c32.erb} +0 -0
- data/templates/{_procedures.c32.erb → c32/_procedures.c32.erb} +0 -0
- data/templates/{_results.c32.erb → c32/_results.c32.erb} +0 -0
- data/templates/{_social_history.c32.erb → c32/_social_history.c32.erb} +0 -0
- data/templates/{_vital_signs.c32.erb → c32/_vital_signs.c32.erb} +0 -0
- data/templates/{show.c32.erb → c32/show.c32.erb} +0 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.22.4.85.cat1.erb +18 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.1.cat1.erb +14 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.101.cat1.erb +25 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.103.cat1.erb +12 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.105.cat1.erb +60 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.11.cat1.erb +41 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.12.cat1.erb +50 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.13.cat1.erb +37 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.14.cat1.erb +35 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +22 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.18.cat1.erb +21 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.2.cat1.erb +28 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.20.cat1.erb +20 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.22.cat1.erb +21 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.23.cat1.erb +71 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.28.cat1.erb +20 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.3.cat1.erb +24 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +20 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.32.cat1.erb +15 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.34.cat1.erb +58 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +20 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.38.cat1.erb +16 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.4.cat1.erb +27 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.40.cat1.erb +17 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.41.cat1.erb +38 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.42.cat1.erb +38 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.43.cat1.erb +24 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.44.cat1.erb +24 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.45.cat1.erb +26 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.46.cat1.erb +30 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +26 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.51.cat1.erb +13 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.54.cat1.erb +16 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.55.cat1.erb +10 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.57.cat1.erb +19 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.59.cat1.erb +17 -0
- data/templates/cat1/_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 +23 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.64.cat1.erb +29 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.66.cat1.erb +34 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.69.cat1.erb +23 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.7.cat1.erb +30 -0
- data/templates/cat1/_2.16.840.1.113883.10.20.24.3.76.cat1.erb +32 -0
- data/templates/cat1/_measures.cat1.erb +66 -0
- data/templates/cat1/_medication_details.cat1.erb +9 -0
- data/templates/cat1/_ordinality.cat1.erb +4 -0
- data/templates/cat1/_patient_data.cat1.erb +14 -0
- data/templates/cat1/_reason.cat1.erb +16 -0
- data/templates/cat1/_record_target.cat1.erb +39 -0
- data/templates/cat1/_reporting_parameters.cat1.erb +24 -0
- data/templates/cat1/_result_value.cat1.erb +16 -0
- data/templates/cat1/show.cat1.erb +125 -0
- data/templates/{_address.gc32.erb → gc32/_address.gc32.erb} +1 -1
- data/templates/gc32/_advance_directive.gc32.erb +5 -0
- data/templates/gc32/_allergy.gc32.erb +12 -0
- data/templates/{_care_goal.gc32.erb → gc32/_care_goal.gc32.erb} +1 -1
- data/templates/gc32/_condition.gc32.erb +10 -0
- data/templates/gc32/_encounter.gc32.erb +28 -0
- data/templates/gc32/_entry.gc32.erb +3 -0
- data/templates/gc32/_entry_attributes.gc32.erb +10 -0
- data/templates/gc32/_immunization.gc32.erb +9 -0
- data/templates/gc32/_insurance_provider.gc32.erb +28 -0
- data/templates/gc32/_medical_equipment.gc32.erb +6 -0
- data/templates/gc32/_medication.gc32.erb +91 -0
- data/templates/{_name.gc32.erb → gc32/_name.gc32.erb} +0 -0
- data/templates/gc32/_organization.gc32.erb +10 -0
- data/templates/gc32/_person_attributes.gc32.erb +7 -0
- data/templates/gc32/_procedure.gc32.erb +9 -0
- data/templates/gc32/_provider.gc32.erb +9 -0
- data/templates/gc32/_result.gc32.erb +12 -0
- data/templates/gc32/_social_history.gc32.erb +6 -0
- data/templates/{_support.gc32.erb → gc32/_support.gc32.erb} +4 -3
- data/templates/gc32/_telecom.gc32.erb +1 -0
- data/templates/gc32/_vital_sign.gc32.erb +4 -0
- data/templates/{record.gc32.erb → gc32/record.gc32.erb} +26 -10
- data/templates/html/_entries_by_encounter.html.erb +2 -2
- data/templates/html/_entries_by_section.html.erb +1 -1
- data/templates/html/_entry.html.erb +16 -21
- data/templates/html/_header.html.erb +1 -1
- data/templates/html/_section.html.erb +1 -1
- data/templates/html/show.html.erb +23 -2
- data/templates/metadata.hdata.erb +3 -3
- metadata +282 -54
- data/lib/health-data-standards/import/c32/allergy_importer.rb +0 -47
- data/lib/health-data-standards/import/c32/medical_equipment_importer.rb +0 -45
- data/lib/health-data-standards/import/c32/procedure_importer.rb +0 -62
- data/lib/health-data-standards/import/c32/result_importer.rb +0 -56
- data/templates/_advance_directive.gc32.erb +0 -8
- data/templates/_allergy.gc32.erb +0 -23
- data/templates/_condition.gc32.erb +0 -9
- data/templates/_encounter.gc32.erb +0 -26
- data/templates/_entry.gc32.erb +0 -14
- data/templates/_immunization.gc32.erb +0 -11
- data/templates/_insurance_provider.gc32.erb +0 -0
- data/templates/_medical_equipment.gc32.erb +0 -7
- data/templates/_medication.gc32.erb +0 -72
- data/templates/_organization.gc32.erb +0 -10
- data/templates/_procedure.gc32.erb +0 -10
- data/templates/_provider.gc32.erb +0 -19
- data/templates/_result.gc32.erb +0 -16
- data/templates/_social_history.gc32.erb +0 -8
- data/templates/_telecom.gc32.erb +0 -1
- data/templates/_vital_sign.gc32.erb +0 -7
|
@@ -1,14 +1,48 @@
|
|
|
1
|
-
require 'ostruct'
|
|
2
|
-
|
|
3
1
|
module HealthDataStandards
|
|
4
2
|
module Export
|
|
3
|
+
# Used to actually render stuff. A RenderingContext needs to be set up with
|
|
4
|
+
# a template helper and may be provided with extensions.
|
|
5
|
+
#
|
|
6
|
+
# :call-seq:
|
|
7
|
+
# template_helper = HealthDataStandards::Export::TemplateHelper.new('cat1', 'cat1')
|
|
8
|
+
# rendering_context = HealthDataStandards::Export::RenderingContext.new
|
|
9
|
+
# rendering_context.template_helper = template_helper
|
|
10
|
+
# rendering_context.extensions = [HealthDataStandards::Export::Helper::Cat1ViewHelper]
|
|
11
|
+
#
|
|
12
|
+
# In this case, a RenderingContext is being set up to generate Category 1 files. It is
|
|
13
|
+
# passed a template helper to finds the correct ERb templates to render from. It is also
|
|
14
|
+
# given an extension. This is just a Ruby Module which will have its methods exposed to
|
|
15
|
+
# the templates. RenderingContext will assume that extensions is an Array and will include
|
|
16
|
+
# multiple extensions if more than one is provided.
|
|
5
17
|
class RenderingContext < OpenStruct
|
|
6
|
-
include TemplateHelper
|
|
7
18
|
include ViewHelper
|
|
19
|
+
attr_accessor :template_helper, :extensions
|
|
8
20
|
|
|
9
21
|
def my_binding
|
|
10
22
|
binding
|
|
11
23
|
end
|
|
24
|
+
|
|
25
|
+
def render(params)
|
|
26
|
+
erb = nil
|
|
27
|
+
if params[:template]
|
|
28
|
+
erb = @template_helper.template(params[:template])
|
|
29
|
+
elsif params[:partial]
|
|
30
|
+
erb = @template_helper.partial(params[:partial])
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
locals = params[:locals]
|
|
34
|
+
locals ||= {}
|
|
35
|
+
rendering_context = RenderingContext.new(locals)
|
|
36
|
+
rendering_context.template_helper = @template_helper
|
|
37
|
+
if @extensions.present?
|
|
38
|
+
rendering_context.extensions = @extensions
|
|
39
|
+
@extensions.each do |extension|
|
|
40
|
+
rendering_context.extend(extension)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
eruby = Erubis::EscapedEruby.new(erb) # TODO: cache these
|
|
44
|
+
eruby.result(rendering_context.my_binding)
|
|
45
|
+
end
|
|
12
46
|
end
|
|
13
47
|
end
|
|
14
48
|
end
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
module HealthDataStandards
|
|
2
2
|
module Export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
# Class that finds ERb templates. Here is how it can be configured:
|
|
4
|
+
# [template_format] What format (C32, CCDA, etc) are we looking for. This will cause
|
|
5
|
+
# the TemplateHelper to look for template_name.template_format.erb
|
|
6
|
+
# [template_subdir] The sub directory where templates live. If none is provided, it
|
|
7
|
+
# will look for templates in the root of the template_directory
|
|
8
|
+
# [template_directory] The root directory to look in for templates. By default, it
|
|
9
|
+
# is in the template folder of this gem. It can be handy to
|
|
10
|
+
# provide a different directory if you want to use this class
|
|
11
|
+
# outside of the HDS gem
|
|
12
|
+
class TemplateHelper
|
|
13
|
+
def initialize(template_format, template_subdir = nil, template_directory = nil)
|
|
14
|
+
@template_format = template_format
|
|
15
|
+
@template_directory = template_directory
|
|
16
|
+
@template_subdir = template_subdir
|
|
17
|
+
end
|
|
7
18
|
|
|
8
19
|
def template_root
|
|
9
20
|
@template_directory ||= File.dirname(__FILE__)
|
|
@@ -15,31 +26,17 @@ module HealthDataStandards
|
|
|
15
26
|
end
|
|
16
27
|
end
|
|
17
28
|
|
|
29
|
+
# Returns the raw ERb for the template_name provided. This method will look in
|
|
30
|
+
# template_directory/template_subdir/template_name.template_format.erb
|
|
18
31
|
def template(template_name)
|
|
19
|
-
File.read(File.join(template_root, "#{template_name}.#{
|
|
32
|
+
File.read(File.join(template_root, "#{template_name}.#{@template_format}.erb"))
|
|
20
33
|
end
|
|
21
34
|
|
|
35
|
+
# Basically the same template, but prepends an underscore to the template name
|
|
36
|
+
# to mimic the Rails convention for template fragments
|
|
22
37
|
def partial(partial_name)
|
|
23
38
|
template("_#{partial_name}")
|
|
24
39
|
end
|
|
25
|
-
|
|
26
|
-
def render(params)
|
|
27
|
-
erb = nil
|
|
28
|
-
if params[:template]
|
|
29
|
-
erb = template(params[:template])
|
|
30
|
-
elsif params[:partial]
|
|
31
|
-
erb = partial(params[:partial])
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
locals = params[:locals]
|
|
35
|
-
locals ||= {}
|
|
36
|
-
rendering_context = RenderingContext.new(locals)
|
|
37
|
-
rendering_context.template_format = self.template_format
|
|
38
|
-
rendering_context.template_subdir = self.template_subdir
|
|
39
|
-
rendering_context.template_directory = self.template_directory
|
|
40
|
-
eruby = Erubis::EscapedEruby.new(erb)
|
|
41
|
-
eruby.result(rendering_context.my_binding)
|
|
42
|
-
end
|
|
43
40
|
end
|
|
44
41
|
end
|
|
45
42
|
end
|
|
@@ -4,18 +4,22 @@ module HealthDataStandards
|
|
|
4
4
|
def code_display(entry, options={})
|
|
5
5
|
options['tag_name'] ||= 'code'
|
|
6
6
|
options['attribute'] ||= :codes
|
|
7
|
+
options['exclude_null_flavor'] ||= false
|
|
7
8
|
code_string = nil
|
|
8
9
|
preferred_code = entry.preferred_code(options['preferred_code_sets'], options['attribute'])
|
|
9
10
|
if preferred_code
|
|
10
11
|
code_system_oid = HealthDataStandards::Util::CodeSystemHelper.oid_for_code_system(preferred_code['code_set'])
|
|
11
12
|
code_string = "<#{options['tag_name']} code=\"#{preferred_code['code']}\" codeSystem=\"#{code_system_oid}\" #{options['extra_content']}>"
|
|
12
13
|
else
|
|
13
|
-
code_string = "<#{options['tag_name']}
|
|
14
|
+
code_string = "<#{options['tag_name']} "
|
|
15
|
+
code_string += "nullFlavor=\"UNK\" " unless options["exclude_null_flavor"]
|
|
16
|
+
code_string += "#{options['extra_content']}>"
|
|
14
17
|
end
|
|
15
18
|
|
|
16
|
-
code_string += "<originalText>#{ERB::Util.html_escape entry.description}</originalText>" if entry.respond_to?(:description)
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
|
|
21
|
+
if options["attribute"] == :codes && entry.respond_to?(:translation_codes)
|
|
22
|
+
code_string += "<originalText>#{ERB::Util.html_escape entry.description}</originalText>" if entry.respond_to?(:description)
|
|
19
23
|
entry.translation_codes(options['preferred_code_sets']).each do |translation|
|
|
20
24
|
code_string += "<translation code=\"#{translation['code']}\" codeSystem=\"#{HealthDataStandards::Util::CodeSystemHelper.oid_for_code_system(translation['code_set'])}\"/>\n"
|
|
21
25
|
end
|
|
@@ -24,20 +28,7 @@ module HealthDataStandards
|
|
|
24
28
|
code_string += "</#{options['tag_name']}>"
|
|
25
29
|
code_string
|
|
26
30
|
end
|
|
27
|
-
|
|
28
|
-
def gc32_effective_time(entry)
|
|
29
|
-
if entry.time
|
|
30
|
-
"<effectiveTime value=\"#{Time.at(entry.time).to_formatted_s(:number)}\" />"
|
|
31
|
-
elsif entry.start_time || entry.end_time
|
|
32
|
-
time = "<effectiveTime>"
|
|
33
|
-
time += "<start value=\"#{Time.at(entry.start_time).to_formatted_s(:number)}\" />" if entry.start_time
|
|
34
|
-
time += "<end value=\"#{Time.at(entry.end_time).to_formatted_s(:number)}\" />" if entry.end_time
|
|
35
|
-
time += "</effectiveTime>"
|
|
36
|
-
else
|
|
37
|
-
"<effectiveTime />"
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
31
|
+
|
|
41
32
|
def status_code_for(entry)
|
|
42
33
|
case entry.status.to_s.downcase
|
|
43
34
|
when 'active'
|
|
@@ -58,16 +49,6 @@ module HealthDataStandards
|
|
|
58
49
|
end
|
|
59
50
|
end
|
|
60
51
|
|
|
61
|
-
|
|
62
|
-
def quantity_display(value, tag_name="value")
|
|
63
|
-
return unless value
|
|
64
|
-
if value.respond_to?(:scalar)
|
|
65
|
-
"<#{tag_name} value=\"#{value.scalar}\" units=\"#{value.units}\" />"
|
|
66
|
-
else
|
|
67
|
-
"<#{tag_name} value=\"#{value['value']}\" units=\"#{value['unit']}\" />"
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
52
|
def time_if_not_nil(*args)
|
|
72
53
|
args.compact.map {|t| Time.at(t).utc}.first
|
|
73
54
|
end
|
|
@@ -84,21 +65,6 @@ module HealthDataStandards
|
|
|
84
65
|
return ["true","false"].include? (str || "").downcase
|
|
85
66
|
end
|
|
86
67
|
|
|
87
|
-
def decode_hqmf_section(section, oid)
|
|
88
|
-
if oid
|
|
89
|
-
HealthDataStandards::Util::HQMFTemplateHelper.definition_for_template_id(oid)['definition'].pluralize.to_sym
|
|
90
|
-
else
|
|
91
|
-
section
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
def decode_hqmf_status(status, oid)
|
|
95
|
-
if oid
|
|
96
|
-
HealthDataStandards::Util::HQMFTemplateHelper.definition_for_template_id(oid)['status']
|
|
97
|
-
else
|
|
98
|
-
status
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
68
|
def convert_field_to_hash(field, codes)
|
|
103
69
|
if (codes.is_a? Hash)
|
|
104
70
|
clean_hash = {}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
module HealthDataStandards
|
|
2
|
+
module Import
|
|
3
|
+
module Bundle
|
|
4
|
+
|
|
5
|
+
class Importer
|
|
6
|
+
COLLECTION_NAMES = ["bundles", "records", "measures", "selected_measures", "patient_cache", "query_cache", "system.js"]
|
|
7
|
+
DEFAULTS = {clear_db: false,
|
|
8
|
+
type: nil,
|
|
9
|
+
delete_existing: false,
|
|
10
|
+
update_measures: true,
|
|
11
|
+
clear_collections: COLLECTION_NAMES
|
|
12
|
+
}
|
|
13
|
+
# Import a quality bundle into the database. This includes metadata, measures, test patients, supporting JS libraries, and expected results.
|
|
14
|
+
#
|
|
15
|
+
# @param [File] zip The bundle zip file.
|
|
16
|
+
# @param [String] Type of measures to import, either 'ep', 'eh' or nil for all
|
|
17
|
+
# @param [Boolean] keep_existing If true, delete all current collections related to patients and measures.
|
|
18
|
+
def self.import(zip, options={})
|
|
19
|
+
options = DEFAULTS.merge(options)
|
|
20
|
+
bundle_versions = Hash[* HealthDataStandards::CQM::Bundle.where({}).collect{|b| [b._id, b.version]}.flatten]
|
|
21
|
+
# Unpack content from the bundle.
|
|
22
|
+
bundle_contents = unpack_bundle_contents(zip, options[:type])
|
|
23
|
+
bundle = HealthDataStandards::CQM::Bundle.new( JSON.parse(bundle_contents[:bundle]))
|
|
24
|
+
|
|
25
|
+
if bundle_versions.invert[bundle.version] && !(options[:delete_existing] || options[:clear_db])
|
|
26
|
+
raise "A bundle with version #{bundle.version} already exists in the database. "
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
drop_collections(COLLECTION_NAMES+(options[:clear_collections]||[])) if options[:clear_db]
|
|
30
|
+
HealthDataStandards::CQM::Bundle.where({:version => bundle.version}).each {|b| b.delete}
|
|
31
|
+
# Store all JS libraries.
|
|
32
|
+
bundle_contents[:extensions].each do |key, contents|
|
|
33
|
+
save_system_js_fn(key, contents)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Store the bundle metadata.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
unless bundle.save
|
|
40
|
+
raise bundle.errors.full_messages.join(",")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
bundle_id = bundle.id
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# Store all measures.
|
|
47
|
+
bundle_contents[:measures].each do |key, contents|
|
|
48
|
+
json = JSON.parse(contents, {:max_nesting => 100})
|
|
49
|
+
measure = json.clone
|
|
50
|
+
# measure = HealthDataStandards::CQM::Measure.new(json)
|
|
51
|
+
measure['bundle_id'] = bundle_id
|
|
52
|
+
Mongoid.default_session["measures"].insert(measure)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
if options[:update_measures]
|
|
56
|
+
Mongoid.default_session["measures"].where({hqmf_id: measure["hqmf_id"], sub_id: measure["sub_id"]}).each do |m|
|
|
57
|
+
b = HealthDataStandards::CQM::Bundle.find(m["bundle_id"])
|
|
58
|
+
if b.version < bundle.version
|
|
59
|
+
m.merge!(json)
|
|
60
|
+
Mongoid.default_session["measures"].where({"_id" => m["_id"]}).update(m)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
bundle_contents[:patients].each do |key, contents|
|
|
69
|
+
patient = Record.new( JSON.parse(contents, {:max_nesting => 100}))
|
|
70
|
+
patient['bundle_id'] = bundle_id
|
|
71
|
+
patient.save
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
bundle_contents[:valuesets].each do |key, contents|
|
|
75
|
+
json = JSON.parse(contents, {:max_nesting => 100})
|
|
76
|
+
vs = HealthDataStandards::SVS::ValueSet.new(json)
|
|
77
|
+
vs['bundle_id'] = bundle_id
|
|
78
|
+
vs.save
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Store the expected results into the query and patient caches.
|
|
82
|
+
bundle_contents[:results].each do |name, contents|
|
|
83
|
+
collection = name == "by_patient" ? "patient_cache" : "query_cache"
|
|
84
|
+
contents = JSON.parse(contents, {:max_nesting => 100})
|
|
85
|
+
|
|
86
|
+
contents.each {|document|
|
|
87
|
+
document['bundle_id'] = bundle_id
|
|
88
|
+
Mongoid.default_session[collection].insert(document)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
bundle
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Delete a list of collections. By default, this function drops all of collections related to measures and patients.
|
|
97
|
+
#
|
|
98
|
+
# @param [Array] collection_names Optionally, an array of collection names to be dropped.
|
|
99
|
+
def self.drop_collections(collection_names=[])
|
|
100
|
+
collection_names = COLLECTION_NAMES if collection_names.empty?
|
|
101
|
+
collection_names.each {|collection| Mongoid.default_session[collection].drop}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Save a javascript function into Mongo's system.js collection for measure execution.
|
|
105
|
+
#
|
|
106
|
+
# @param [String] name The name by which the function will be referred.
|
|
107
|
+
# @param [String] fn The body of the function being saved.
|
|
108
|
+
def self.save_system_js_fn(name, fn)
|
|
109
|
+
fn = "function () {\n #{fn} \n }"
|
|
110
|
+
Mongoid.default_session['system.js'].find('_id' => name).upsert(
|
|
111
|
+
{
|
|
112
|
+
"_id" => name,
|
|
113
|
+
"value" => Moped::BSON::Code.new(fn)
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# A utility function for finding files in a bundle. Strip a file path of it's extension and just give the filename.
|
|
119
|
+
#
|
|
120
|
+
# @param [String] original A file path.
|
|
121
|
+
# @param [String] extension A file extension.
|
|
122
|
+
# @return The filename at the end of the original String path with the extension removed. e.g. "/boo/urns.html" -> "urns"
|
|
123
|
+
def self.entry_key(original, extension)
|
|
124
|
+
original.split('/').last.gsub(".#{extension}", '')
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def self.unpack_bundle_contents(zip, type = nil)
|
|
128
|
+
bundle_contents = { bundle: nil, measures: {}, patients: {}, extensions: {}, results: {}, valuesets: {} }
|
|
129
|
+
Zip::ZipFile.open(zip.path) do |zipfile|
|
|
130
|
+
zipfile.entries.each do |entry|
|
|
131
|
+
bundle_contents[:bundle] = zipfile.read(entry.name) if entry.name.include? "bundle"
|
|
132
|
+
if type.nil? || entry.name.match(Regexp.new("/#{type}/"))
|
|
133
|
+
bundle_contents[:measures][entry_key(entry.name, "json")] = zipfile.read(entry.name) if entry.name.match /^measures.*\.json$/
|
|
134
|
+
bundle_contents[:patients][entry_key(entry.name, "json")] = zipfile.read(entry.name) if entry.name.match /^patients.*\.json$/ # Only need to import one of the formats
|
|
135
|
+
bundle_contents[:results][entry_key(entry.name,"json")] = zipfile.read(entry.name) if entry.name.match /^results.*\.json/
|
|
136
|
+
end
|
|
137
|
+
bundle_contents[:extensions][entry_key(entry.name,"js")] = zipfile.read(entry.name) if entry.name.match /^library_functions.*\.js/
|
|
138
|
+
|
|
139
|
+
bundle_contents[:valuesets][entry_key(entry.name,"json")] = zipfile.read(entry.name) if entry.name.match /^value_sets.*\.json/
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
bundle_contents
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
@@ -1,38 +1,26 @@
|
|
|
1
1
|
module HealthDataStandards
|
|
2
2
|
module Import
|
|
3
3
|
module C32
|
|
4
|
-
class CareGoalImporter < SectionImporter
|
|
4
|
+
class CareGoalImporter < CDA::SectionImporter
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
7
|
-
|
|
6
|
+
def initialize(entry_finder=CDA::EntryFinder.new("//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.124']/cda:entry/cda:*[cda:templateId/@root='2.16.840.1.113883.10.20.1.25']"))
|
|
7
|
+
super(entry_finder)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
when "
|
|
17
|
-
|
|
18
|
-
when "substanceAdministration" then MedicationImporter.new
|
|
19
|
-
when "encounter" then EncounterImporter.new
|
|
20
|
-
when "procedure" then ProcedureImporter.new
|
|
21
|
-
else SectionImporter.new(nil) #don't need entry xpath, since we already have the entry
|
|
10
|
+
def create_entry(goal_element, nrh = CDA::NarrativeReferenceHandler.new)
|
|
11
|
+
importer = case goal_element.name
|
|
12
|
+
when "observation" then CDA::ResultImporter.new
|
|
13
|
+
when "supply" then CDA::MedicalEquipment.new
|
|
14
|
+
when "substanceAdministration" then CDA::MedicationImporter.new
|
|
15
|
+
when "encounter" then CDA::EncounterImporter.new
|
|
16
|
+
when "procedure" then CDA::ProcedureImporter.new
|
|
17
|
+
else CDA::SectionImporter.new(nil) #don't need entry xpath, since we already have the entry
|
|
22
18
|
end
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
entry = importer.create_entry(goal_element, nrh)
|
|
21
|
+
extract_negation(goal_element, entry)
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if @check_for_usable
|
|
30
|
-
goal_list << entry if entry.usable?
|
|
31
|
-
else
|
|
32
|
-
goal_list << entry
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
goal_list
|
|
23
|
+
entry
|
|
36
24
|
end
|
|
37
25
|
end
|
|
38
26
|
end
|
|
@@ -1,68 +1,29 @@
|
|
|
1
1
|
module HealthDataStandards
|
|
2
2
|
module Import
|
|
3
3
|
module C32
|
|
4
|
-
class ConditionImporter <
|
|
4
|
+
class ConditionImporter < CDA::ConditionImporter
|
|
5
5
|
|
|
6
6
|
def initialize
|
|
7
|
-
|
|
8
|
-
@
|
|
9
|
-
@
|
|
10
|
-
@
|
|
11
|
-
@description_xpath = "./cda:text/cda:reference[@value]"
|
|
12
|
-
@provider_xpath = "./cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.1.27']/cda:performer"
|
|
13
|
-
@cod_xpath = "./cda:entryRelationship[@typeCode='CAUS']/cda:observation/cda:code[@code='419620001']"
|
|
14
|
-
@priority_xpath = "../cda:sequenceNumber"
|
|
7
|
+
super
|
|
8
|
+
@death_xpath = "./cda:entryRelationship[@typeCode='CAUS']/cda:observation"
|
|
9
|
+
@cod_xpath = "#{@death_xpath}/cda:code[@code='419620001']"
|
|
10
|
+
@time_of_death_xpath = "#{@death_xpath}/cda:effectiveTime/@value"
|
|
15
11
|
end
|
|
16
12
|
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
entry_elements.each do |entry_element|
|
|
23
|
-
condition = Condition.new
|
|
24
|
-
|
|
25
|
-
extract_codes(entry_element, condition)
|
|
26
|
-
extract_dates(entry_element, condition)
|
|
27
|
-
extract_status(entry_element, condition)
|
|
28
|
-
extract_ordinality(entry_element, condition)
|
|
29
|
-
extract_description(entry_element, condition, id_map)
|
|
30
|
-
extract_cause_of_death(entry_element, condition) if @cod_xpath
|
|
31
|
-
extract_type(entry_element, condition)
|
|
32
|
-
extract_negation(entry_element, condition)
|
|
33
|
-
extract_priority(entry_element, condition)
|
|
34
|
-
|
|
35
|
-
if @provider_xpath
|
|
36
|
-
entry_element.xpath(@provider_xpath).each do |provider_element|
|
|
37
|
-
condition.treating_provider << import_actor(provider_element)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
condition_list << condition
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
condition_list
|
|
13
|
+
def create_entry(entry_element, nrh = CDA::NarrativeReferenceHandler.new)
|
|
14
|
+
condition = super
|
|
15
|
+
extract_cause_of_death(entry_element, condition)
|
|
16
|
+
extract_type(entry_element, condition)
|
|
17
|
+
condition
|
|
45
18
|
end
|
|
46
19
|
|
|
47
20
|
private
|
|
48
21
|
|
|
49
|
-
def extract_ordinality(parent_element, entry)
|
|
50
|
-
ordinality_element = parent_element.at_xpath(@ordinality_xpath)
|
|
51
|
-
if ordinality_element
|
|
52
|
-
entry.ordinality = {CodeSystemHelper.code_system_for(ordinality_element['codeSystem']) => [ordinality_element['code']]}
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
22
|
def extract_cause_of_death(entry_element, condition)
|
|
57
23
|
cod = entry_element.at_xpath(@cod_xpath)
|
|
58
24
|
condition.cause_of_death = cod.present?
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def extract_priority(entry_element, condition)
|
|
62
|
-
priority_element = entry_element.at_xpath(@priority_xpath)
|
|
63
|
-
if priority_element
|
|
64
|
-
condition.priority = priority_element['value'].to_i
|
|
65
|
-
end
|
|
25
|
+
time_of_death = entry_element.at_xpath(@time_of_death_xpath)
|
|
26
|
+
condition.time_of_death = HL7Helper.timestamp_to_integer(time_of_death.text) if time_of_death
|
|
66
27
|
end
|
|
67
28
|
|
|
68
29
|
def extract_type(entry_element, condition)
|