health-data-standards 0.8.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/Rakefile +1 -1
  2. data/lib/health-data-standards/export/ccr.rb +1 -1
  3. data/lib/health-data-standards/export/csv.rb +6 -1
  4. data/lib/health-data-standards/export/green_c32/entry.rb +1 -1
  5. data/lib/health-data-standards/export/green_c32/record.rb +15 -0
  6. data/lib/health-data-standards/export/template_helper.rb +0 -2
  7. data/lib/health-data-standards/export/view_helper.rb +28 -2
  8. data/lib/health-data-standards/import/c32/allergy_importer.rb +12 -8
  9. data/lib/health-data-standards/import/c32/care_goal_importer.rb +39 -0
  10. data/lib/health-data-standards/import/c32/condition_importer.rb +10 -4
  11. data/lib/health-data-standards/import/c32/encounter_importer.rb +16 -10
  12. data/lib/health-data-standards/import/c32/immunization_importer.rb +2 -2
  13. data/lib/health-data-standards/import/c32/insurance_provider_importer.rb +42 -0
  14. data/lib/health-data-standards/import/c32/medical_equipment_importer.rb +45 -0
  15. data/lib/health-data-standards/import/c32/medication_importer.rb +35 -48
  16. data/lib/health-data-standards/import/c32/organization_importer.rb +1 -1
  17. data/lib/health-data-standards/import/c32/patient_importer.rb +3 -3
  18. data/lib/health-data-standards/import/c32/procedure_importer.rb +12 -8
  19. data/lib/health-data-standards/import/c32/result_importer.rb +11 -14
  20. data/lib/health-data-standards/import/c32/section_importer.rb +60 -29
  21. data/lib/health-data-standards/import/ccda/allergy_importer.rb +20 -0
  22. data/lib/health-data-standards/import/ccda/care_goal_importer.rb +13 -0
  23. data/lib/health-data-standards/import/ccda/condition_importer.rb +20 -0
  24. data/lib/health-data-standards/import/ccda/encounter_importer.rb +18 -0
  25. data/lib/health-data-standards/import/ccda/immunization_importer.rb +16 -0
  26. data/lib/health-data-standards/import/ccda/insurance_provider_importer.rb +14 -0
  27. data/lib/health-data-standards/import/ccda/medical_equipment_importer.rb +16 -0
  28. data/lib/health-data-standards/import/ccda/medication_importer.rb +19 -0
  29. data/lib/health-data-standards/import/ccda/patient_importer.rb +29 -0
  30. data/lib/health-data-standards/import/ccda/procedure_importer.rb +17 -0
  31. data/lib/health-data-standards/import/ccda/result_importer.rb +13 -0
  32. data/lib/health-data-standards/import/ccda/vital_sign_importer.rb +12 -0
  33. data/lib/health-data-standards/import/ccr/patient_importer.rb +16 -3
  34. data/lib/health-data-standards/import/green_c32/advance_directive_importer.rb +14 -0
  35. data/lib/health-data-standards/import/green_c32/allergy_importer.rb +1 -1
  36. data/lib/health-data-standards/import/green_c32/care_goal_importer.rb +26 -0
  37. data/lib/health-data-standards/import/green_c32/condition_importer.rb +0 -6
  38. data/lib/health-data-standards/import/green_c32/encounter_importer.rb +1 -6
  39. data/lib/health-data-standards/import/green_c32/immunization_importer.rb +1 -1
  40. data/lib/health-data-standards/import/green_c32/medical_equipment_importer.rb +24 -0
  41. data/lib/health-data-standards/import/green_c32/medication_importer.rb +1 -1
  42. data/lib/health-data-standards/import/green_c32/procedure_importer.rb +2 -10
  43. data/lib/health-data-standards/import/green_c32/section_importer.rb +36 -5
  44. data/lib/health-data-standards/import/green_c32/social_history_importer.rb +1 -6
  45. data/lib/health-data-standards/import/green_c32/support_importer.rb +22 -0
  46. data/lib/health-data-standards/models/allergy.rb +1 -1
  47. data/lib/health-data-standards/models/condition.rb +3 -1
  48. data/lib/health-data-standards/models/encounter.rb +1 -3
  49. data/lib/health-data-standards/models/entry.rb +23 -21
  50. data/lib/health-data-standards/models/guarantor.rb +10 -0
  51. data/lib/health-data-standards/models/insurance_provider.rb +17 -0
  52. data/lib/health-data-standards/models/medical_equipment.rb +5 -0
  53. data/lib/health-data-standards/models/medication.rb +0 -2
  54. data/lib/health-data-standards/models/person.rb +4 -0
  55. data/lib/health-data-standards/models/personable.rb +13 -0
  56. data/lib/health-data-standards/models/procedure.rb +0 -2
  57. data/lib/health-data-standards/models/provider.rb +1 -6
  58. data/lib/health-data-standards/models/record.rb +11 -5
  59. data/lib/health-data-standards/models/support.rb +18 -0
  60. data/lib/health-data-standards.rb +28 -2
  61. data/templates/_advance_directive.gc32.erb +8 -0
  62. data/templates/_allergy.gc32.erb +17 -7
  63. data/templates/_care_goal.gc32.erb +8 -0
  64. data/templates/_condition.gc32.erb +4 -6
  65. data/templates/_conditions.c32.erb +3 -0
  66. data/templates/_encounter.gc32.erb +1 -7
  67. data/templates/_entry.gc32.erb +14 -0
  68. data/templates/_immunization.gc32.erb +4 -2
  69. data/templates/_insurance_provider.gc32.erb +0 -0
  70. data/templates/_medical_equipment.c32.erb +6 -0
  71. data/templates/_medical_equipment.gc32.erb +7 -0
  72. data/templates/_medication.gc32.erb +26 -14
  73. data/templates/_medications_no_current.c32.erb +26 -6
  74. data/templates/_name.gc32.erb +11 -0
  75. data/templates/_narrative_block.c32.erb +1 -1
  76. data/templates/_procedure.gc32.erb +6 -4
  77. data/templates/_result.gc32.erb +2 -8
  78. data/templates/_results.c32.erb +8 -2
  79. data/templates/_social_history.gc32.erb +3 -1
  80. data/templates/_support.gc32.erb +14 -0
  81. data/templates/_vital_sign.gc32.erb +2 -7
  82. data/templates/_vital_signs.c32.erb +8 -2
  83. data/templates/record.gc32.erb +81 -0
  84. data/templates/show.c32.erb +1 -1
  85. metadata +48 -16
  86. data/lib/health-data-standards/models/comment.rb +0 -2
  87. data/lib/health-data-standards/models/social_history.rb +0 -3
