health-data-standards 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +9 -1
- data/Rakefile +14 -4
- data/lib/health-data-standards.rb +23 -0
- data/lib/health-data-standards/export/ccr.rb +55 -56
- data/lib/health-data-standards/export/hdata/metadata.rb +16 -0
- data/lib/health-data-standards/export/html.rb +21 -0
- data/lib/health-data-standards/export/template_helper.rb +3 -0
- data/lib/health-data-standards/export/view_helper.rb +29 -5
- data/lib/health-data-standards/import/c32/condition_importer.rb +31 -33
- data/lib/health-data-standards/import/c32/encounter_importer.rb +4 -6
- data/lib/health-data-standards/import/c32/medication_importer.rb +1 -5
- data/lib/health-data-standards/import/c32/organization_importer.rb +23 -0
- data/lib/health-data-standards/import/c32/patient_importer.rb +1 -4
- data/lib/health-data-standards/import/c32/provider_importer.rb +43 -30
- data/lib/health-data-standards/import/c32/section_importer.rb +20 -41
- data/lib/health-data-standards/import/ccr/patient_importer.rb +27 -10
- data/lib/health-data-standards/import/ccr/provider_importer.rb +29 -41
- data/lib/health-data-standards/import/ccr/section_importer.rb +38 -27
- data/lib/health-data-standards/import/green_c32/allergy_importer.rb +20 -0
- data/lib/health-data-standards/import/green_c32/condition_importer.rb +2 -3
- data/lib/health-data-standards/import/green_c32/encounter_importer.rb +42 -0
- data/lib/health-data-standards/import/green_c32/immunization_importer.rb +23 -0
- data/lib/health-data-standards/import/green_c32/medication_importer.rb +69 -0
- data/lib/health-data-standards/import/green_c32/procedure_importer.rb +35 -0
- data/lib/health-data-standards/import/green_c32/result_importer.rb +21 -8
- data/lib/health-data-standards/import/green_c32/section_importer.rb +55 -9
- data/lib/health-data-standards/import/green_c32/social_history_importer.rb +18 -0
- data/lib/health-data-standards/import/green_c32/vital_sign_importer.rb +21 -0
- data/lib/health-data-standards/import/hdata/metadata_importer.rb +82 -0
- data/lib/health-data-standards/import/provider_import_utils.rb +23 -0
- data/lib/health-data-standards/models/address.rb +11 -0
- data/lib/health-data-standards/models/allergy.rb +1 -0
- data/lib/health-data-standards/models/condition.rb +1 -1
- data/lib/health-data-standards/models/encounter.rb +11 -6
- data/lib/health-data-standards/models/entry.rb +16 -5
- data/lib/health-data-standards/models/fulfillment_history.rb +3 -5
- data/lib/health-data-standards/models/immunization.rb +7 -1
- data/lib/health-data-standards/models/medication.rb +4 -3
- data/lib/health-data-standards/models/metadata/author.rb +16 -0
- data/lib/health-data-standards/models/metadata/base.rb +20 -0
- data/lib/health-data-standards/models/metadata/change_info.rb +9 -0
- data/lib/health-data-standards/models/metadata/link_info.rb +9 -0
- data/lib/health-data-standards/models/metadata/pedigree.rb +15 -0
- data/lib/health-data-standards/models/organization.rb +8 -0
- data/lib/health-data-standards/models/procedure.rb +5 -2
- data/lib/health-data-standards/models/provider.rb +6 -1
- data/lib/health-data-standards/models/record.rb +13 -3
- data/lib/health-data-standards/models/social_history.rb +3 -0
- data/lib/health-data-standards/models/telecom.rb +9 -0
- data/lib/health-data-standards/models/vital_sign.rb +2 -0
- data/lib/health-data-standards/util/code_system_helper.rb +3 -1
- data/templates/_address.gc32.erb +9 -0
- data/templates/_allergies.c32.erb +2 -2
- data/templates/_allergy.gc32.erb +13 -0
- data/templates/_care_goals.c32.erb +1 -1
- data/templates/_condition.gc32.erb +6 -6
- data/templates/_conditions.c32.erb +2 -2
- data/templates/_encounter.gc32.erb +32 -0
- data/templates/_encounters.c32.erb +1 -1
- data/templates/_immunization.gc32.erb +9 -0
- data/templates/_immunizations.c32.erb +1 -1
- data/templates/_medical_equipment.c32.erb +1 -1
- data/templates/_medication.gc32.erb +60 -0
- data/templates/_medications.c32.erb +1 -1
- data/templates/_narrative_block.c32.erb +1 -1
- data/templates/_organization.gc32.erb +10 -0
- data/templates/_pedigree.hdata.erb +24 -0
- data/templates/_procedure.gc32.erb +8 -0
- data/templates/_procedures.c32.erb +1 -1
- data/templates/_provider.gc32.erb +19 -0
- data/templates/_results.c32.erb +1 -1
- data/templates/_social_history.c32.erb +1 -1
- data/templates/_social_history.gc32.erb +6 -0
- data/templates/_telecom.gc32.erb +1 -0
- data/templates/_vital_sign.gc32.erb +12 -0
- data/templates/_vital_signs.c32.erb +1 -1
- data/templates/metadata.hdata.erb +35 -0
- data/templates/show.html.erb +287 -0
- metadata +50 -15
@@ -0,0 +1,20 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module GreenC32
|
4
|
+
class AllergyImporter < SectionImporter
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def import(allergy_xml)
|
8
|
+
allergy_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
|
9
|
+
allergy_element = allergy_xml.xpath("./gc32:allergy")
|
10
|
+
allergy = Allergy.new
|
11
|
+
extract_entry(allergy_element, allergy)
|
12
|
+
allergy.type = extract_node_text(allergy_element.at_xpath("./gc32:type"))
|
13
|
+
extract_code(allergy_element, allergy, "./gc32:reaction", :reaction)
|
14
|
+
extract_code(allergy_element, allergy, "./gc32:severity", :severity)
|
15
|
+
allergy
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -10,16 +10,15 @@ module HealthDataStandards
|
|
10
10
|
|
11
11
|
def import(condition_xml)
|
12
12
|
condition_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
|
13
|
-
|
14
13
|
condition_element = condition_xml.xpath("./gc32:condition")
|
15
14
|
|
16
15
|
condition = Condition.new
|
17
|
-
|
16
|
+
|
18
17
|
extract_entry(condition_element, condition)
|
19
18
|
extract_name(condition_element, condition)
|
20
|
-
extract_interval(condition_element, condition)
|
21
19
|
extract_cause_of_death(condition_element, condition)
|
22
20
|
extract_type(condition_element, condition)
|
21
|
+
|
23
22
|
condition
|
24
23
|
end
|
25
24
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module GreenC32
|
4
|
+
class EncounterImporter < SectionImporter
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def import(encounter_xml)
|
12
|
+
encounter = Encounter.new
|
13
|
+
encounter_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
|
14
|
+
encounter_element = encounter_xml.xpath("/gc32:encounter")
|
15
|
+
extract_entry(encounter_element, encounter)
|
16
|
+
extract_code(encounter_element, encounter, "./gc32:dischargeDisposition", :discharge_disposition)
|
17
|
+
extract_code(encounter_element, encounter, "./gc32:admissionType", :admit_type)
|
18
|
+
extract_code(encounter_element, encounter, "./gc32:reasonForVisit", :reason)
|
19
|
+
extract_code(encounter_element, encounter)
|
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
|
27
|
+
|
28
|
+
encounter
|
29
|
+
end
|
30
|
+
|
31
|
+
def extract_facility(encounter_element, encounter)
|
32
|
+
facility_element = encounter_element.xpath("./gc32:facility").first
|
33
|
+
if facility_element
|
34
|
+
organization = extract_organization(facility_element)
|
35
|
+
encounter.facility = organization
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module GreenC32
|
4
|
+
class ImmunizationImporter < SectionImporter
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def import(immunization_xml)
|
8
|
+
immunization_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
|
9
|
+
immunization_element = immunization_xml.at_xpath("./gc32:immunization")
|
10
|
+
immunization = Immunization.new
|
11
|
+
extract_entry(immunization_element, immunization)
|
12
|
+
extract_time(immunization_element, immunization, "./gc32:administeredDate")
|
13
|
+
extract_code(immunization_element, immunization, "./gc32:refusalReason")
|
14
|
+
series_number = extract_node_text(immunization_element.at_xpath("./gc32:seriesNumber"))
|
15
|
+
immunization.series_number = series_number.to_i if series_number
|
16
|
+
immunization.refusalInd = extract_node_attribute(immunization_element, :refused, true)
|
17
|
+
immunization
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module GreenC32
|
4
|
+
class MedicationImporter < SectionImporter
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def import(med_xml)
|
8
|
+
med_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
|
9
|
+
med_element = med_xml.at_xpath("./gc32:medication")
|
10
|
+
medication = Medication.new
|
11
|
+
extract_entry(med_element, medication)
|
12
|
+
extract_interval(med_element, medication, "administrationTiming")
|
13
|
+
extract_administration_timing(med_element, medication)
|
14
|
+
medication.dose = extract_quantity(med_element, "./gc32:dose")
|
15
|
+
extract_med_code_attribute(med_element, medication, :type, :typeOfMedication)
|
16
|
+
extract_med_code_attribute(med_element, medication, :statusOfMedication)
|
17
|
+
extract_med_code_attribute(med_element, medication, :route)
|
18
|
+
extract_med_code_attribute(med_element, medication, :site)
|
19
|
+
extract_dose_restriction(med_element, medication)
|
20
|
+
extract_med_code_attribute(med_element, medication, :indication)
|
21
|
+
extract_med_code_attribute(med_element, medication, :productForm)
|
22
|
+
extract_med_code_attribute(med_element, medication, :vehicle)
|
23
|
+
extract_med_code_attribute(med_element, medication, :reaction)
|
24
|
+
extract_med_code_attribute(med_element, medication, :deliveryMethod)
|
25
|
+
medication.free_text_sig = extract_node_text(med_element.at_xpath("./gc32:freeTextSig"))
|
26
|
+
medication.fulfillment_instructions = extract_node_text(med_element.at_xpath("./gc32:patientInstructions"))
|
27
|
+
medication.dose_indicator = extract_node_text(med_element.at_xpath("./gc32:doseIndicator"))
|
28
|
+
medication.fulfillment_history = extract_fulfillment_history(med_element)
|
29
|
+
medication.order_information = extract_order_information(med_element)
|
30
|
+
medication
|
31
|
+
end
|
32
|
+
|
33
|
+
def extract_administration_timing(element,entry)
|
34
|
+
entry.administration_timing = {"period" => extract_quantity(element, "./gc32:administrationTiming/gc32:period"),
|
35
|
+
"institutionSpecified" => extract_node_attribute(element.at_xpath("./gc32:administrationTiming"), :institutionSpecified)}
|
36
|
+
end
|
37
|
+
|
38
|
+
def extract_dose_restriction(element, entry)
|
39
|
+
dose_element = element.at_xpath("./gc32:doseRestriction")
|
40
|
+
entry.dose_restriction = {"numerator" => extract_quantity(dose_element, "./gc32:numerator"), "denominator" => extract_quantity(dose_element,"./gc32:denominator")}
|
41
|
+
end
|
42
|
+
|
43
|
+
def extract_fulfillment_history(med_element)
|
44
|
+
med_element.xpath("./gc32:fulfillmentHistory").map do |fh_doc|
|
45
|
+
fh = FulfillmentHistory.new(quantityDispensed: extract_quantity(fh_doc, "./gc32:quantityDispensed"))
|
46
|
+
fh.prescription_number = extract_node_text(fh_doc.at_xpath("./gc32:prescriptionUmber"))
|
47
|
+
extract_time(fh_doc, fh, "./gc32:dispenseDate", :dispense_date)
|
48
|
+
fh
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def extract_order_information(med_element)
|
53
|
+
med_element.xpath("./gc32:orderInformation").map do |oi_doc|
|
54
|
+
oi = OrderInformation.new(fills: extract_node_attribute(oi_doc, :fills, true), orderNumber: extract_node_attribute(oi_doc, :orderNumber))
|
55
|
+
extract_time(oi_doc, oi, "./gc32:orderDateTime", :order_date_time)
|
56
|
+
extract_time(oi_doc, oi, "./gc32:expiresDateTime", :order_expiration_date_time)
|
57
|
+
oi
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def extract_med_code_attribute(doc, med, attribute, mongo_attribute_name=nil)
|
62
|
+
mongo_attribute_name ||= attribute
|
63
|
+
extract_code(doc, med, "./gc32:#{attribute}", mongo_attribute_name)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module GreenC32
|
4
|
+
class ProcedureImporter < SectionImporter
|
5
|
+
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def import(procedure_xml)
|
13
|
+
procedure_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
|
14
|
+
|
15
|
+
procedure_element = procedure_xml.xpath("./gc32:procedure")
|
16
|
+
|
17
|
+
procedure = Procedure.new
|
18
|
+
|
19
|
+
extract_entry(procedure_element, procedure)
|
20
|
+
extract_type(procedure_element, procedure)
|
21
|
+
|
22
|
+
procedure
|
23
|
+
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
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -2,28 +2,41 @@ module HealthDataStandards
|
|
2
2
|
module Import
|
3
3
|
module GreenC32
|
4
4
|
class ResultImporter < SectionImporter
|
5
|
+
|
5
6
|
include Singleton
|
6
7
|
|
8
|
+
#-------------------------------------------------------------------------------
|
9
|
+
|
7
10
|
def initialize
|
8
11
|
super
|
9
12
|
@range = "./gc32:referenceRange"
|
10
13
|
@interpretation = "./gc32:interpretation"
|
14
|
+
@klass = LabResult
|
15
|
+
@base_xpath = "./gc32:result"
|
11
16
|
end
|
12
17
|
|
13
|
-
|
14
|
-
|
18
|
+
#-------------------------------------------------------------------------------
|
19
|
+
|
20
|
+
def import(result_xml)
|
21
|
+
result_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
|
15
22
|
|
16
|
-
result_element =
|
17
|
-
lab_result =
|
23
|
+
result_element = result_xml.xpath(@base_xpath)
|
24
|
+
lab_result = @klass.new(reference_range: extract_node_text(result_element.xpath(@range)))
|
18
25
|
|
19
|
-
|
20
|
-
extract_time(result_element, lab_result)
|
21
|
-
extract_value(result_element, lab_result)
|
22
|
-
extract_code(result_element, lab_result, @interpretation, :interpretation)
|
26
|
+
extract_result(result_element, lab_result)
|
23
27
|
|
24
28
|
lab_result
|
25
29
|
end
|
26
30
|
|
31
|
+
#-------------------------------------------------------------------------------
|
32
|
+
private
|
33
|
+
#-------------------------------------------------------------------------------
|
34
|
+
|
35
|
+
def extract_result(result_element, lab_result)
|
36
|
+
extract_entry(result_element, lab_result)
|
37
|
+
extract_code(result_element, lab_result, @interpretation, :interpretation)
|
38
|
+
end
|
39
|
+
|
27
40
|
end
|
28
41
|
end
|
29
42
|
end
|
@@ -37,36 +37,82 @@ module HealthDataStandards
|
|
37
37
|
entry.status = status
|
38
38
|
end
|
39
39
|
|
40
|
+
def extract_effective_time(element, entry)
|
41
|
+
if element.at_xpath("./gc32:effectiveTime/gc32:start")
|
42
|
+
extract_interval(element,entry)
|
43
|
+
else
|
44
|
+
extract_time(element, entry)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
40
48
|
def extract_time(element, entry, xpath = "./gc32:effectiveTime", attribute = "time")
|
41
|
-
datetime = element.
|
49
|
+
datetime = element.at_xpath(xpath)
|
42
50
|
return unless datetime && !datetime.inner_text.empty?
|
43
51
|
entry.send("#{attribute}=", Time.parse(datetime.inner_text).to_i)
|
44
52
|
end
|
45
53
|
|
46
|
-
def extract_interval(element, entry)
|
47
|
-
extract_time(element, entry, "./gc32
|
48
|
-
extract_time(element, entry, "./gc32
|
54
|
+
def extract_interval(element, entry, element_name="effectiveTime")
|
55
|
+
extract_time(element, entry, "./gc32:#{element_name}/gc32:start", "start_time")
|
56
|
+
extract_time(element, entry, "./gc32:#{element_name}/gc32:end", "end_time")
|
49
57
|
end
|
50
58
|
|
51
|
-
def
|
52
|
-
|
53
|
-
value_element = element.xpath(@value).first
|
59
|
+
def extract_quantity(element, xpath)
|
60
|
+
value_element = element.at_xpath(xpath)
|
54
61
|
|
55
62
|
return unless value_element
|
56
63
|
|
57
64
|
node_value = extract_node_attribute(value_element, "amount", true)
|
58
65
|
node_units = extract_node_attribute(value_element, "unit")
|
59
66
|
|
60
|
-
|
61
|
-
|
67
|
+
return {} unless node_value
|
68
|
+
|
69
|
+
{'scalar' => node_value, "unit" => node_units}
|
70
|
+
end
|
71
|
+
|
72
|
+
def extract_value(element, entry)
|
73
|
+
entry.value = extract_quantity(element, @value)
|
62
74
|
end
|
63
75
|
|
64
76
|
def extract_entry(element, entry)
|
65
77
|
extract_code(element, entry)
|
66
78
|
extract_description(element, entry)
|
67
79
|
extract_status(element, entry)
|
80
|
+
extract_value(element, entry)
|
81
|
+
extract_effective_time(element, entry)
|
68
82
|
end
|
69
83
|
|
84
|
+
def extract_organization(organization_element)
|
85
|
+
org_id = extract_node_text(organization_element.xpath("./gc32:id"))
|
86
|
+
organization = org_id ? Organization.find_or_create_by(id: org_id) : Organization.new
|
87
|
+
if organization.new_record?
|
88
|
+
else
|
89
|
+
organization.name = extract_node_text(organization_element.xpath("./gc32:name"))
|
90
|
+
organization.addresses = organization_element.xpath("./gc32:address").map { |addr| extract_address(addr) }
|
91
|
+
organization.telecoms = organization_element.xpath("./gc32:telecom").map { |tele| extract_telecom(tele) }
|
92
|
+
organization.save!
|
93
|
+
end
|
94
|
+
|
95
|
+
return organization
|
96
|
+
end
|
97
|
+
|
98
|
+
def extract_address(address_element)
|
99
|
+
address = Address.new
|
100
|
+
address.street = address_element.xpath("./gc32:street").map { |st| extract_node_text(st) }
|
101
|
+
address.city = extract_node_text(address_element.xpath("./gc32:city"))
|
102
|
+
address.state = extract_node_text(address_element.xpath("./gc32:state"))
|
103
|
+
address.zip = extract_node_text(address_element.xpath("./gc32:postalCode"))
|
104
|
+
address
|
105
|
+
end
|
106
|
+
|
107
|
+
def extract_telecom(telecom_element)
|
108
|
+
telecom = Telecom.new
|
109
|
+
telecom.use = extract_node_attribute(telecom_element, :type)
|
110
|
+
telecom.value = extract_node_attribute(telecom_element, :value)
|
111
|
+
telecom.preferred = extract_node_attribute(telecom_element, :preferred)
|
112
|
+
telecom
|
113
|
+
end
|
114
|
+
|
115
|
+
|
70
116
|
private
|
71
117
|
|
72
118
|
def build_code(code_element)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module GreenC32
|
4
|
+
class SocialHistoryImporter < SectionImporter
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def import(sh_xml)
|
8
|
+
sh_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
|
9
|
+
sh_element = sh_xml.at_xpath("./gc32:socialHistory")
|
10
|
+
sh = SocialHistory.new
|
11
|
+
extract_entry(sh_element, sh)
|
12
|
+
extract_code(sh_element, sh, "./gc32:type", :type)
|
13
|
+
sh
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module GreenC32
|
4
|
+
# This really needs to get refactored to share code with result importer
|
5
|
+
class VitalSignImporter < ResultImporter
|
6
|
+
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
#-------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
super
|
13
|
+
@range = "./gc32:referenceRange"
|
14
|
+
@klass = VitalSign
|
15
|
+
@base_xpath = "./gc32:vitalSign"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module Hdata
|
4
|
+
class MetadataImporter
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def import(meta_xml)
|
8
|
+
meta_xml.root.add_namespace_definition("hrf-md", Metadata::NS)
|
9
|
+
meta_element = meta_xml.at_xpath("./hrf-md:DocumentMetadata")
|
10
|
+
return unless meta_element
|
11
|
+
|
12
|
+
meta = Metadata::Base.new
|
13
|
+
|
14
|
+
extract_metadata(meta_element, meta)
|
15
|
+
|
16
|
+
meta
|
17
|
+
end
|
18
|
+
|
19
|
+
def extract_metadata(meta_element, meta)
|
20
|
+
meta.mime_types = meta_element.xpath("./hrf-md:MediaType").map { |media| media.text }
|
21
|
+
meta.confidentiality = meta_element.at_xpath("./hrf-md:Confidentiality").try(:text)
|
22
|
+
meta.pedigrees = meta_element.xpath("./hrf-md:PedigreeInfo").map { |ped| extract_pedigree(ped) }
|
23
|
+
creation_el = meta_element.at_xpath("./hrf-md:RecordDate/hrf-md:CreatedDateTime")
|
24
|
+
meta.original_creation_time = Time.parse(creation_el.text) if creation_el
|
25
|
+
meta.linked_documents = meta_element.xpath("./hrf-md:LinkedDocuments/hrf-md:Link").map {|l| extract_link_info(l)}
|
26
|
+
copied_elements = meta_element.xpath("./hrf-md:RecordDate/hrf-md:Copied/hrf-md:CopiedInfo")
|
27
|
+
meta.copied_dates = copied_elements.map { |cp| extract_change_info(cp) }
|
28
|
+
modified_elements = meta_element.xpath("./hrf-md:RecordDate/hrf-md:Modified/hrf-md:ModifiedInfo")
|
29
|
+
meta.modified_dates = modified_elements.map { |md| extract_change_info(md) }
|
30
|
+
meta
|
31
|
+
end
|
32
|
+
|
33
|
+
def extract_pedigree(pedi_el)
|
34
|
+
return unless pedi_el
|
35
|
+
|
36
|
+
author = extract_author(pedi_el)
|
37
|
+
organization = pedi_el.at_xpath("./hrf-md:Organization")
|
38
|
+
|
39
|
+
ped = Metadata::Pedigree.new(author: author,
|
40
|
+
organization: organization.try(:content))
|
41
|
+
|
42
|
+
source_pedigree_els = pedi_el.xpath("./hrf-md:Source/hrf-md:PedigreeInfo")
|
43
|
+
ped.source_pedigrees = source_pedigree_els.map { |ped_el| extract_pedigree(ped_el) }
|
44
|
+
ped.derived = pedi_el.attribute("derived")# == "true" ? true : false
|
45
|
+
# ped.signature = pedi_el.at_xpath("./hrf-md:Signature/")
|
46
|
+
|
47
|
+
source_doc_els = pedi_el.xpath("./hrf-md:Source/hrf-md:Document")
|
48
|
+
ped.source_documents = source_doc_els.map { |doc_el| extract_link_info(doc_el) }
|
49
|
+
|
50
|
+
ped
|
51
|
+
end
|
52
|
+
|
53
|
+
def extract_author(pedi_el)
|
54
|
+
return unless pedi_el
|
55
|
+
author = pedi_el.at_xpath("./hrf-md:Author")
|
56
|
+
return unless author
|
57
|
+
Metadata::Author.new(name: author.try(:content),
|
58
|
+
type: author.attribute('typeCode').try("content"),
|
59
|
+
role: author.attribute('role').try("content"))
|
60
|
+
end
|
61
|
+
|
62
|
+
def extract_link_info(link_info_el)
|
63
|
+
return unless link_info_el
|
64
|
+
target_el = link_info_el.at_xpath("./hrf-md:Target")
|
65
|
+
return unless target_el
|
66
|
+
Metadata::LinkInfo.new(uri: target_el.content,
|
67
|
+
extension: target_el.attribute("TargetExtension").try(:content))
|
68
|
+
end
|
69
|
+
|
70
|
+
def extract_change_info(change_info_el)
|
71
|
+
return unless change_info_el
|
72
|
+
change_info = Metadata::ChangeInfo.new
|
73
|
+
change_info.timestamp = change_info_el.at_xpath("./hrf-md:ChangeDateTime").try("content")
|
74
|
+
change_info.pedigree = extract_pedigree(change_info_el.at_xpath("./hrf-md:PedigreeInfo"))
|
75
|
+
change_info_el
|
76
|
+
change_info
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|