cqm-parsers 0.2.2 → 3.0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +7 -3
  3. data/README.md +57 -5
  4. data/Rakefile +1 -0
  5. data/lib/{hqmf-parser.rb → cqm-parsers.rb} +13 -45
  6. data/lib/ext/data_element.rb +1 -1
  7. data/lib/hqmf-parser/2.0/document.rb +1 -1
  8. data/lib/hqmf-parser/2.0/population_criteria.rb +1 -1
  9. data/lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb +11 -6
  10. data/lib/measure-loader/cql_loader.rb +165 -0
  11. data/lib/measure-loader/elm_dependency_finder.rb +72 -0
  12. data/lib/measure-loader/elm_parser.rb +67 -0
  13. data/lib/measure-loader/exceptions.rb +10 -0
  14. data/lib/measure-loader/helpers.rb +11 -0
  15. data/lib/measure-loader/hqmf_measure_loader.rb +170 -0
  16. data/lib/measure-loader/mat_measure_files.rb +138 -0
  17. data/lib/measure-loader/source_data_criteria_loader.rb +75 -0
  18. data/lib/measure-loader/value_set_helpers.rb +68 -0
  19. data/lib/measure-loader/vsac_value_set_loader.rb +97 -0
  20. data/lib/tasks/hqmf.rake +1 -1
  21. data/lib/util/util.rb +23 -0
  22. data/lib/util/vsac_api.rb +166 -103
  23. metadata +49 -116
  24. data/lib/ext/code.rb +0 -10
  25. data/lib/qrda-export/catI-r5/_code.mustache +0 -1
  26. data/lib/qrda-export/catI-r5/_codes.mustache +0 -10
  27. data/lib/qrda-export/catI-r5/_header.mustache +0 -28
  28. data/lib/qrda-export/catI-r5/_measure_section.mustache +0 -59
  29. data/lib/qrda-export/catI-r5/_reporting_period.mustache +0 -23
  30. data/lib/qrda-export/catI-r5/_values.mustache +0 -10
  31. data/lib/qrda-export/catI-r5/qrda1_r5.mustache +0 -137
  32. data/lib/qrda-export/catI-r5/qrda1_r5.rb +0 -125
  33. data/lib/qrda-export/catI-r5/qrda_header/_author.mustache +0 -24
  34. data/lib/qrda-export/catI-r5/qrda_header/_custodian.mustache +0 -43
  35. data/lib/qrda-export/catI-r5/qrda_header/_documentation_of_service_event.mustache +0 -82
  36. data/lib/qrda-export/catI-r5/qrda_header/_information_recipient.mustache +0 -7
  37. data/lib/qrda-export/catI-r5/qrda_header/_legal_authenticator.mustache +0 -25
  38. data/lib/qrda-export/catI-r5/qrda_header/_participant.mustache +0 -7
  39. data/lib/qrda-export/catI-r5/qrda_header/_record_target.mustache +0 -28
  40. data/lib/qrda-export/catI-r5/qrda_templates/adverse_event.mustache +0 -28
  41. data/lib/qrda-export/catI-r5/qrda_templates/allergy_intolerance.mustache +0 -28
  42. data/lib/qrda-export/catI-r5/qrda_templates/assessment_performed.mustache +0 -25
  43. data/lib/qrda-export/catI-r5/qrda_templates/communication_from_patient_to_provider.mustache +0 -29
  44. data/lib/qrda-export/catI-r5/qrda_templates/communication_from_provider_to_patient.mustache +0 -24
  45. data/lib/qrda-export/catI-r5/qrda_templates/communication_from_provider_to_provider.mustache +0 -31
  46. data/lib/qrda-export/catI-r5/qrda_templates/device_applied.mustache +0 -32
  47. data/lib/qrda-export/catI-r5/qrda_templates/device_ordered.mustache +0 -31
  48. data/lib/qrda-export/catI-r5/qrda_templates/diagnosis.mustache +0 -38
  49. data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_ordered.mustache +0 -19
  50. data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_performed.mustache +0 -29
  51. data/lib/qrda-export/catI-r5/qrda_templates/encounter_ordered.mustache +0 -24
  52. data/lib/qrda-export/catI-r5/qrda_templates/encounter_performed.mustache +0 -40
  53. data/lib/qrda-export/catI-r5/qrda_templates/immunization_administered.mustache +0 -29
  54. data/lib/qrda-export/catI-r5/qrda_templates/insurance_provider.mustache +0 -11
  55. data/lib/qrda-export/catI-r5/qrda_templates/intervention_ordered.mustache +0 -18
  56. data/lib/qrda-export/catI-r5/qrda_templates/intervention_performed.mustache +0 -25
  57. data/lib/qrda-export/catI-r5/qrda_templates/lab_test_ordered.mustache +0 -18
  58. data/lib/qrda-export/catI-r5/qrda_templates/lab_test_performed.mustache +0 -22
  59. data/lib/qrda-export/catI-r5/qrda_templates/medication_active.mustache +0 -35
  60. data/lib/qrda-export/catI-r5/qrda_templates/medication_administered.mustache +0 -31
  61. data/lib/qrda-export/catI-r5/qrda_templates/medication_discharge.mustache +0 -55
  62. data/lib/qrda-export/catI-r5/qrda_templates/medication_dispensed.mustache +0 -39
  63. data/lib/qrda-export/catI-r5/qrda_templates/medication_ordered.mustache +0 -38
  64. data/lib/qrda-export/catI-r5/qrda_templates/patient_characteristic_expired.mustache +0 -16
  65. data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_performed.mustache +0 -25
  66. data/lib/qrda-export/catI-r5/qrda_templates/procedure_ordered.mustache +0 -19
  67. data/lib/qrda-export/catI-r5/qrda_templates/procedure_performed.mustache +0 -44
  68. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_admission_source.mustache +0 -6
  69. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_anatomical_location_site.mustache +0 -1
  70. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_author.mustache +0 -7
  71. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_author_participation.mustache +0 -7
  72. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_component.mustache +0 -11
  73. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_encounter_diagnosis.mustache +0 -19
  74. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_encounter_facility_location.mustache +0 -16
  75. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_mediation_frequency.mustache +0 -3
  76. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_medication_details.mustache +0 -11
  77. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_ordinality.mustache +0 -1
  78. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_principal_diagnosis.mustache +0 -8
  79. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_reason.mustache +0 -12
  80. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_related_to.mustache +0 -6
  81. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_results.mustache +0 -21
  82. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_severity.mustache +0 -8
  83. data/lib/qrda-export/helper/cat_1_view_helper.rb +0 -142
  84. data/lib/qrda-export/helper/code_system_helper.rb +0 -77
  85. data/lib/qrda-export/helper/date_helper.rb +0 -85
  86. data/lib/qrda-import/base-importers/demographics_importer.rb +0 -43
  87. data/lib/qrda-import/base-importers/medication_importer.rb +0 -23
  88. data/lib/qrda-import/base-importers/section_importer.rb +0 -196
  89. data/lib/qrda-import/cda_identifier.rb +0 -19
  90. data/lib/qrda-import/data-element-importers/adverse_event_importer.rb +0 -24
  91. data/lib/qrda-import/data-element-importers/allergy_intolerance_importer.rb +0 -22
  92. data/lib/qrda-import/data-element-importers/assessment_performed_importer.rb +0 -24
  93. data/lib/qrda-import/data-element-importers/communication_from_patient_to_provider_importer.rb +0 -19
  94. data/lib/qrda-import/data-element-importers/communication_from_provider_to_patient_importer.rb +0 -19
  95. data/lib/qrda-import/data-element-importers/communication_from_provider_to_provider_importer.rb +0 -21
  96. data/lib/qrda-import/data-element-importers/device_applied_importer.rb +0 -24
  97. data/lib/qrda-import/data-element-importers/device_order_importer.rb +0 -19
  98. data/lib/qrda-import/data-element-importers/diagnosis_importer.rb +0 -24
  99. data/lib/qrda-import/data-element-importers/diagnostic_study_order_importer.rb +0 -21
  100. data/lib/qrda-import/data-element-importers/diagnostic_study_performed_importer.rb +0 -31
  101. data/lib/qrda-import/data-element-importers/encounter_order_importer.rb +0 -21
  102. data/lib/qrda-import/data-element-importers/encounter_performed_importer.rb +0 -42
  103. data/lib/qrda-import/data-element-importers/immunization_administered_importer.rb +0 -18
  104. data/lib/qrda-import/data-element-importers/intervention_order_importer.rb +0 -19
  105. data/lib/qrda-import/data-element-importers/intervention_performed_importer.rb +0 -23
  106. data/lib/qrda-import/data-element-importers/laboratory_test_order_importer.rb +0 -21
  107. data/lib/qrda-import/data-element-importers/laboratory_test_performed_importer.rb +0 -29
  108. data/lib/qrda-import/data-element-importers/medication_active_importer.rb +0 -17
  109. data/lib/qrda-import/data-element-importers/medication_administered_importer.rb +0 -17
  110. data/lib/qrda-import/data-element-importers/medication_discharge_importer.rb +0 -19
  111. data/lib/qrda-import/data-element-importers/medication_dispensed_importer.rb +0 -19
  112. data/lib/qrda-import/data-element-importers/medication_order_importer.rb +0 -16
  113. data/lib/qrda-import/data-element-importers/patient_characteristic_expired.rb +0 -22
  114. data/lib/qrda-import/data-element-importers/physical_exam_performed_importer.rb +0 -27
  115. data/lib/qrda-import/data-element-importers/procedure_order_importer.rb +0 -27
  116. data/lib/qrda-import/data-element-importers/procedure_performed_importer.rb +0 -35
  117. data/lib/qrda-import/data-element-importers/substance_administered_importer.rb +0 -16
  118. data/lib/qrda-import/entry_finder.rb +0 -20
  119. data/lib/qrda-import/entry_package.rb +0 -16
  120. data/lib/qrda-import/narrative_reference_handler.rb +0 -33
  121. data/lib/qrda-import/patient_importer.rb +0 -111