@@ -15,10 +15,11 @@ module HealthDataStandards
15
15
  # @param [String] status_xpath XPath expression to find the status element as a child of the desired CDA
16
16
  # entry. Defaults to nil. If not provided, a status will not be checked for since it is not applicable
17
17
  # to all enrty types
18
- def initialize(entry_xpath, code_xpath="./cda:code", status_xpath=nil, description_xpath="./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] ")
18
+ def initialize(entry_xpath, code_xpath="./cda:code", status_xpath=nil,priority_xpath=nil, description_xpath="./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] ")
19
19
  @entry_xpath = entry_xpath
20
20
  @code_xpath = code_xpath
21
21
  @status_xpath = status_xpath
22
+ @priority_xpath = priority_xpath
22
23
  @description_xpath = description_xpath
23
24
  @check_for_usable = true # Pilot tools will set this to false
24
25
  end
@@ -48,16 +49,7 @@ module HealthDataStandards
48
49
  entry_list = []
49
50
  entry_elements = doc.xpath(@entry_xpath)
50
51
  entry_elements.each do |entry_element|
51
- entry = Entry.new
52
- extract_codes(entry_element, entry)
53
- extract_dates(entry_element, entry)
54
- extract_value(entry_element, entry)
55
- if @status_xpath
56
- extract_status(entry_element, entry)
57
- end
58
- if @description_xpath
59
- extract_description(entry_element, entry, id_map)
60
- end
52
+ entry = create_entry(entry_element, id_map)
61
53
  if @check_for_usable
62
54
  entry_list << entry if entry.usable?
63
55
  else
@@ -66,6 +58,23 @@ module HealthDataStandards
66
58
  end
67
59
  entry_list
68
60
  end
