cqm-parsers 0.2.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +8 -4
  3. data/README.md +44 -5
  4. data/Rakefile +1 -0
  5. data/lib/ext/data_element.rb +1 -1
  6. data/lib/hqmf-parser.rb +13 -45
  7. data/lib/hqmf-parser/2.0/document.rb +1 -1
  8. data/lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb +6 -1
  9. data/lib/measure-loader/cql_loader.rb +165 -0
  10. data/lib/measure-loader/elm_dependency_finder.rb +72 -0
  11. data/lib/measure-loader/elm_parser.rb +67 -0
  12. data/lib/measure-loader/exceptions.rb +10 -0
  13. data/lib/measure-loader/helpers.rb +11 -0
  14. data/lib/measure-loader/hqmf_measure_loader.rb +170 -0
  15. data/lib/measure-loader/mat_measure_files.rb +138 -0
  16. data/lib/measure-loader/source_data_criteria_loader.rb +65 -0
  17. data/lib/measure-loader/value_set_helpers.rb +68 -0
  18. data/lib/measure-loader/vsac_value_set_loader.rb +97 -0
  19. data/lib/util/util.rb +23 -0
  20. data/lib/util/vsac_api.rb +164 -101
  21. metadata +47 -129
  22. data/lib/ext/code.rb +0 -10
  23. data/lib/qrda-export/catI-r5/_code.mustache +0 -1
  24. data/lib/qrda-export/catI-r5/_codes.mustache +0 -10
  25. data/lib/qrda-export/catI-r5/_header.mustache +0 -28
  26. data/lib/qrda-export/catI-r5/_measure_section.mustache +0 -59
  27. data/lib/qrda-export/catI-r5/_reporting_period.mustache +0 -23
  28. data/lib/qrda-export/catI-r5/_values.mustache +0 -10
  29. data/lib/qrda-export/catI-r5/qrda1_r5.mustache +0 -137
  30. data/lib/qrda-export/catI-r5/qrda1_r5.rb +0 -125
  31. data/lib/qrda-export/catI-r5/qrda_header/_author.mustache +0 -24
  32. data/lib/qrda-export/catI-r5/qrda_header/_custodian.mustache +0 -43
  33. data/lib/qrda-export/catI-r5/qrda_header/_documentation_of_service_event.mustache +0 -82
  34. data/lib/qrda-export/catI-r5/qrda_header/_information_recipient.mustache +0 -7
  35. data/lib/qrda-export/catI-r5/qrda_header/_legal_authenticator.mustache +0 -25
  36. data/lib/qrda-export/catI-r5/qrda_header/_participant.mustache +0 -7
  37. data/lib/qrda-export/catI-r5/qrda_header/_record_target.mustache +0 -28
  38. data/lib/qrda-export/catI-r5/qrda_templates/adverse_event.mustache +0 -28
  39. data/lib/qrda-export/catI-r5/qrda_templates/allergy_intolerance.mustache +0 -28
  40. data/lib/qrda-export/catI-r5/qrda_templates/assessment_performed.mustache +0 -25
  41. data/lib/qrda-export/catI-r5/qrda_templates/communication_from_patient_to_provider.mustache +0 -29
  42. data/lib/qrda-export/catI-r5/qrda_templates/communication_from_provider_to_patient.mustache +0 -24
  43. data/lib/qrda-export/catI-r5/qrda_templates/communication_from_provider_to_provider.mustache +0 -31
  44. data/lib/qrda-export/catI-r5/qrda_templates/device_applied.mustache +0 -32
  45. data/lib/qrda-export/catI-r5/qrda_templates/device_ordered.mustache +0 -31
  46. data/lib/qrda-export/catI-r5/qrda_templates/diagnosis.mustache +0 -38
  47. data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_ordered.mustache +0 -19
  48. data/lib/qrda-export/catI-r5/qrda_templates/diagnostic_study_performed.mustache +0 -32
  49. data/lib/qrda-export/catI-r5/qrda_templates/encounter_ordered.mustache +0 -24
  50. data/lib/qrda-export/catI-r5/qrda_templates/encounter_performed.mustache +0 -40
  51. data/lib/qrda-export/catI-r5/qrda_templates/immunization_administered.mustache +0 -29
  52. data/lib/qrda-export/catI-r5/qrda_templates/insurance_provider.mustache +0 -11
  53. data/lib/qrda-export/catI-r5/qrda_templates/intervention_ordered.mustache +0 -18
  54. data/lib/qrda-export/catI-r5/qrda_templates/intervention_performed.mustache +0 -25
  55. data/lib/qrda-export/catI-r5/qrda_templates/lab_test_ordered.mustache +0 -18
  56. data/lib/qrda-export/catI-r5/qrda_templates/lab_test_performed.mustache +0 -22
  57. data/lib/qrda-export/catI-r5/qrda_templates/medication_active.mustache +0 -35
  58. data/lib/qrda-export/catI-r5/qrda_templates/medication_administered.mustache +0 -31
  59. data/lib/qrda-export/catI-r5/qrda_templates/medication_discharge.mustache +0 -55
  60. data/lib/qrda-export/catI-r5/qrda_templates/medication_dispensed.mustache +0 -39
  61. data/lib/qrda-export/catI-r5/qrda_templates/medication_ordered.mustache +0 -38
  62. data/lib/qrda-export/catI-r5/qrda_templates/patient_characteristic_expired.mustache +0 -16
  63. data/lib/qrda-export/catI-r5/qrda_templates/physical_exam_performed.mustache +0 -25
  64. data/lib/qrda-export/catI-r5/qrda_templates/procedure_ordered.mustache +0 -19
  65. data/lib/qrda-export/catI-r5/qrda_templates/procedure_performed.mustache +0 -44
  66. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_admission_source.mustache +0 -6
  67. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_anatomical_location_site.mustache +0 -1
  68. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_author.mustache +0 -7
  69. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_author_participation.mustache +0 -7
  70. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_component.mustache +0 -11
  71. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_encounter_diagnosis.mustache +0 -19
  72. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_encounter_facility_location.mustache +0 -16
  73. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_mediation_frequency.mustache +0 -3
  74. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_medication_details.mustache +0 -11
  75. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_ordinality.mustache +0 -1
  76. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_principal_diagnosis.mustache +0 -8
  77. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_reason.mustache +0 -12
  78. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_related_to.mustache +0 -6
  79. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_results.mustache +0 -19
  80. data/lib/qrda-export/catI-r5/qrda_templates/template_partials/_severity.mustache +0 -8
  81. data/lib/qrda-export/helper/cat_1_view_helper.rb +0 -150
  82. data/lib/qrda-export/helper/code_system_helper.rb +0 -77
  83. data/lib/qrda-export/helper/date_helper.rb +0 -89
  84. data/lib/qrda-import/base-importers/demographics_importer.rb +0 -49
  85. data/lib/qrda-import/base-importers/medication_importer.rb +0 -23
  86. data/lib/qrda-import/base-importers/section_importer.rb +0 -203
  87. data/lib/qrda-import/cda_identifier.rb +0 -19
  88. data/lib/qrda-import/data-element-importers/adverse_event_importer.rb +0 -24
  89. data/lib/qrda-import/data-element-importers/allergy_intolerance_importer.rb +0 -22
  90. data/lib/qrda-import/data-element-importers/assessment_performed_importer.rb +0 -26
  91. data/lib/qrda-import/data-element-importers/communication_from_patient_to_provider_importer.rb +0 -20
  92. data/lib/qrda-import/data-element-importers/communication_from_provider_to_patient_importer.rb +0 -20
  93. data/lib/qrda-import/data-element-importers/communication_from_provider_to_provider_importer.rb +0 -22
  94. data/lib/qrda-import/data-element-importers/device_applied_importer.rb +0 -26
  95. data/lib/qrda-import/data-element-importers/device_order_importer.rb +0 -21
  96. data/lib/qrda-import/data-element-importers/diagnosis_importer.rb +0 -24
  97. data/lib/qrda-import/data-element-importers/diagnostic_study_order_importer.rb +0 -23
  98. data/lib/qrda-import/data-element-importers/diagnostic_study_performed_importer.rb +0 -33
  99. data/lib/qrda-import/data-element-importers/encounter_order_importer.rb +0 -23
  100. data/lib/qrda-import/data-element-importers/encounter_performed_importer.rb +0 -42
  101. data/lib/qrda-import/data-element-importers/immunization_administered_importer.rb +0 -20
  102. data/lib/qrda-import/data-element-importers/intervention_order_importer.rb +0 -21
  103. data/lib/qrda-import/data-element-importers/intervention_performed_importer.rb +0 -25
  104. data/lib/qrda-import/data-element-importers/laboratory_test_order_importer.rb +0 -23
  105. data/lib/qrda-import/data-element-importers/laboratory_test_performed_importer.rb +0 -31
  106. data/lib/qrda-import/data-element-importers/medication_active_importer.rb +0 -17
  107. data/lib/qrda-import/data-element-importers/medication_administered_importer.rb +0 -19
  108. data/lib/qrda-import/data-element-importers/medication_discharge_importer.rb +0 -19
  109. data/lib/qrda-import/data-element-importers/medication_dispensed_importer.rb +0 -19
  110. data/lib/qrda-import/data-element-importers/medication_order_importer.rb +0 -18
  111. data/lib/qrda-import/data-element-importers/patient_characteristic_expired.rb +0 -22
  112. data/lib/qrda-import/data-element-importers/physical_exam_performed_importer.rb +0 -29
  113. data/lib/qrda-import/data-element-importers/procedure_order_importer.rb +0 -29
  114. data/lib/qrda-import/data-element-importers/procedure_performed_importer.rb +0 -37
  115. data/lib/qrda-import/data-element-importers/substance_administered_importer.rb +0 -17
  116. data/lib/qrda-import/entry_finder.rb +0 -20
  117. data/lib/qrda-import/entry_package.rb +0 -16
  118. data/lib/qrda-import/narrative_reference_handler.rb +0 -33
  119. 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,89 +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 relevant_period_as_value