@@ -1,77 +0,0 @@
1
- module Qrda
2
- module Export
3
- module Helper
4
- # General helpers for working with codes and code systems
5
- class CodeSystemHelper
6
- CODE_SYSTEMS = {
7
- '2.16.840.1.113883.6.1' => 'LOINC',
8
- '2.16.840.1.113883.6.96' => 'SNOMED-CT',
9
- '2.16.840.1.113883.6.12' => 'CPT',
10
- '2.16.840.1.113883.6.88' => 'RxNorm',
11
- '2.16.840.1.113883.6.103' => 'ICD-9-CM',
12
- '2.16.840.1.113883.6.104' => 'ICD-9-PCS',
13
- '2.16.840.1.113883.6.4' => 'ICD-10-PCS',
14
- '2.16.840.1.113883.6.90' => 'ICD-10-CM',
15
- '2.16.840.1.113883.6.14' => 'HCP',
16
- '2.16.840.1.113883.6.285' => 'HCPCS',
17
- '2.16.840.1.113883.5.2' => "HL7 Marital Status",
18
- '2.16.840.1.113883.12.292' => 'CVX',
19
- '2.16.840.1.113883.5.83' => 'HITSP C80 Observation Status',
20
- '2.16.840.1.113883.3.26.1.1' => 'NCI Thesaurus',
21
- '2.16.840.1.113883.3.88.12.80.20' => 'FDA',
22
- "2.16.840.1.113883.4.9" => "UNII",
23
- "2.16.840.1.113883.6.69" => "NDC",
24
- '2.16.840.1.113883.5.14' => 'HL7 ActStatus',
25
- '2.16.840.1.113883.6.259' => 'HL7 Healthcare Service Location',
26
- '2.16.840.1.113883.12.112' => 'DischargeDisposition',
27
- '2.16.840.1.113883.5.4' => 'HL7 Act Code',
28
- '2.16.840.1.113883.1.11.18877' => 'HL7 Relationship Code',
29
- '2.16.840.1.113883.6.238' => 'CDC Race',
30
- '2.16.840.1.113883.6.177' => 'NLM MeSH',
31
- '2.16.840.1.113883.5.1076' => "Religious Affiliation",
32
- '2.16.840.1.113883.1.11.19717' => "HL7 ActNoImmunicationReason",
33
- '2.16.840.1.113883.3.88.12.80.33' => "NUBC",
34
- '2.16.840.1.113883.1.11.78' => "HL7 Observation Interpretation",
35
- '2.16.840.1.113883.3.221.5' => "Source of Payment Typology",
36
- '2.16.840.1.113883.6.13' => 'CDT',
37
- '2.16.840.1.113883.18.2' => 'AdministrativeSex'
38
- }
39
-
40
- CODE_SYSTEM_ALIASES = {
41
- 'FDA SPL' => 'NCI Thesaurus',
42
- 'HSLOC' => 'HL7 Healthcare Service Location',
43
- 'SOP' => "Source of Payment Typology"
44
- }
45
-
46
- # Some old OID are still around in data, this hash maps retired OID values to
47
- # the new value
48
- OID_ALIASES = {
49
- '2.16.840.1.113883.6.59' => '2.16.840.1.113883.12.292' # CVX
50
- }
51
-
52
- # Returns the name of a code system given an oid
53
- # @param [String] oid of a code system
54
- # @return [String] the name of the code system as described in the measure definition JSON
55
- def self.code_system_for(oid)
56
- oid = OID_ALIASES[oid] if OID_ALIASES[oid]
57
- CODE_SYSTEMS[oid] || "Unknown"
58
- end
59
-
60
- # Returns the oid for a code system given a codesystem name
61
- # @param [String] the name of the code system
62
- # @return [String] the oid of the code system
63
- def self.oid_for_code_system(code_system)
64
- code_system = CODE_SYSTEM_ALIASES[code_system] if CODE_SYSTEM_ALIASES[code_system]
65
- CODE_SYSTEMS.invert[code_system]
66
- end
67
-
68
- # Returns the whole map of OIDs to code systems
69
- # @terurn [Hash] oids as keys, code system names as values
70
- def self.code_systems
71
- CODE_SYSTEMS
72
- end
73
- end
74
- end
75
- end
76
- end
77
-
@@ -1,85 +0,0 @@
1
- module Qrda
2
- module Export
3
- module Helper
4
- module DateHelper
5
- def value_or_null_flavor(time)
6
- # this is a bit of a hack for a defineded undefined date
7
- if time && DateTime.parse(time).year < 3000
8
- "value='#{DateTime.parse(time).utc.to_formatted_s(:number)}'"
9
- else
10
- "nullFlavor='UNK'"
11
- end
12
- end
13
-
14
- def performance_period_start
15
- @performance_period_start.to_formatted_s(:number)
16
- end
17
-
18
- def performance_period_end
19
- @performance_period_end.to_formatted_s(:number)
20
- end
21
-
22
- def current_time
23
- Time.now.utc.to_formatted_s(:number)
24
- end
25
-
26
- def author_time
27
- "<time #{value_or_null_flavor(self['authorDatetime'])}/>"
28
- end
29
-
30
- def author_effective_time
31
- "<effectiveTime #{value_or_null_flavor(self['authorDatetime'])}/>"
32
- end
33
-
34
- def expired_date_time
35
- "<effectiveTime>"\
36
- "<low #{value_or_null_flavor(self['expiredDatetime'])}/>"\
37
- "</effectiveTime>"
38
- end
39
-
40
- def prevalence_period
41
- "<effectiveTime>"\
42
- "<low #{value_or_null_flavor(self['prevalencePeriod']['low'])}/>"\
43
- "<high #{value_or_null_flavor(self['prevalencePeriod']['high'])}/>"\
44
- "</effectiveTime>"
45
- end
46
-
47
- def relevant_period
48
- "<effectiveTime>"\
49
- "<low #{value_or_null_flavor(self['relevantPeriod']['low'])}/>"\
50
- "<high #{value_or_null_flavor(self['relevantPeriod']['high'])}/>"\
51
- "</effectiveTime>"
52
- end
53
-
54
- def insurance_provider_period
55
- start_time = self['start_time'] ? DateTime.strptime(self['start_time'].to_s, '%s').to_s : nil
56
- end_time = self['end_time'] ? DateTime.strptime(self['end_time'].to_s, '%s').to_s : nil
57
- "<effectiveTime>"\
58
- "<low #{value_or_null_flavor(start_time)}/>"\
59
- "<high #{value_or_null_flavor(end_time)}/>"\
60
- "</effectiveTime>"
61
- end
62
-
63
- def medication_duration_effective_time
64
- "<effectiveTime xsi:type=\"IVL_TS\">"\
65
- "<low #{value_or_null_flavor(self['relevantPeriod']['low'])}/>"\
66
- "<high #{value_or_null_flavor(self['relevantPeriod']['high'])}/>"\
67
- "</effectiveTime>"
68
- end
69
-
70
- def facility_period
71
- "<low #{value_or_null_flavor(self['locationPeriod']['low'])}/>"\
72
- "<high #{value_or_null_flavor(self['locationPeriod']['high'])}/>"
73
- end
74
-
75
- def incision_datetime
76
- "<effectiveTime #{value_or_null_flavor(self['incisionDatetime'])}/>"
77
- end
78
-
79
- def completed_prevalence_period
80
- self['prevalencePeriod']['high'] ? true : false
81
- end
82
- end
83
- end
84
- end
85
- end
@@ -1,43 +0,0 @@
1
- module QRDA
2
- module Cat1
3
- module DemographicsImporter
4
- def get_demographics(patient, doc)
5
- patient_role_element = doc.at_xpath('/cda:ClinicalDocument/cda:recordTarget/cda:patientRole')
6
- patient_element = patient_role_element.at_xpath('./cda:patient')
7
- patient.givenNames = [patient_element.at_xpath('cda:name/cda:given').text]
8
- patient.familyName = patient_element.at_xpath('cda:name/cda:family').text
9
- patient.birthDatetime = Time.parse(patient_element.at_xpath('cda:birthTime')['value']).utc
10
- pcbd = QDM::PatientCharacteristicBirthdate.new
11
- pcbd.birthDatetime = patient.birthDatetime
12
- pcbd.dataElementCodes = [{ code: '21112-8', codeSystem: 'LOINC' }]
13
- patient.dataElements << pcbd
14
-
15
- pcs = QDM::PatientCharacteristicSex.new
16
- gender_code = patient_element.at_xpath('cda:administrativeGenderCode')['code']
17
- pcs.dataElementCodes = [{ code: gender_code, codeSystem: 'AdministrativeGender' }]
18
- patient.dataElements << pcs
19
-
20
- pcr = QDM::PatientCharacteristicRace.new
21
- race_code = patient_element.at_xpath('cda:raceCode')['code']
22
- pcr.dataElementCodes = [{ code: race_code, codeSystem: 'cdcrec' }]
23
- patient.dataElements << pcr
24
-
25
- pce = QDM::PatientCharacteristicEthnicity.new
26
- ethnicity_code = patient_element.at_xpath('cda:ethnicGroupCode')['code']
27
- pce.dataElementCodes = [{ code: ethnicity_code, codeSystem: 'cdcrec' }]
28
- patient.dataElements << pce
29
-
30
- provider_element = doc.xpath("//cda:entry/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.55']")
31
-
32
- # If a provider element isn't in the record, return wiihout adding one.
33
- return if provider_element.blank?
34
- provider_code = provider_element.first.at_xpath('cda:value')['code']
35
- ip = {}
36
- ip['financial_responsibility_type'] = { 'code' => 'SELF', 'codeSystem' => 'HL7 Relationship Code' }
37
- ip['codes'] = { 'SOP' => [provider_code] }
38
- patient.extendedData = {}
39
- patient.extendedData['insurance_providers'] = JSON.generate([ip])
40
- end
41
- end
42
- end
43
- end
@@ -1,23 +0,0 @@
1
- module QRDA
2
- module Cat1
3
- class MedicationImporter < SectionImporter
4
-
5
- def initialize(entry_finder = nil)
6
- super(entry_finder)
7
- @id_xpath = './cda:id'
8
- @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
9
- @relevant_period_xpath = "./cda:effectiveTime"
10
- @author_datetime_xpath = "./cda:author/cda:time"
11
- @dosage_xpath = "./cda:doseQuantity"
12
- @route_xpath = "./cda:routeCode"
13
- end
14
-
15
- def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
16
- medication = super
17
- medication.dosage = extract_scalar(entry_element, @dosage_xpath)
18
- medication.route = code_if_present(entry_element.at_xpath(@route_xpath))
19
- medication
20
- end
21
- end
22
- end
23
- end
@@ -1,196 +0,0 @@
1
- module QRDA
2
- module Cat1
3
- class SectionImporter
4
- attr_accessor :check_for_usable, :status_xpath, :code_xpath
5
-
6
- def initialize(entry_finder)
7
- @entry_finder = entry_finder
8
- @code_xpath = "./cda:code"
9
- @entry_id_map = {}
10
- @check_for_usable = true
11
- @entry_class = QDM::DataElement
12
- end
13
-
14
- # Traverses an HL7 CDA document passed in and creates an Array of Entry
15
- # objects based on what it finds
16
- # @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
17
- # will have the "cda" namespace registered to "urn:hl7-org:v3"
18
- # measure definition
19
- # @return [Array] will be a list of Entry objects
20
- def create_entries(doc, nrh = NarrativeReferenceHandler.new)
21
- entry_list = []
22
- @entry_id_map = {}
23
- entry_elements = @entry_finder.entries(doc)
24
- entry_elements.each do |entry_element|
25
- entry = create_entry(entry_element, nrh)
26
- if @check_for_usable
27
- entry_list << entry if usable_entry?(entry)
28
- else
29
- entry_list << entry
30
- end
31
- end
32
- [entry_list, @entry_id_map]
33
- end
34
-
35
- def usable_entry?(entry)
36
- entry.dataElementCodes.present?
37
- end
38
-
39
- def create_entry(entry_element, _nrh = NarrativeReferenceHandler.new)
40
- entry = @entry_class.new
41
- @entry_id_map[extract_id(entry_element, @id_xpath).value] ||= []
42
- @entry_id_map[extract_id(entry_element, @id_xpath).value] << entry.id
43
- entry.dataElementCodes = extract_codes(entry_element, @code_xpath)
44
- extract_dates(entry_element, entry)
45
- if @result_xpath
46
- entry.result = extract_result_values(entry_element)
47
- end
48
- extract_reason_or_negation(entry_element, entry)
49
- entry
50
- end
51
-
52
- private
53
-
54
- def extract_id(parent_element, id_xpath)
55
- id_element = parent_element.at_xpath(id_xpath)
56
- return unless id_element
57
- # If an extension is not included, use the root as the value. Other wise use the extension
58
- value = id_element['extension'] ? id_element['extension'] : id_element['root']
59
- identifier = QDM::Id.new(value: value, namingSystem: id_element['root'])
60
- identifier
61
- end
62
-
63
- def extract_codes(coded_element, code_xpath)
64
- code_list = []
65
- code_elements = coded_element.xpath(code_xpath)
66
- code_elements.each do |code_element|
67
- code_list << code_if_present(code_element)
68
- translations = code_element.xpath('cda:translation')
69
- translations.each do |translation|
70
- code_list << code_if_present(translation)
71
- end
72
- end
73
- code_list.compact
74
- end
75
-
76
- def code_if_present(code_element)
77
- return unless code_element && code_element['codeSystem'] && code_element['code']
78
- QDM::Code.new(code_element['code'], HQMF::Util::CodeSystemHelper.code_system_for(code_element['codeSystem']))
79
- end
80
-
81
- def extract_dates(parent_element, entry)
82
- entry.authorDatetime = extract_time(parent_element, @author_datetime_xpath) if @author_datetime_xpath
83
- entry.relevantPeriod = extract_interval(parent_element, @relevant_period_xpath) if @relevant_period_xpath
84
- entry.prevalencePeriod = extract_interval(parent_element, @prevalence_period_xpath) if @prevalence_period_xpath
85
- end
86
-
87
- def extract_interval(parent_element, interval_xpath)
88
- if parent_element.at_xpath("#{interval_xpath}/@value")
89
- low_time = DateTime.parse(parent_element.at_xpath(interval_xpath)['value'])
90
- high_time = DateTime.parse(parent_element.at_xpath(interval_xpath)['value'])
91
- end
92
- if parent_element.at_xpath("#{interval_xpath}/cda:low")
93
- low_time = DateTime.parse(parent_element.at_xpath("#{interval_xpath}/cda:low")['value'])
94
- end
95
- if parent_element.at_xpath("#{interval_xpath}/cda:high")
96
- high_time = if parent_element.at_xpath("#{interval_xpath}/cda:high")['value']
97
- DateTime.parse(parent_element.at_xpath("#{interval_xpath}/cda:high")['value'])
98
- else
99
- DateTime.new(9999,1,1)
100
- end
101
- end
102
- if parent_element.at_xpath("#{interval_xpath}/cda:center")
103
- low_time = Time.parse(parent_element.at_xpath("#{interval_xpath}/cda:center")['value'])
104
- high_time = Time.parse(parent_element.at_xpath("#{interval_xpath}/cda:center")['value'])
105
- end
106
- QDM::Interval.new(low_time, high_time).shift_dates(0)
107
- end
108
-
109
- def extract_time(parent_element, datetime_xpath)
110
- DateTime.parse(parent_element.at_xpath(datetime_xpath)['value']) if parent_element.at_xpath("#{datetime_xpath}/@value")
111
- end
112
-
113
- def extract_result_values(parent_element)
114
- result = []
115
- parent_element.xpath(@result_xpath).each do |elem|
116
- result << extract_result_value(elem)
117
- end
118
- result.size > 1 ? result : result.first
119
- end
120
-
121
- def extract_result_value(value_element)
122
- return unless value_element && !value_element['nullFlavor']
123
- value = value_element['value']
124
- if value.present?
125
- return value.strip.to_i if (value_element['unit'] == "1" || value_element['unit'].nil?)
126
- return QDM::Quantity.new(value.strip.to_i, value_element['unit'])
127
- elsif value_element['code'].present?
128
- return code_if_present(value_element)
129
- end
130
- end
131
-
132
- # extracts the reason or negation data. if an element is negated and the code has a null flavor, a random code is assigned for calculation
133
- # coded_parent_element is the 'parent' element when the coded is nested (e.g., medication order)
134
- def extract_reason_or_negation(parent_element, entry, coded_parent_element = nil)
135
- coded_parent_element ||= parent_element
136
- reason_element = parent_element.xpath(".//cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.88']/cda:value | .//cda:entryRelationship[@typeCode='RSON']/cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.1.27']/cda:code")
137
- negation_indicator = parent_element['negationInd']
138
- unless reason_element.blank?
139
- if negation_indicator.eql?('true')
140
- entry.negationRationale = code_if_present(reason_element.first)
141
- else
142
- entry.reason = code_if_present(reason_element.first)
143
- end
144
- end
145
- extract_negated_code(coded_parent_element, entry)
146
- end
147
-
148
- def extract_negated_code(coded_parent_element, entry)
149
- code_elements = coded_parent_element.xpath(@code_xpath)
150
- code_elements.each do |code_element|
151
- if code_element['nullFlavor'] == 'NA' && code_element['sdtc:valueSet']
152
- entry.dataElementCodes = [{ code: code_element['sdtc:valueSet'], codeSystem: 'NA_VALUESET' }]
153
- end
154
- end
155
- end
156
-
157
- def extract_scalar(parent_element, scalar_xpath)
158
- scalar_element = parent_element.at_xpath(scalar_xpath)
159
- return unless scalar_element
160
- QDM::Quantity.new(scalar_element['value'].to_i, scalar_element['unit'])
161
- end
162
-
163
- def extract_components(parent_element)
164
- component_elements = parent_element.xpath(@components_xpath)
165
- components = []
166
- component_elements&.each do |component_element|
167
- component = QDM::Component.new
168
- component.code = code_if_present(component_element.at_xpath('./cda:code'))
169
- component.result = extract_result_value(component_element.at_xpath('./cda:value'))
170
- components << component
171
- end
172
- components
173
- end
174
-
175
- def extract_facility(parent_element, entry)
176
- facility_element = parent_element.at_xpath(@facility_xpath)
177
- return unless facility_element
178
- facility = QDM::FacilityLocation.new
179
- participant_element = facility_element.at_xpath("./cda:participantRole[@classCode='SDLOC']/cda:code")
180
- facility.code = code_if_present(participant_element)
181
- facility.locationPeriod = extract_interval(facility_element, './cda:time')
182
- entry.facilityLocations = [facility]
183
- end
184
-
185
- def extract_related_to(parent_element)
186
- related_to_elements = parent_element.xpath(@related_to_xpath)
187
- related_ids = []
188
- related_to_elements.each do |related_to_element|
189
- related_ids << extract_id(related_to_element, './sdtc:id')
190
- end
191
- related_ids
192
- end
193
-
194
- end
195
- end
196
- end
@@ -1,19 +0,0 @@
1
- require 'mongoid'
2
-
3
- class CDAIdentifier
4
- include Mongoid::Document
5
- include Mongoid::Attributes::Dynamic
6
-
7
- field :root, type: String
8
- field :extension, type: String
9
- embedded_in :cda_identifiable, polymorphic: true
10
-
11
- def ==(other)
12
- return unless other.respond_to?(:root) && other.respond_to?(:extension)
13
- root == other.root && extension == other.extension
14
- end
15
-
16
- def hash
17
- "#{root}#{extension}".hash
18
- end
19
- end