61
+
62
+ def create_entry(entry_element, id_map={})
63
+ entry = Entry.new
64
+ extract_codes(entry_element, entry)
65
+ extract_dates(entry_element, entry)
66
+ extract_value(entry_element, entry)
67
+ if @status_xpath
68
+ extract_status(entry_element, entry)
69
+ end
70
+ if @priority_xpath
71
+ extract_priority(entry_element, entry)
72
+ end
73
+ if @description_xpath
74
+ extract_description(entry_element, entry, id_map)
75
+ end
76
+ entry
77
+ end
69
78
 
70
79
  private
71
80
 
@@ -83,6 +92,17 @@ module HealthDataStandards
83
92
  end
84
93
  end
85
94
 
95
+ def extract_priority(parent_element, entry)
96
+ priority_element = parent_element.at_xpath(@priority_xpath)
97
+ if priority_element
98
+ case priority_element['code']
99
+ when '8319008'
100
+ entry.ordinality = :principal
101
+ end
102
+ end
103
+ end
104
+
105
+
86
106
  def extract_description(parent_element, entry, id_map)
87
107
  code_elements = parent_element.xpath(@description_xpath)
88
108
  code_elements.each do |code_element|
@@ -108,18 +128,18 @@ module HealthDataStandards
108
128
  end
109
129
  end
110
130
 
111
- def extract_dates(parent_element, entry)
112
- if parent_element.at_xpath('cda:effectiveTime')
113
- entry.time = HL7Helper.timestamp_to_integer(parent_element.at_xpath('cda:effectiveTime')['value'])
131
+ def extract_dates(parent_element, entry, element_name="effectiveTime")
132
+ if parent_element.at_xpath("cda:#{element_name}")
133
+ entry.time = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}")['value'])
114
134
  end
115
- if parent_element.at_xpath('cda:effectiveTime/cda:low')
116
- entry.start_time = HL7Helper.timestamp_to_integer(parent_element.at_xpath('cda:effectiveTime/cda:low')['value'])
135
+ if parent_element.at_xpath("cda:#{element_name}/cda:low")
136
+ entry.start_time = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}/cda:low")['value'])
117
137
  end
118
- if parent_element.at_xpath('cda:effectiveTime/cda:high')
119
- entry.end_time = HL7Helper.timestamp_to_integer(parent_element.at_xpath('cda:effectiveTime/cda:high')['value'])
138
+ if parent_element.at_xpath("cda:#{element_name}/cda:high")
139
+ entry.end_time = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}/cda:high")['value'])
120
140
  end
121
- if parent_element.at_xpath('cda:effectiveTime/cda:center')
122
- entry.time = HL7Helper.timestamp_to_integer(parent_element.at_xpath('cda:effectiveTime/cda:center')['value'])
141
+ if parent_element.at_xpath("cda:#{element_name}/cda:center")
142
+ entry.time = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}/cda:center")['value'])
123
143
  end
124
144
  end
125
145
 
@@ -128,24 +148,35 @@ module HealthDataStandards
128
148
  if value_element
129
149
  value = value_element['value']
130
150
  unit = value_element['unit']
151
+ value ||= value_element.text
131
152
  if value
132
- entry.set_value(value, unit)
153
+ entry.set_value(value.strip, unit)
133
154
  end
155
+
134
156
  end
135
157
  end
136
158
 
137
159
  def import_actor(actor_element)
138
160
  return ProviderImporter.instance.extract_provider(actor_element)
139
161
  end
162
+
163
+ def import_organization(organization_element)
164
+ return OrganizationImporter.instance.extract_organization(organization_element)
165
+ end
140
166
 
141
- # def import_person(person_element)
142
- # person_hash = {}
143
- # name_element = person_element.at_xpath("./cda:name")
144
- # person_hash['name'] = name_element.try(:text)
145
- # person_hash['first'] = name_element.at_xpath("./cda:given").try(:text)
146
- # person_hash['last'] = name_element.at_xpath("./cda:family").try(:text)
147
- # person_hash
148
- # end
167
+ def import_person(person_element)
168
+ return unless person_element
169
+ person = Person.new
170
+ name_element = person_element.at_xpath("./cda:name")
171
+ if name_element
172
+ person.title = name_element.at_xpath("./cda:title").try(:text)
173
+ person.given_name = name_element.at_xpath("./cda:given").try(:text)
174
+ person.family_name = name_element.at_xpath("./cda:family").try(:text)
175
+ end
176
+ person.addresses = person_element.xpath("./cda:addr").map { |addr| import_address(addr) }
177
+ person.telecoms = person_element.xpath("./cda:telecom").map { |tele| import_telecom(tele) }
178
+ return person
179
+ end
149
180
 
