class HealthDataStandards::Import::CDA::SectionImporter

Attributes

check_for_usable[RW]
code_xpath[RW]
status_xpath[RW]

Public Class Methods

new(entry_finder) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 10
def initialize(entry_finder)
  @entry_finder = entry_finder
  @code_xpath = "./cda:code"
  @id_xpath = "./cda:id"
  @status_xpath = nil
  @priority_xpath = nil
  @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value]"
  @check_for_usable = true
  @entry_class = Entry
  @value_xpath = 'cda:value'
end

Public Instance Methods

create_entries(doc, nrh = NarrativeReferenceHandler.new) click to toggle source

Traverses an HL7 CDA document passed in and creates an Array of Entry objects based on what it finds @param [Nokogiri::XML::Document] doc It is expected that the root node of this document

will have the "cda" namespace registered to "urn:hl7-org:v3"
measure definition

@return [Array] will be a list of Entry objects

# File lib/health-data-standards/import/cda/section_importer.rb, line 28
def create_entries(doc, nrh = NarrativeReferenceHandler.new)
  entry_list = []
  entry_elements = @entry_finder.entries(doc)
  entry_elements.each do |entry_element|
    entry = create_entry(entry_element, nrh)
    if @check_for_usable
      entry_list << entry if entry.usable?
    else
      entry_list << entry
    end
  end
  entry_list
end
create_entry(entry_element, nrh = NarrativeReferenceHandler.new) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 42
def create_entry(entry_element, nrh = NarrativeReferenceHandler.new)
  entry = @entry_class.new
  extract_id(entry_element, entry)
  extract_codes(entry_element, entry)
  extract_dates(entry_element, entry)
  if @value_xpath
    extract_values(entry_element, entry)
  end
  extract_description(entry_element, entry, nrh)
  if @status_xpath
    extract_status(entry_element, entry)
  end
  entry
end

Private Instance Methods

add_code_if_present(code_element, entry) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 107
def add_code_if_present(code_element, entry)
  if code_element['codeSystem'] && code_element['code']
    entry.add_code(code_element['code'], CodeSystemHelper.code_system_for(code_element['codeSystem']))
  end
end
extract_code(parent_element, code_xpath, code_system=nil) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 221
def extract_code(parent_element, code_xpath, code_system=nil)
  code_element = parent_element.at_xpath(code_xpath)
  code_hash = nil
  if code_element
    code_hash = {'code' => code_element['code']}
    if code_system
      code_hash['codeSystem'] = code_system
    else
      code_hash['codeSystemOid'] = code_element['codeSystem']
      code_hash['codeSystem'] = CodeSystemHelper.code_system_for(code_hash['codeSystemOid'])
    end
  end

  code_hash
end
extract_codes(parent_element, entry) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 96
def extract_codes(parent_element, entry)
  code_elements = parent_element.xpath(@code_xpath)
  code_elements.each do |code_element|
    add_code_if_present(code_element, entry)
    translations = code_element.xpath('cda:translation')
    translations.each do |translation|
      add_code_if_present(translation, entry)
    end
  end
end
extract_dates(parent_element, entry, element_name="effectiveTime") click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 113
def extract_dates(parent_element, entry, element_name="effectiveTime")
  if parent_element.at_xpath("cda:#{element_name}/@value")
    entry[:time] = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}")['value'])
  end
  if parent_element.at_xpath("cda:#{element_name}/cda:low")
    entry[:start_time] = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}/cda:low")['value'])
  end
  if parent_element.at_xpath("cda:#{element_name}/cda:high")
    entry[:end_time] = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}/cda:high")['value'])
  end
  if parent_element.at_xpath("cda:#{element_name}/cda:center")
    entry[:time] = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}/cda:center")['value'])
  end
end
extract_description(parent_element, entry, nrh) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 59
def extract_description(parent_element, entry, nrh)
  orig_text_ref_element = parent_element.at_xpath(@description_xpath)
  desc_ref_element = parent_element.at_xpath("./cda:text/cda:reference")
  if orig_text_ref_element && orig_text_ref_element['value']
    entry.description = nrh.lookup_tag(orig_text_ref_element['value'])
  elsif desc_ref_element && desc_ref_element['value']
    entry.description = nrh.lookup_tag(desc_ref_element['value'])
  else
    entry.description = parent_element.at_xpath("./cda:text").try("text")
  end
end
extract_id(parent_element, entry) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 78
def extract_id(parent_element, entry)
  id_element = parent_element.at_xpath(@id_xpath)
  if id_element
    identifier = CDAIdentifier.new
    identifier.root = id_element['root']
    identifier.extension = id_element['extension']
    entry.cda_identifier = identifier
  end