55
- "<effectiveTime #{value_or_null_flavor(self['relevantPeriod']['low'])}/>"
56
- end
57
-
58
- def insurance_provider_period
59
- start_time = self['start_time'] ? DateTime.strptime(self['start_time'].to_s, '%s').to_s : nil
60
- end_time = self['end_time'] ? DateTime.strptime(self['end_time'].to_s, '%s').to_s : nil
61
- "<effectiveTime>"\
62
- "<low #{value_or_null_flavor(start_time)}/>"\
63
- "<high #{value_or_null_flavor(end_time)}/>"\
64
- "</effectiveTime>"
65
- end
66
-
67
- def medication_duration_effective_time
68
- "<effectiveTime xsi:type=\"IVL_TS\">"\
69
- "<low #{value_or_null_flavor(self['relevantPeriod']['low'])}/>"\
70
- "<high #{value_or_null_flavor(self['relevantPeriod']['high'])}/>"\
71
- "</effectiveTime>"
72
- end
73
-
74
- def facility_period
75
- "<low #{value_or_null_flavor(self['locationPeriod']['low'])}/>"\
76
- "<high #{value_or_null_flavor(self['locationPeriod']['high'])}/>"
77
- end
78
-
79
- def incision_datetime
80
- "<effectiveTime #{value_or_null_flavor(self['incisionDatetime'])}/>"
81
- end
82
-
83
- def completed_prevalence_period
84
- self['prevalencePeriod']['high'] ? true : false
85
- end
86
- end
87
- end
88
- end
89
- end
@@ -1,49 +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
- code_element = patient_element.at_xpath('cda:administrativeGenderCode')
17
- pcs.dataElementCodes = [code_if_present(code_element)]
18
- patient.dataElements << pcs
19
-
20
- pcr = QDM::PatientCharacteristicRace.new
21
- code_element = patient_element.at_xpath('cda:raceCode')
22
- pcr.dataElementCodes = [code_if_present(code_element)]
23
- patient.dataElements << pcr
24
-
25
- pce = QDM::PatientCharacteristicEthnicity.new
26
- code_element = patient_element.at_xpath('cda:ethnicGroupCode')
27
- pce.dataElementCodes = [code_if_present(code_element)]
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
-
42
- def code_if_present(code_element)
43
- return unless code_element && code_element['codeSystem'] && code_element['code']
44
-
45
- QDM::Code.new(code_element['code'], HQMF::Util::CodeSystemHelper.code_system_for(code_element['codeSystem']))
46
- end
47
- end
48
- end
49
- 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,203 +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_qrda_id = extract_id(entry_element, @id_xpath)
42
- # Create a hash to map all of entry.ids to the same QRDA ids. This will be used to merge QRDA entries
43
- # that represent the same event.
44
- @entry_id_map["#{entry_qrda_id.value}_#{entry_qrda_id.namingSystem}"] ||= []
45
- @entry_id_map["#{entry_qrda_id.value}_#{entry_qrda_id.namingSystem}"] << entry.id
46
- entry.dataElementCodes = extract_codes(entry_element, @code_xpath)
47
- extract_dates(entry_element, entry)
48
- if @result_xpath
49
- entry.result = extract_result_values(entry_element)
50
- end
51
- extract_negation(entry_element, entry)
52
- entry
53
- end
54
-
55
- private
56
-
57
- def extract_id(parent_element, id_xpath)
58
- id_element = parent_element.at_xpath(id_xpath)
59
- return unless id_element
60
- # If an extension is not included, use the root as the value. Other wise use the extension
61
- value = id_element['extension'] || id_element['root']
62
- identifier = QDM::Id.new(value: value, namingSystem: id_element['root'])
63
- identifier
64
- end
65
-
66
- def extract_codes(coded_element, code_xpath)
67
- code_list = []
68
- code_elements = coded_element.xpath(code_xpath)
69
- code_elements.each do |code_element|
70
- code_list << code_if_present(code_element)
71
- translations = code_element.xpath('cda:translation')
72
- translations.each do |translation|
73
- code_list << code_if_present(translation)
74
- end
75
- end
76
- code_list.compact
77
- end
78
-
79
- def code_if_present(code_element)
80
- return unless code_element && code_element['codeSystem'] && code_element['code']
81
- QDM::Code.new(code_element['code'], HQMF::Util::CodeSystemHelper.code_system_for(code_element['codeSystem']))
82
- end
83
-
84
- def extract_dates(parent_element, entry)
85
- entry.authorDatetime = extract_time(parent_element, @author_datetime_xpath) if @author_datetime_xpath
86
- entry.relevantPeriod = extract_interval(parent_element, @relevant_period_xpath) if @relevant_period_xpath
87
- entry.prevalencePeriod = extract_interval(parent_element, @prevalence_period_xpath) if @prevalence_period_xpath
88
- end
89
-
90
- def extract_interval(parent_element, interval_xpath)
91
- if parent_element.at_xpath("#{interval_xpath}/@value")
92
- low_time = DateTime.parse(parent_element.at_xpath(interval_xpath)['value'])
93
- high_time = DateTime.parse(parent_element.at_xpath(interval_xpath)['value'])
94
- end
95
- if parent_element.at_xpath("#{interval_xpath}/cda:low")
96
- low_time = if parent_element.at_xpath("#{interval_xpath}/cda:low")['value']
97
- DateTime.parse(parent_element.at_xpath("#{interval_xpath}/cda:low")['value'])
98
- end
99
- end
100
- if parent_element.at_xpath("#{interval_xpath}/cda:high")
101
- high_time = if parent_element.at_xpath("#{interval_xpath}/cda:high")['value']
102
- DateTime.parse(parent_element.at_xpath("#{interval_xpath}/cda:high")['value'])
103
- end
104
- end
105
- if parent_element.at_xpath("#{interval_xpath}/cda:center")
106
- low_time = Time.parse(parent_element.at_xpath("#{interval_xpath}/cda:center")['value'])
107
- high_time = Time.parse(parent_element.at_xpath("#{interval_xpath}/cda:center")['value'])
108
- end
109
- QDM::Interval.new(low_time, high_time).shift_dates(0)
110
- end
111
-
112
- def extract_time(parent_element, datetime_xpath)
113
- DateTime.parse(parent_element.at_xpath(datetime_xpath)['value']) if parent_element.at_xpath("#{datetime_xpath}/@value")
114
- end
115
-
116
- def extract_result_values(parent_element)
117
- result = []
118
- parent_element.xpath(@result_xpath).each do |elem|
119
- result << extract_result_value(elem)
120
- end
121
- result.size > 1 ? result : result.first
122
- end
123
-
124
- def extract_result_value(value_element)
125
- return unless value_element && !value_element['nullFlavor']
126
- value = value_element['value']
127
- if value.present?
128
- return value.strip.to_f if (value_element['unit'] == "1" || value_element['unit'].nil?)
129
- return QDM::Quantity.new(value.strip.to_f, value_element['unit'])
130
- elsif value_element['code'].present?
131
- return code_if_present(value_element)
132
- end
133
- end
134
-
135
- def extract_reason(parent_element)
136
- return unless @reason_xpath
137
- reason_element = parent_element.xpath(@reason_xpath)
138
- negation_indicator = parent_element['negationInd']
139
- # Return and do not set reason attribute if the entry is negated
140
- return nil if negation_indicator.eql?('true')
141
-
142
- reason_element.blank? ? nil : code_if_present(reason_element.first)
143
- end
144
-
145
- def extract_negation(parent_element, entry)
146
- negation_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")
147
- negation_indicator = parent_element['negationInd']
148
- # Return and do not set negationRationale attribute if the entry is not negated
149
- return unless negation_indicator.eql?('true')
150
-
151
- entry.negationRationale = code_if_present(negation_element.first) unless negation_element.blank?
152
- extract_negated_code(parent_element, entry)
153
- end
154
-
155
- def extract_negated_code(parent_element, entry)
156
- code_elements = parent_element.xpath(@code_xpath)
157
- code_elements.each do |code_element|
158
- if code_element['nullFlavor'] == 'NA' && code_element['sdtc:valueSet']
159
- entry.dataElementCodes = [{ code: code_element['sdtc:valueSet'], codeSystem: 'NA_VALUESET' }]
160
- end
161
- end
162
- end
163
-
164
- def extract_scalar(parent_element, scalar_xpath)
165
- scalar_element = parent_element.at_xpath(scalar_xpath)
166
- return unless scalar_element
167
- QDM::Quantity.new(scalar_element['value'].to_f, scalar_element['unit'])
168
- end
169
-
170
- def extract_components(parent_element)
171
- component_elements = parent_element.xpath(@components_xpath)
172
- components = []
173
- component_elements&.each do |component_element|
174
- component = QDM::Component.new
175
- component.code = code_if_present(component_element.at_xpath('./cda:code'))
176
- component.result = extract_result_value(component_element.at_xpath('./cda:value'))
177
- components << component
178
- end
179
- components
180
- end
181
-
182
- def extract_facility(parent_element, entry)
183
- facility_element = parent_element.at_xpath(@facility_xpath)
184
- return unless facility_element
185
- facility = QDM::FacilityLocation.new
186
- participant_element = facility_element.at_xpath("./cda:participantRole[@classCode='SDLOC']/cda:code")
187
- facility.code = code_if_present(participant_element)
188
- facility.locationPeriod = extract_interval(facility_element, './cda:time')
189
- entry.facilityLocations = [facility]
190
- end
191
-
192
- def extract_related_to(parent_element)
193
- related_to_elements = parent_element.xpath(@related_to_xpath)
194
- related_ids = []
195
- related_to_elements.each do |related_to_element|
196
- related_ids << extract_id(related_to_element, './sdtc:id')
197
- end
198
- related_ids
199
- end
200
-
201
- end
202
- end
203
- 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