150
181
  def import_address(address_element)
151
182
  address = Address.new
@@ -0,0 +1,20 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+ class AllergyImporter < C32::AllergyImporter
5
+
6
+
7
+ def initialize
8
+ @entry_xpath = "//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.7']"
9
+ @code_xpath = "./cda:participant/cda:participantRole/cda:playingEntity/cda:code"
10
+ @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value]"
11
+ @type_xpath = "./cda:code"
12
+ @reaction_xpath = "./cda:entryRelationship[@typeCode='MFST']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.9']/cda:value"
13
+ @severity_xpath = "./cda:entryRelationship[@typeCode='SUBJ']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.8']/cda:value"
14
+ @status_xpath = "./cda:entryRelationship[@typeCode='SUBJ']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.28']/cda:value"
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+ class CareGoalImporter < C32::CareGoalImporter
5
+
6
+ def initialize
7
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.10']/cda:entry/cda:*"
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+ class ConditionImporter < C32::ConditionImporter
5
+
6
+ def initialize
7
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.5' or cda:templateId/@root='2.16.840.1.113883.10.20.22.2.5.1']/cda:entry/cda:act/cda:entryRelationship/cda:observation"
8
+ @status_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.6']/cda:value"
9
+ @description_xpath = "./cda:text/cda:reference[@value]"
10
+ @code_xpath = "./cda:value"
11
+
12
+ #optional
13
+ #health status
14
+ #age at onset
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+ # TODO Extract Discharge Disposition
5
+ class EncounterImporter < C32::EncounterImporter
6
+
7
+ def initialize
8
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.22' or cda:templateId/@root='2.16.840.1.113883.10.20.22.2.22.1']/cda:entry/cda:encounter"
9
+ @code_xpath = "./cda:code"
10
+ @status_xpath = "./cda:statusCode"
11
+ @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
12
+ @reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation"
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+ class ImmunizationImporter < C32::ImmunizationImporter
5
+
6
+ def initialize
7
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.2' or cda:templateId/@root='2.16.840.1.113883.10.20.22.2.2.1']/cda:entry/cda:substanceAdministration"
8
+ @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
9
+ @description_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code/cda:originalText/cda:reference[@value]"
10
+ @refusal_reason_xpath = "./cda:entryRelationship[@typeCode='MFST']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.9']/cda:value"
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+ class InsuranceProviderImporter < C32::InsuranceProviderImporter
5
+
6
+ def initialize
7
+ @entry_xpath = "//cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.61']"
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,16 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+ class MedicalEquipmentImporter < C32::MedicalEquipmentImporter
5
+
6
+ def initialize
7
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.50']/cda:entry/cda:supply"
8
+ @code_xpath = "./cda:participant/cda:participantRole/cda:playingDevice/cda:code"
9
+ @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value]"
10
+
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+
5
+ class MedicationImporter < C32::MedicationImporter
6
+
7
+ def initialize
8
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.1' or cda:templateId/@root='2.16.840.1.113883.10.20.22.2.1.1']/cda:entry/cda:substanceAdministration"
9
+ @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
10
+ @description_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code/cda:originalText/cda:reference[@value]"
11
+ @indication_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.19']/cda:code"
12
+ @vehicle_xpath = "./cda:participant/cda:participantRole[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.24']/cda:playingEntity/cda:code"
13
+ @fill_number_xpath = './cda:repeatNumber'
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,29 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+ class PatientImporter < C32::PatientImporter
5
+
6
+ def initialize(check_usable = true)
7
+ @section_importers = {}
8
+ @section_importers[:encounters] = EncounterImporter.new
9
+ @section_importers[:procedures] = ProcedureImporter.new
10
+ @section_importers[:results] = ResultImporter.new
11
+ @section_importers[:vital_signs] = VitalSignImporter.new
12
+ @section_importers[:medications] = MedicationImporter.new
13
+ @section_importers[:conditions] = ConditionImporter.new
14
+ @section_importers[:social_history] = C32::SectionImporter.new("//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.38' or cda:templateId/@root='2.16.840.1.113883.10.20.15.3.8']")
15
+ @section_importers[:care_goals] = CareGoalImporter.new
16
+ @section_importers[:medical_equipment] = MedicalEquipmentImporter.new
17
+ @section_importers[:allergies] = AllergyImporter.new
18
+ @section_importers[:immunizations] = ImmunizationImporter.new
19
+ @section_importers[:insurance_providers] = InsuranceProviderImporter.new
20
+ end
21
+
22
+ def parse_ccda(doc)
23
+ parse_c32(doc)
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+ class ProcedureImporter < C32::ProcedureImporter
5
+
6
+ def initialize
7
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.7' or cda:templateId/@root='2.16.840.1.113883.10.20.22.2.7.1']/cda:entry/cda:*"
8
+ @code_xpath = "./cda:code"
9
+ @status_xpath = "./cda:statusCode"
10
+ @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
11
+ @check_for_usable = true # Pilot tools will set this to false
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+ class ResultImporter < C32::ResultImporter
5
+ def initialize
6
+ @entry_xpath = "//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.2']"
7
+ @code_xpath = "./cda:code"
8
+ @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module CCDA
4
+ class VitalSignImporter < C32::VitalSignImporter
5
+ def initialize
6
+ super
7
+ @entry_xpath = "//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.27']"
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -188,9 +188,22 @@ module HealthDataStandards
188
188
  patientActor = doc.at_xpath("//ccr:ContinuityOfCareRecord/ccr:Actors/ccr:Actor[ccr:ActorObjectID = \"#{patientActorID}\"]")
