health-data-standards 2.2.1 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
module HQMF
|
3
|
+
module Conversion
|
4
|
+
module Utilities
|
5
|
+
def build_hash(source, elements)
|
6
|
+
hash = {}
|
7
|
+
elements.each do |element|
|
8
|
+
value = source.send(element)
|
9
|
+
hash[element] = value unless value.nil?
|
10
|
+
end
|
11
|
+
hash
|
12
|
+
end
|
13
|
+
|
14
|
+
def json_array(elements)
|
15
|
+
return nil if elements.nil?
|
16
|
+
array = []
|
17
|
+
elements.each do |element|
|
18
|
+
if (element.is_a? OpenStruct)
|
19
|
+
array << openstruct_to_json(element)
|
20
|
+
else
|
21
|
+
array << element.to_json
|
22
|
+
end
|
23
|
+
end
|
24
|
+
array.compact!
|
25
|
+
(array.empty?) ? nil : array
|
26
|
+
end
|
27
|
+
|
28
|
+
def openstruct_to_json(element)
|
29
|
+
json = {}
|
30
|
+
element.marshal_dump.each do |key,value|
|
31
|
+
if value.is_a? OpenStruct
|
32
|
+
json[key] = openstruct_to_json(value)
|
33
|
+
elsif (value.class.to_s.split("::").first.start_with? 'HQMF')
|
34
|
+
json[key] = value.to_json
|
35
|
+
else
|
36
|
+
json[key] = value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
json
|
40
|
+
end
|
41
|
+
|
42
|
+
def check_equality(left,right)
|
43
|
+
same = true
|
44
|
+
left.instance_variables.each do |variable|
|
45
|
+
same &&= left.instance_variable_get(variable) == right.instance_variable_get(variable)
|
46
|
+
end
|
47
|
+
same
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/hqmf-parser.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# require
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'pry'
|
4
|
+
require 'json'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'health-data-standards'
|
7
|
+
|
8
|
+
# require_relative
|
9
|
+
require_relative 'util/counter.rb'
|
10
|
+
require_relative 'hqmf-model/utilities.rb'
|
11
|
+
|
12
|
+
require_relative 'hqmf-parser/1.0/utilities'
|
13
|
+
require_relative 'hqmf-parser/1.0/range'
|
14
|
+
require_relative 'hqmf-parser/1.0/document'
|
15
|
+
require_relative 'hqmf-parser/1.0/data_criteria'
|
16
|
+
require_relative 'hqmf-parser/1.0/attribute'
|
17
|
+
require_relative 'hqmf-parser/1.0/population_criteria'
|
18
|
+
require_relative 'hqmf-parser/1.0/observation'
|
19
|
+
require_relative 'hqmf-parser/1.0/precondition'
|
20
|
+
require_relative 'hqmf-parser/1.0/restriction'
|
21
|
+
require_relative 'hqmf-parser/1.0/comparison'
|
22
|
+
require_relative 'hqmf-parser/1.0/expression'
|
23
|
+
|
24
|
+
require_relative 'hqmf-parser/2.0/utilities'
|
25
|
+
require_relative 'hqmf-parser/2.0/types'
|
26
|
+
require_relative 'hqmf-parser/2.0/document'
|
27
|
+
require_relative 'hqmf-parser/2.0/data_criteria'
|
28
|
+
require_relative 'hqmf-parser/2.0/population_criteria'
|
29
|
+
require_relative 'hqmf-parser/2.0/precondition'
|
30
|
+
|
31
|
+
require_relative 'hqmf-model/data_criteria.rb'
|
32
|
+
require_relative 'hqmf-model/document.rb'
|
33
|
+
require_relative 'hqmf-model/population_criteria.rb'
|
34
|
+
require_relative 'hqmf-model/precondition.rb'
|
35
|
+
require_relative 'hqmf-model/types.rb'
|
36
|
+
require_relative 'hqmf-model/attribute.rb'
|
37
|
+
|
38
|
+
require_relative 'hqmf-parser/converter/pass1/document_converter'
|
39
|
+
require_relative 'hqmf-parser/converter/pass1/data_criteria_converter'
|
40
|
+
require_relative 'hqmf-parser/converter/pass1/population_criteria_converter'
|
41
|
+
require_relative 'hqmf-parser/converter/pass1/precondition_converter'
|
42
|
+
require_relative 'hqmf-parser/converter/pass1/precondition_extractor'
|
43
|
+
require_relative 'hqmf-parser/converter/pass1/simple_restriction'
|
44
|
+
require_relative 'hqmf-parser/converter/pass1/simple_operator'
|
45
|
+
require_relative 'hqmf-parser/converter/pass1/simple_precondition'
|
46
|
+
require_relative 'hqmf-parser/converter/pass1/simple_data_criteria'
|
47
|
+
require_relative 'hqmf-parser/converter/pass1/simple_population_criteria'
|
48
|
+
|
49
|
+
require_relative 'hqmf-parser/converter/pass2/comparison_converter'
|
50
|
+
require_relative 'hqmf-parser/converter/pass2/operator_converter'
|
51
|
+
|
52
|
+
require_relative 'hqmf-parser/value_sets/value_set_parser'
|
53
|
+
|
54
|
+
require_relative 'hqmf-parser/parser'
|
55
|
+
|
56
|
+
require_relative 'hqmf-generator/hqmf-generator'
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module HQMF1
|
2
|
+
# Represents a HQMF measure attribute
|
3
|
+
class Attribute
|
4
|
+
|
5
|
+
include HQMF1::Utilities
|
6
|
+
|
7
|
+
# Create a new instance based on the supplied HQMF
|
8
|
+
# @param [Nokogiri::XML::Element] entry the measure attribute element
|
9
|
+
def initialize(entry)
|
10
|
+
@entry = entry
|
11
|
+
end
|
12
|
+
|
13
|
+
# Get the attribute code
|
14
|
+
# @return [String] the code
|
15
|
+
def code
|
16
|
+
if (@entry.at_xpath('./cda:code/@code'))
|
17
|
+
@entry.at_xpath('./cda:code/@code').value
|
18
|
+
elsif @entry.at_xpath('./cda:code/@nullFlavor')
|
19
|
+
@entry.at_xpath('./cda:code/@nullFlavor').value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get the attribute name
|
24
|
+
# @return [String] the name
|
25
|
+
def name
|
26
|
+
if (@entry.at_xpath('./cda:code/@displayName'))
|
27
|
+
@entry.at_xpath('./cda:code/@displayName').value
|
28
|
+
elsif @entry.at_xpath('cda:code/cda:originalText')
|
29
|
+
@entry.at_xpath('cda:code/cda:originalText').text
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Get the attribute id, used elsewhere in the document to refer to the attribute
|
34
|
+
# @return [String] the id
|
35
|
+
def id
|
36
|
+
attr_val('./cda:id/@root')
|
37
|
+
end
|
38
|
+
|
39
|
+
# Get the attribute value
|
40
|
+
# @return [String] the value
|
41
|
+
def value
|
42
|
+
val = attr_val('./cda:value/@value')
|
43
|
+
val ||= attr_val('./cda:value/@extension')
|
44
|
+
if val
|
45
|
+
val
|
46
|
+
else
|
47
|
+
@entry.at_xpath('./cda:value').inner_text
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Get the unit of the attribute value or nil if none is defined
|
52
|
+
# @return [String] the unit
|
53
|
+
def unit
|
54
|
+
attr_val('./cda:value/@unit')
|
55
|
+
end
|
56
|
+
|
57
|
+
# Get a JS friendly constant name for this measure attribute
|
58
|
+
def const_name
|
59
|
+
components = name.gsub(/\W/,' ').split.collect {|word| word.strip.upcase }
|
60
|
+
components.join '_'
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_json
|
64
|
+
{self.const_name => build_hash(self, [:code,:value,:unit,:name,:id])}
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module HQMF1
|
2
|
+
class Comparison
|
3
|
+
|
4
|
+
include HQMF1::Utilities
|
5
|
+
|
6
|
+
attr_reader :restrictions, :data_criteria_id, :title, :subset
|
7
|
+
|
8
|
+
def initialize(data_criteria_id, entry, parent, doc)
|
9
|
+
@doc = doc
|
10
|
+
@data_criteria_id = data_criteria_id
|
11
|
+
@entry = entry
|
12
|
+
title_def = @entry.at_xpath('./*/cda:title')
|
13
|
+
if title_def
|
14
|
+
@title = title_def.inner_text
|
15
|
+
end
|
16
|
+
@restrictions = []
|
17
|
+
restriction_def = @entry.at_xpath('./*/cda:sourceOf')
|
18
|
+
if restriction_def
|
19
|
+
@entry.xpath('./*/cda:sourceOf').each do |restriction|
|
20
|
+
@restrictions << Restriction.new(restriction, self, @doc)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_json
|
26
|
+
|
27
|
+
json = build_hash(self, [:data_criteria_id,:title,:subset])
|
28
|
+
json[:restrictions] = json_array(@restrictions)
|
29
|
+
json
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module HQMF1
|
2
|
+
# Represents a data criteria specification
|
3
|
+
class DataCriteria
|
4
|
+
|
5
|
+
include HQMF1::Utilities
|
6
|
+
|
7
|
+
attr_accessor :code_list_id, :derived_from, :definition, :status, :negation, :specific_occurrence
|
8
|
+
|
9
|
+
# Create a new instance based on the supplied HQMF entry
|
10
|
+
# @param [Nokogiri::XML::Element] entry the parsed HQMF entry
|
11
|
+
def initialize(entry, occurrence_counters)
|
12
|
+
@entry = entry
|
13
|
+
|
14
|
+
template_map = HQMF::DataCriteria.get_template_id_map()
|
15
|
+
oid_xpath_file = File.expand_path('../data_criteria_oid_xpath.json', __FILE__)
|
16
|
+
oid_xpath_map = JSON.parse(File.read(oid_xpath_file))
|
17
|
+
template_id = attr_val('cda:act/cda:templateId/@root') || attr_val('cda:observation/cda:templateId/@root')
|
18
|
+
|
19
|
+
# check to see if this is a derived data criteria. These are used for multiple occurrences.
|
20
|
+
derived_entry = @entry.at_xpath('./*/cda:sourceOf[@typeCode="DRIV"]')
|
21
|
+
if derived_entry
|
22
|
+
derived = derived_entry.at_xpath('cda:act/cda:id/@root') || derived_entry.at_xpath('cda:observation/cda:id/@root')
|
23
|
+
@derived_from = derived.value
|
24
|
+
occurrence_counters[@derived_from] ||= HQMF::InstanceCounter.new
|
25
|
+
@occurrence_key = occurrence_counters[@derived_from].next-1
|
26
|
+
@specific_occurrence = "#{('A'..'ZZ').to_a[@occurrence_key]}"
|
27
|
+
end
|
28
|
+
|
29
|
+
template = template_map[template_id]
|
30
|
+
if template
|
31
|
+
@negation=template["negation"]
|
32
|
+
@definition=template["definition"]
|
33
|
+
@status=template["status"]
|
34
|
+
@key=@definition+(@status.empty? ? '' : "_#{@status}")
|
35
|
+
else
|
36
|
+
raise "Unknown data criteria template identifier [#{template_id}]"
|
37
|
+
end
|
38
|
+
|
39
|
+
# Get the code list OID of the criteria, used as an index to the code list database
|
40
|
+
@code_list_id = attr_val(oid_xpath_map[@key]['oid_xpath'])
|
41
|
+
unless @code_list_id
|
42
|
+
puts "\tcode list id not found, getting default" if !@derived_from
|
43
|
+
@code_list_id = attr_val('cda:act/cda:sourceOf//cda:code/@code')
|
44
|
+
end
|
45
|
+
|
46
|
+
puts "\tno oid defined for data criteria: #{@key}" if !@code_list_id and !@derived_from
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get the identifier of the criteria, used elsewhere within the document for referencing
|
51
|
+
# @return [String] the identifier of this data criteria
|
52
|
+
def id
|
53
|
+
attr_val('cda:act/cda:id/@root') || attr_val('cda:observation/cda:id/@root')
|
54
|
+
end
|
55
|
+
|
56
|
+
# Get the title of the criteria, provides a human readable description
|
57
|
+
# @return [String] the title of this data criteria
|
58
|
+
def title
|
59
|
+
title = description
|
60
|
+
title = "Occurrence #{@specific_occurrence}: #{title}" if @derived_from
|
61
|
+
title
|
62
|
+
end
|
63
|
+
|
64
|
+
def description
|
65
|
+
if (@entry.at_xpath('.//cda:title'))
|
66
|
+
description = @entry.at_xpath('.//cda:title').inner_text
|
67
|
+
else
|
68
|
+
description = @entry.at_xpath('.//cda:localVariableName').inner_text
|
69
|
+
end
|
70
|
+
description
|
71
|
+
end
|
72
|
+
|
73
|
+
# Get a JS friendly constant name for this measure attribute
|
74
|
+
def const_name
|
75
|
+
components = title.gsub(/\W/,' ').split.collect {|word| word.strip.upcase }
|
76
|
+
if @derived_from
|
77
|
+
components << HQMF::Counter.instance.next
|
78
|
+
end
|
79
|
+
components.join '_'
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_json
|
83
|
+
json = build_hash(self, [:id,:title,:code_list_id,:derived_from,:description, :definition, :status, :negation, :specific_occurrence])
|
84
|
+
{
|
85
|
+
self.const_name => json
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
{
|
2
|
+
"patient_characteristic":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
3
|
+
"patient_characteristic_birthdate":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
4
|
+
"patient_characteristic_clinical_trial_participant":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
5
|
+
"patient_characteristic_gender":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
6
|
+
"patient_characteristic_ethnicity":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
7
|
+
"patient_characteristic_expired":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
8
|
+
"patient_characteristic_payer":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
9
|
+
"patient_characteristic_race":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
10
|
+
"encounter":{"oid_xpath":"cda:act/cda:sourceOf/cda:encounter/cda:code/@code"},
|
11
|
+
"encounter_active":{"oid_xpath":"cda:act/cda:sourceOf/cda:encounter/cda:code/@code"},
|
12
|
+
"encounter_performed":{"oid_xpath":"cda:act/cda:sourceOf/cda:encounter/cda:code/@code"},
|
13
|
+
"encounter_ordered":{"oid_xpath":"cda:act/cda:sourceOf/cda:encounter/cda:code/@code"},
|
14
|
+
"encounter_recommended":{"oid_xpath":"cda:act/cda:sourceOf/cda:encounter/cda:code/@code"},
|
15
|
+
"procedure_performed":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:code/@code"},
|
16
|
+
"procedure_ordered":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:code/@code"},
|
17
|
+
"procedure_result":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:code/@code"},
|
18
|
+
"procedure_adverse_event":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:sourceOf/cda:procedure/cda:code/@code"},
|
19
|
+
"procedure_intolerance":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:sourceOf/cda:procedure/cda:code/@code"},
|
20
|
+
"procedure_recommended":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:code/@code"},
|
21
|
+
"diagnosis_active":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
22
|
+
"diagnosis_resolved":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
23
|
+
"diagnosis_family_history":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
24
|
+
"diagnosis_inactive":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
25
|
+
"diagnosis_risk_of":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
26
|
+
"diagnostic_study_performed":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
27
|
+
"diagnostic_study_result":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
28
|
+
"diagnostic_study_adverse_event":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:sourceOf/cda:procedure/cda:code/@code"},
|
29
|
+
"diagnostic_study_intolerance":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:sourceOf/cda:procedure/cda:code/@code"},
|
30
|
+
"diagnostic_study_ordered":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:code/@code"},
|
31
|
+
"medication_discharge":{"oid_xpath":"cda:act/cda:sourceOf/cda:substanceAdministration/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
32
|
+
"medication_dispensed":{"oid_xpath":"cda:act/cda:sourceOf/cda:supply/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
33
|
+
"medication_ordered":{"oid_xpath":"cda:act/cda:sourceOf/cda:substanceAdministration/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
34
|
+
"medication_active":{"oid_xpath":"cda:act/cda:sourceOf/cda:substanceAdministration/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
35
|
+
"medication_administered":{"oid_xpath":"cda:act/cda:sourceOf/cda:substanceAdministration/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
36
|
+
"medication_adverse_effects":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
37
|
+
"medication_allergy":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
38
|
+
"medication_intolerance":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
39
|
+
"physical_exam":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
40
|
+
"physical_exam":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
41
|
+
"physical_exam_ordered":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
42
|
+
"physical_exam_performed":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
43
|
+
"physical_exam_recommended":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
44
|
+
"laboratory_test":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
45
|
+
"laboratory_test_performed":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
46
|
+
"laboratory_test_adverse_event":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:sourceOf/cda:procedure/cda:code/@code"},
|
47
|
+
"laboratory_test_intolerance":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:sourceOf/cda:procedure/cda:code/@code"},
|
48
|
+
"laboratory_test_ordered":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:code/@code"},
|
49
|
+
"laboratory_test_recommended":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:code/@code"},
|
50
|
+
"care_goal":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:value/@code"},
|
51
|
+
"communication_from_patient_to_provider":{"oid_xpath":"cda:act/cda:sourceOf/cda:act/cda:code/@code"},
|
52
|
+
"communication_from_provider_to_patient":{"oid_xpath":"cda:act/cda:sourceOf/cda:act/cda:code/@code"},
|
53
|
+
"communication_from_provider_to_provider":{"oid_xpath":"cda:act/cda:sourceOf/cda:act/cda:code/@code"},
|
54
|
+
"device_applied":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:participant/cda:roleParticipant/cda:playingDevice/cda:code/@code"},
|
55
|
+
"device_adverse_event":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
56
|
+
"device_allergy":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
57
|
+
"device_intolerance":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
58
|
+
"device_ordered":{"oid_xpath":"cda:act/cda:sourceOf/cda:supply/cda:participant/cda:roleParticipant/cda:playingDevice/cda:code/@code"},
|
59
|
+
"device_recommended":{"oid_xpath":"cda:act/cda:sourceOf/cda:supply/cda:participant/cda:roleParticipant/cda:playingDevice/cda:code/@code"},
|
60
|
+
"substance_administered":{"oid_xpath":"cda:act/cda:sourceOf/cda:substanceAdministration/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
61
|
+
"substance_ordered":{"oid_xpath":"cda:act/cda:sourceOf/cda:substanceAdministration/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
62
|
+
"substance_adverse_event":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
63
|
+
"substance_intolerance":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
64
|
+
"substance_allergy":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
65
|
+
"substance_recommended":{"oid_xpath":"cda:act/cda:sourceOf/cda:substanceAdministration/cda:participant/cda:roleParticipant/cda:playingMaterial/cda:code/@code"},
|
66
|
+
"intervention_adverse_event":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:sourceOf/cda:procedure/cda:code/@code"},
|
67
|
+
"intervention_intolerance":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:sourceOf/cda:procedure/cda:code/@code"},
|
68
|
+
"intervention_ordered":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:code/@code"},
|
69
|
+
"intervention_performed":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:code/@code"},
|
70
|
+
"intervention_result":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:code/@code"},
|
71
|
+
"intervention_recommended":{"oid_xpath":"cda:act/cda:sourceOf/cda:procedure/cda:code/@code"},
|
72
|
+
"symptom_active":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
73
|
+
"symptom_assessed":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
74
|
+
"symptom_inactive":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
75
|
+
"symptom_resolved":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
76
|
+
"functional_status":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
77
|
+
"functional_status_performed":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
78
|
+
"functional_status_ordered":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
79
|
+
"functional_status_recommended":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
80
|
+
"functional_status_result":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
81
|
+
"risk_category_assessment":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
82
|
+
"provider_care_experience":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
83
|
+
"patient_care_experience":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
84
|
+
"preference_provider":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
85
|
+
"preference_patient":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
86
|
+
"system_characteristic":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:code/@code"},
|
87
|
+
"provider_characteristic":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:code/@code"},
|
88
|
+
"provider_characteristic":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:code/@code"},
|
89
|
+
"transfer_from":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:code/@code"},
|
90
|
+
"transfer_to":{"oid_xpath":"cda:act/cda:sourceOf/cda:observation/cda:participant/cda:roleParticipant/cda:code/@code"}
|
91
|
+
}
|
@@ -0,0 +1,203 @@
|
|
1
|
+
module HQMF1
|
2
|
+
# Class representing an HQMF document
|
3
|
+
class Document
|
4
|
+
|
5
|
+
include HQMF1::Utilities
|
6
|
+
|
7
|
+
attr_reader :hqmf_id, :hqmf_set_id, :hqmf_version_number
|
8
|
+
|
9
|
+
# Create a new HQMF1::Document instance by parsing the supplied contents
|
10
|
+
# @param [String] hqmf_contents the contents of an HQMF v1.0 document
|
11
|
+
def initialize(hqmf_contents)
|
12
|
+
|
13
|
+
@doc = Document.parse(hqmf_contents)
|
14
|
+
occurrence_counters = {}
|
15
|
+
@data_criteria = @doc.xpath('//cda:section[cda:code/@code="57025-9"]/cda:entry').collect do |entry|
|
16
|
+
DataCriteria.new(entry, occurrence_counters)
|
17
|
+
end
|
18
|
+
|
19
|
+
backfill_derived_code_lists
|
20
|
+
|
21
|
+
@attributes = @doc.xpath('//cda:subjectOf/cda:measureAttribute').collect do |attr|
|
22
|
+
Attribute.new(attr)
|
23
|
+
end
|
24
|
+
@population_criteria = @doc.xpath('//cda:section[cda:code/@code="57026-7"]/cda:entry').collect do |attr|
|
25
|
+
PopulationCriteria.new(attr, self)
|
26
|
+
end
|
27
|
+
observations = @doc.xpath('//cda:section[cda:code/@code="57027-5"]/cda:entry').collect do |attr|
|
28
|
+
Observation.new(attr, self)
|
29
|
+
end
|
30
|
+
@population_criteria.concat(observations)
|
31
|
+
|
32
|
+
@stratification = @doc.xpath('//cda:section[cda:code/@code="69669-0"]/cda:entry').collect do |attr|
|
33
|
+
PopulationCriteria.new(attr, self)
|
34
|
+
end
|
35
|
+
|
36
|
+
if (@stratification and !@stratification.empty?)
|
37
|
+
initial_populations = @population_criteria.select {|pc| pc.code.starts_with? 'IPP'}
|
38
|
+
initial_populations.each do |population|
|
39
|
+
|
40
|
+
@stratification.each do |stratification|
|
41
|
+
new_population = HQMF1::PopulationCriteria.new(population.entry, population.doc)
|
42
|
+
new_population.hqmf_id = new_population.id
|
43
|
+
new_population.stratification_id = stratification.id
|
44
|
+
new_population.id = "#{new_population.id}_#{stratification.id}"
|
45
|
+
ids = stratification.preconditions.map(&:id)
|
46
|
+
new_population.preconditions.delete_if {|precondition| ids.include? precondition.id}
|
47
|
+
new_population.preconditions.concat(stratification.preconditions)
|
48
|
+
new_population.preconditions.rotate!(-1*stratification.preconditions.size)
|
49
|
+
@population_criteria << new_population
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
@hqmf_set_id = @doc.at_xpath('//cda:setId/@root').value.upcase
|
57
|
+
@hqmf_id = @doc.at_xpath('//cda:id/@root').value.upcase
|
58
|
+
@hqmf_version_number = @doc.at_xpath('//cda:versionNumber/@value').value.to_i
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
# Get the title of the measure
|
63
|
+
# @return [String] the title
|
64
|
+
def title
|
65
|
+
@doc.at_xpath('cda:QualityMeasureDocument/cda:title').inner_text
|
66
|
+
end
|
67
|
+
|
68
|
+
# Get the description of the measure
|
69
|
+
# @return [String] the description
|
70
|
+
def description
|
71
|
+
@doc.at_xpath('cda:QualityMeasureDocument/cda:text').inner_text
|
72
|
+
end
|
73
|
+
|
74
|
+
# Get all the attributes defined by the measure
|
75
|
+
# @return [Array] an array of HQMF1::Attribute
|
76
|
+
def all_attributes
|
77
|
+
@attributes
|
78
|
+
end
|
79
|
+
|
80
|
+
# Get a specific attribute by id.
|
81
|
+
# @param [String] id the attribute identifier
|
82
|
+
# @return [HQMF1::Attribute] the matching attribute, raises an Exception if not found
|
83
|
+
def attribute(id)
|
84
|
+
find(@attributes, :id, id)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Get a specific attribute by code.
|
88
|
+
# @param [String] code the attribute code
|
89
|
+
# @return [HQMF1::Attribute] the matching attribute, raises an Exception if not found
|
90
|
+
def attribute_for_code(code)
|
91
|
+
find(@attributes, :code, code)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Get all the population criteria defined by the measure
|
95
|
+
# @return [Array] an array of HQMF1::PopulationCriteria
|
96
|
+
def all_population_criteria
|
97
|
+
@population_criteria
|
98
|
+
end
|
99
|
+
|
100
|
+
def stratification
|
101
|
+
@stratification
|
102
|
+
end
|
103
|
+
|
104
|
+
# Get a specific population criteria by id.
|
105
|
+
# @param [String] id the population identifier
|
106
|
+
# @return [HQMF1::PopulationCriteria] the matching criteria, raises an Exception if not found
|
107
|
+
def population_criteria(id)
|
108
|
+
find(@population_criteria, :id, id)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Get a specific population criteria by code.
|
112
|
+
# @param [String] code the population criteria code
|
113
|
+
# @return [HQMF1::PopulationCriteria] the matching criteria, raises an Exception if not found
|
114
|
+
def population_criteria_for_code(code)
|
115
|
+
find(@population_criteria, :code, code)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Get all the data criteria defined by the measure
|
119
|
+
# @return [Array] an array of HQMF1::DataCriteria describing the data elements used by the measure
|
120
|
+
def all_data_criteria
|
121
|
+
@data_criteria
|
122
|
+
end
|
123
|
+
|
124
|
+
# Get a specific data criteria by id.
|
125
|
+
# @param [String] id the data criteria identifier
|
126
|
+
# @return [HQMF1::DataCriteria] the matching data criteria, raises an Exception if not found
|
127
|
+
def data_criteria(id)
|
128
|
+
val = find(@data_criteria, :id, id) || raise("unknown data criteria #{id}")
|
129
|
+
end
|
130
|
+
|
131
|
+
# Parse an XML document from the supplied contents
|
132
|
+
# @return [Nokogiri::XML::Document]
|
133
|
+
def self.parse(hqmf_contents)
|
134
|
+
doc = Nokogiri::XML(hqmf_contents)
|
135
|
+
doc.root.add_namespace_definition('cda', 'urn:hl7-org:v3')
|
136
|
+
doc
|
137
|
+
end
|
138
|
+
|
139
|
+
# if the data criteria is derived from another criteria, then we want to grab the properties from the derived criteria
|
140
|
+
# this is typically the case with Occurrence A, Occurrence B type data criteria
|
141
|
+
def backfill_derived_code_lists
|
142
|
+
data_criteria_by_id = {}
|
143
|
+
@data_criteria.each {|criteria| data_criteria_by_id[criteria.id] = criteria}
|
144
|
+
@data_criteria.each do |criteria|
|
145
|
+
if (criteria.derived_from)
|
146
|
+
derived_from = data_criteria_by_id[criteria.derived_from]
|
147
|
+
criteria.definition = derived_from.definition
|
148
|
+
criteria.status = derived_from.status
|
149
|
+
criteria.code_list_id = derived_from.code_list_id
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def to_json
|
155
|
+
json = build_hash(self, [:title, :description, :hqmf_id, :hqmf_set_id, :hqmf_version_number])
|
156
|
+
|
157
|
+
json[:data_criteria] = {}
|
158
|
+
@data_criteria.each do |criteria|
|
159
|
+
criteria_json = criteria.to_json
|
160
|
+
# check if the key already exists... if it does redefine the key
|
161
|
+
if (json[:data_criteria][criteria_json.keys.first])
|
162
|
+
criteria_json = {"#{criteria_json.keys.first}_#{HQMF::Counter.instance.next}" => criteria_json.values.first}
|
163
|
+
end
|
164
|
+
json[:data_criteria].merge! criteria_json
|
165
|
+
end
|
166
|
+
|
167
|
+
json[:metadata] = {}
|
168
|
+
json[:attributes] = {}
|
169
|
+
@attributes.each do |attribute|
|
170
|
+
if (attribute.id)
|
171
|
+
json[:attributes].merge! attribute.to_json
|
172
|
+
else
|
173
|
+
json[:metadata].merge! attribute.to_json
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
json[:logic] = {}
|
179
|
+
counters = {}
|
180
|
+
@population_criteria.each do |population|
|
181
|
+
population_json = population.to_json
|
182
|
+
key = population_json.keys.first
|
183
|
+
if json[:logic][key]
|
184
|
+
counters[key] ||= 0
|
185
|
+
counters[key] += 1
|
186
|
+
population_json["#{key}_#{counters[key]}"] = population_json[key]
|
187
|
+
population_json.delete(key)
|
188
|
+
end
|
189
|
+
json[:logic].merge! population_json
|
190
|
+
end
|
191
|
+
|
192
|
+
clean_json_recursive(json)
|
193
|
+
json
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
def find(collection, attribute, value)
|
199
|
+
collection.find {|e| e.send(attribute)==value}
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
end
|