end
extract_negated_code(coded_parent_element, entry) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 198
def extract_negated_code(coded_parent_element, entry)
  code_elements = coded_parent_element.xpath(@code_xpath)
  code_elements.each do |code_element|
    if code_element['nullFlavor'] == 'NA' && code_element['sdtc:valueSet']
      # choose code from valueset
      valueset = HealthDataStandards::SVS::ValueSet.where(oid: code_element['sdtc:valueSet'], bundle_id: get_bundle_id(coded_parent_element))
      entry.add_code(valueset.first.concepts.first['code'], valueset.first.concepts.first['code_system_name'])
      # A "code" is added to indicate the Non-Applicable valueset.
      entry.add_code(code_element['sdtc:valueSet'], 'NA_VALUESET')
    end
  end
end
extract_reason_description(parent_element, entry, nrh) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 88
def extract_reason_description(parent_element, entry, nrh)
  code_elements = parent_element.xpath(@description_xpath)
  code_elements.each do |code_element|
    tag = code_element['value']
    entry.description = nrh.lookup_tag(tag)
  end
end
extract_reason_or_negation(parent_element, entry, coded_parent_element = nil) click to toggle source

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 coded_parent_element is the 'parent' element when the coded is nested (e.g., medication order)

# File lib/health-data-standards/import/cda/section_importer.rb, line 178
def extract_reason_or_negation(parent_element, entry, coded_parent_element = nil)
  coded_parent_element ||= parent_element
  reason_element = parent_element.at_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")
  negation_indicator = parent_element['negationInd']
  if reason_element
    code_system_oid = reason_element['codeSystem']
    code = reason_element['code']
    code_system = HealthDataStandards::Util::CodeSystemHelper.code_system_for(code_system_oid)
    entry.negation_ind = negation_indicator.eql?('true')
    if entry.negation_ind
      entry.negation_reason = {'code' => code, 'code_system' => code_system, 'codeSystem' => code_system}
    else
      entry.reason = {'code' => code, 'code_system' => code_system, 'codeSystem' => code_system}
    end
  elsif negation_indicator
    entry.negation_ind = negation_indicator.eql?('true')
  end
  extract_negated_code(coded_parent_element, entry)
end
extract_scalar(parent_element, scalar_xpath) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 237
def extract_scalar(parent_element, scalar_xpath)
  scalar_element = parent_element.at_xpath(scalar_xpath)
  if scalar_element
    {'unit' => scalar_element['unit'], 'value' => scalar_element['value'].to_i}
  else
    nil
  end
end
extract_status(parent_element, entry) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 71
def extract_status(parent_element, entry)
  status_element = parent_element.at_xpath(@status_xpath)
  if status_element
    entry.status_code = {CodeSystemHelper.code_system_for(status_element['codeSystem']) => [status_element['code']]}
  end
end
extract_value(parent_element, value_element, entry) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 134
def extract_value(parent_element, value_element, entry)
  if value_element && !value_element['nullFlavor']
    value = value_element['value']
    if value.present?
      unit = value_element['unit']
      entry.set_value(value.strip, unit)
    elsif value_element['code'].present?
      crv = CodedResultValue.new
      add_code_if_present(value_element, crv)
      extract_dates(parent_element, crv)
      entry.values << crv
    else
      value = value_element.text
      unit = value_element['unit']
      entry.set_value(value.strip, unit)
    end

  end
end
extract_values(parent_element, entry) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 128
def extract_values(parent_element, entry)
  parent_element.xpath(@value_xpath).each do |elem|
    extract_value(parent_element, elem, entry)
  end
end
get_bundle_id(parent_element) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 211
def get_bundle_id(parent_element)
  while parent_element.name != 'document'
    parent_element = parent_element.parent
  end
  # first measure id specified in the document
  measure_id = parent_element.xpath("cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section/cda:entry/cda:organizer[cda:templateId/@root='2.16.840.1.113883.10.20.24.3.98']/cda:reference/cda:externalDocument/cda:id[@root='2.16.840.1.113883.4.738']/@extension").first.value.upcase
  # bundle of the first measure id
  HealthDataStandards::CQM::Measure.where(hqmf_id: measure_id).first['bundle_id']
end
import_actor(actor_element) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 154
def import_actor(actor_element)
  return ProviderImporter.instance.extract_provider(actor_element)
end
import_organization(organization_element) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 158
def import_organization(organization_element)
  return OrganizationImporter.instance.extract_organization(organization_element)
end
import_person(person_element) click to toggle source
# File lib/health-data-standards/import/cda/section_importer.rb, line 162
def import_person(person_element)
  return unless person_element
  person = Person.new
  name_element = person_element.at_xpath("./cda:name")
  if name_element
    person.title = name_element.at_xpath("./cda:title").try(:text)
    person.given_name = name_element.at_xpath("./cda:given").try(:text)
    person.family_name = name_element.at_xpath("./cda:family").try(:text)
  end
  person.addresses = person_element.xpath("./cda:addr").map { |addr| import_address(addr) }
  person.telecoms = person_element.xpath("./cda:telecom").map { |tele| import_telecom(tele) }
  return person
end