189
189
  patientID = patientActor.at_xpath(patient_id_xpath).try(:content)
190
190
  patientID ||= patientActorID
191
-
192
- patient['first'] = patientActor.at_xpath('./ccr:Person/ccr:Name/ccr:CurrentName/ccr:Given').content
193
- patient['last'] = patientActor.at_xpath('./ccr:Person/ccr:Name/ccr:CurrentName/ccr:Family').content
191
+
192
+ name_element = patientActor.at_xpath('./ccr:Person/ccr:Name')
193
+
194
+ if name_element
195
+ if name_element.at_xpath("./ccr:CurrentName")
196
+ patient['first'] = name_element.at_xpath('./ccr:CurrentName/ccr:Given').try(:content)
197
+ patient['last'] = name_element.at_xpath('./ccr:CurrentName/ccr:Family').try(:content)
198
+ elsif name_element.at_xpath("./ccr:DisplayName")
199
+ # this will not work in all cases, but we're using it as a last resort if no CurrentName is found
200
+ first, last = name_element.at_xpath("./ccr:DisplayName").content.split(" ")
201
+ patient['first'] = first.strip
202
+ patient['last'] = last.strip
203
+ end
204
+ end
205
+
206
+
194
207
  birthdate = patientActor.at_xpath('./ccr:Person//ccr:DateOfBirth/ccr:ExactDateTime | ./ccr:Person//ccr:DateOfBirth/ccr:ApproximateDateTime')
195
208
  patient['birthdate'] = Time.parse(birthdate.content).to_i if birthdate
196
209
 
@@ -0,0 +1,14 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module GreenC32
4
+ class AdvanceDirectiveImporter < SectionImporter
5
+ include Singleton
6
+
7
+ def import(ad_xml)
8
+ generic_import(ad_xml, "advanceDirective")
9
+ end
10
+
11
+ end
12
+ end
13
+ end
14
+ end
@@ -9,7 +9,7 @@ module HealthDataStandards
9
9
  allergy_element = allergy_xml.xpath("./gc32:allergy")
10
10
  allergy = Allergy.new
11
11
  extract_entry(allergy_element, allergy)
12
- allergy.type = extract_node_text(allergy_element.at_xpath("./gc32:type"))
12
+ extract_code(allergy_element, allergy, "./gc32:type", :type)
13
13
  extract_code(allergy_element, allergy, "./gc32:reaction", :reaction)
14
14
  extract_code(allergy_element, allergy, "./gc32:severity", :severity)
15
15
  allergy
@@ -0,0 +1,26 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module GreenC32
4
+ class CareGoalImporter
5
+ include Singleton
6
+
7
+ def initialize
8
+ end
9
+
10
+ def import(care_goal_xml)
11
+ importer = case care_goal_xml.at_xpath("/*").try(:name)
12
+ when "medication" then MedicationImporter.instance
13
+ when "immunization" then ImmunizationImporter.instance
14
+ when "procedure" then ProcedureImporter.instance
15
+ when "encounter" then EncounterImporter.instance
16
+ when "medicalEquipment" then MedicalEquipmentImporter.instance
17
+ else SectionImporter.new
18
+ end
19
+
20
+ return importer.import(care_goal_xml)
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -15,7 +15,6 @@ module HealthDataStandards
15
15
  condition = Condition.new
16
16
 
17
17
  extract_entry(condition_element, condition)
18
- extract_name(condition_element, condition)
19
18
  extract_cause_of_death(condition_element, condition)
20
19
  extract_type(condition_element, condition)
21
20
 
@@ -29,11 +28,6 @@ module HealthDataStandards
29
28
  condition.type = extract_node_text(type)
30
29
  end
31
30
 
32
- def extract_name(condition_xml, condition)
33
- name = condition_xml.xpath("./gc32:name").first
34
- condition.name = extract_node_text(name)
35
- end
36
-
37
31
  def extract_cause_of_death(condition_xml, condition)
38
32
  condition.cause_of_death = extract_node_attribute(condition_xml, "causeOfDeath")
39
33
  end
@@ -18,12 +18,7 @@ module HealthDataStandards
18
18
  extract_code(encounter_element, encounter, "./gc32:reasonForVisit", :reason)
19
19
  extract_code(encounter_element, encounter)
20
20
  extract_facility(encounter_element, encounter)
21
-
22
- free_text = encounter_element.xpath("./gc32:freeText").first
23
-
24
- if free_text
25
- encounter.free_text = free_text.content
26
- end
21
+ extract_free_text(encounter_element, encounter)
27
22
 
28
23
  encounter
29
24
  end
@@ -9,7 +9,7 @@ module HealthDataStandards
9
9
  immunization_element = immunization_xml.at_xpath("./gc32:immunization")
10
10
  immunization = Immunization.new
11
11
  extract_entry(immunization_element, immunization)
12
- extract_time(immunization_element, immunization, "./gc32:administeredDate")
12
+ extract_time(immunization_element, immunization, "./gc32:effectiveTime")
13
13
  extract_code(immunization_element, immunization, "./gc32:refusalReason")
14
14
  series_number = extract_node_text(immunization_element.at_xpath("./gc32:seriesNumber"))
15
15
  immunization.series_number = series_number.to_i if series_number
@@ -0,0 +1,24 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module GreenC32
4
+ class MedicalEquipmentImporter < SectionImporter
5
+ include Singleton
6
+
7
+ def initialize
8
+ super
9
+ @value = "./gc32:quantity"
10
+ end
11
+
12
+ def import(me_xml)
13
+ me_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
14
+ me_element = me_xml.at_xpath("./gc32:medicalEquipment")
15
+ me = MedicalEquipment.new
16
+ extract_entry(me_element, me)
17
+ me.manufacturer = extract_node_text(me_element.at_xpath("./gc32:manufacturer")).try(:strip)
18
+ me
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -22,7 +22,7 @@ module HealthDataStandards
22
22
  extract_med_code_attribute(med_element, medication, :vehicle)
23
23
  extract_med_code_attribute(med_element, medication, :reaction)
24
24
  extract_med_code_attribute(med_element, medication, :deliveryMethod)
25
- medication.free_text_sig = extract_node_text(med_element.at_xpath("./gc32:freeTextSig"))
25
+ extract_free_text(med_element, medication, "freeTextSig")
26
26
  medication.fulfillment_instructions = extract_node_text(med_element.at_xpath("./gc32:patientInstructions"))
27
27
  medication.dose_indicator = extract_node_text(med_element.at_xpath("./gc32:doseIndicator"))
28
28
  medication.fulfillment_history = extract_fulfillment_history(med_element)
@@ -17,18 +17,10 @@ module HealthDataStandards
17
17
  procedure = Procedure.new
18
18
 
19
19
  extract_entry(procedure_element, procedure)
20
- extract_type(procedure_element, procedure)
21
-
20
+ extract_code(procedure_element, procedure, xpath="./gc32:site", attribute=:site)
22
21
  procedure
23
22
  end
24
-
25
- private
26
-
27
- def extract_type(procedure_xml, procedure)
28
- type = procedure_xml.xpath("./gc32:type").first
29
- procedure.type = extract_node_text(type)
30
- end
31
-
23
+
32
24
  end
33
25
  end
34
26
  end
@@ -11,9 +11,22 @@ module HealthDataStandards
11
11
  @value = "./gc32:value"
12
12
  end
13
13
 
14
+
15
+ def import(entry_xml)
16
+ generic_import(entry_xml)
17
+ end
18
+
19
+ def generic_import(element_xml, element_name="entry")
20
+ entry = Entry.new
21
+ element_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
22
+ element = element_xml.at_xpath("./gc32:#{element_name}")
23
+ extract_entry(element, entry)
24
+ entry
25
+ end
26
+
14
27
  def extract_code(element, entry, xpath="./gc32:code", attribute=:codes)
15
28
 
16
- code_element = element.xpath(xpath).first
29
+ code_element = element.at_xpath(xpath)
17
30
 
18
31
  return unless code_element
19
32
 
@@ -27,12 +40,12 @@ module HealthDataStandards
27
40
  end
28
41
 
29
42
  def extract_description(element, entry)
30
- description = element.xpath(@description).first
43
+ description = element.at_xpath(@description)
31
44
  entry.description = extract_node_text(description)
32
45
  end
33
46
 
34
47
  def extract_status(element, entry)
35
- status = extract_node_text(element.xpath(@status).first)
48
+ status = extract_node_text(element.at_xpath(@status))
36
49
  return unless status
37
50
  entry.status = status
38
51
  end
@@ -45,10 +58,20 @@ module HealthDataStandards
45
58
  end
46
59
  end
47
60
 
61
+ def extract_name(element, entry, name_element="name")
62
+ name_element = element.at_xpath("./gc32:#{name_element}")
63
+ return unless name_element
64
+ entry.title = name_element.at_xpath("./gc32:title").try(:content)
65
+ entry.given_name = name_element.at_xpath("./gc32:givenName").try(:content)
66
+ entry.family_name = name_element.at_xpath("./gc32:familyName").try(:content)
67
+ end
68
+
48
69
  def extract_time(element, entry, xpath = "./gc32:effectiveTime", attribute = "time")
49
70
  datetime = element.at_xpath(xpath)
50
- return unless datetime && !datetime.inner_text.empty?
51
- entry.send("#{attribute}=", Time.parse(datetime.inner_text).to_i)
71
+
72
+ return unless datetime && datetime['value']
73
+
74
+ entry.send("#{attribute}=", Time.parse(datetime['value']).to_i)
52
75
  end
53
76
 
54
77
  def extract_interval(element, entry, element_name="effectiveTime")
@@ -79,6 +102,8 @@ module HealthDataStandards
79
102
  extract_status(element, entry)
80
103
  extract_value(element, entry)
81
104
  extract_effective_time(element, entry)
105
+ entry.free_text = element.at_xpath("./gc32:freeText").try(:inner_text)
106
+ entry
82
107
  end
83
108
 
84
109
  def extract_organization(organization_element)
@@ -96,6 +121,7 @@ module HealthDataStandards
96
121
  end
97
122
 
98
123
  def extract_address(address_element)
124
+ return unless address_element
99
125
  address = Address.new
100
126
  address.street = address_element.xpath("./gc32:street").map { |st| extract_node_text(st) }
101
127
  address.city = extract_node_text(address_element.xpath("./gc32:city"))
@@ -105,6 +131,7 @@ module HealthDataStandards
105
131
  end
106
132
 
107
133
  def extract_telecom(telecom_element)
134
+ return unless telecom_element
108
135
  telecom = Telecom.new
109
136
  telecom.use = extract_node_attribute(telecom_element, :type)
110
137
  telecom.value = extract_node_attribute(telecom_element, :value)
@@ -112,6 +139,10 @@ module HealthDataStandards
112
139
  telecom
113
140
  end
114
141
 
142
+ def extract_free_text(element, entry, free_text_element="freeText")
143
+ entry.free_text = extract_node_text(element.at_xpath("./gc32:#{free_text_element}"))
144
+ end
145
+
115
146
 
116
147
  private
117
148