lib/hqmf-parser/2.0/data_criteria_helpers/dc_definition_from_template_or_type_extract.rb
module HQMF2
# Extracts the type, and modifies the data criteria, based on the template id or definition
module DataCriteriaTypeAndDefinitionExtraction
VARIABLE_TEMPLATE = '0.1.2.3.4.5.6.7.8.9.1'
SATISFIES_ANY_TEMPLATE = '2.16.840.1.113883.10.20.28.3.108'
SATISFIES_ALL_TEMPLATE = '2.16.840.1.113883.10.20.28.3.109'
def extract_definition_from_template_or_type
# Try to determine what kind of data criteria we are dealing with
# First we look for a template id and if we find one just use the definition
# status and negation associated with that
# If no template id or not one we recognize then try to determine type from
# the definition element
extract_definition_from_type unless extract_definition_from_template_id
end
# Given a template id, derive (if available) the definition for the template.
# The definitions are stored in hqmf-model/data_criteria.json.
def extract_definition_from_template_id
found = false
@template_ids.each do |template_id|
defs = HQMF::DataCriteria.definition_for_template_id(template_id, 'r2')
if defs
@definition = defs['definition']
@status = defs['status'].length > 0 ? defs['status'] : nil
found ||= true
else
found ||= handle_known_template_id(template_id)
end
end
found
end
# Given a template id, modify the variables inside this data criteria to reflect the template
def handle_known_template_id(template_id)
case template_id
when VARIABLE_TEMPLATE
@derivation_operator = HQMF::DataCriteria::INTERSECT if @derivation_operator == HQMF::DataCriteria::XPRODUCT
@definition ||= 'derived'
@variable = true
@negation = false
when SATISFIES_ANY_TEMPLATE
@definition = HQMF::DataCriteria::SATISFIES_ANY
@negation = false
when SATISFIES_ALL_TEMPLATE
@definition = HQMF::DataCriteria::SATISFIES_ALL
@derivation_operator = HQMF::DataCriteria::INTERSECT
@negation = false
else
return false
end
true
end
# Extract the definition (sometimes status, sometimes other elements) of the data criteria based on the type
def extract_definition_from_type
# If we have a specific occurrence of a variable, pull attributes from the reference.
# IDEA set this up to be called from dc_specific_and_source_extract, the number of
# fields changed by handle_specific_variable_ref may pose an issue.
extract_information_for_specific_variable if @variable && @specific_occurrence
if @entry.at_xpath('./cda:grouperCriteria')
@definition ||= 'derived'
return
end
# See if we can find a match for the entry definition value and status.
entry_type = attr_val('./*/cda:definition/*/cda:id/@extension')
handle_entry_type(entry_type)
end
# Extracts information from a reference for a specific
def extract_information_for_specific_variable
reference = @entry.at_xpath('./*/cda:outboundRelationship/cda:criteriaReference',
HQMF2::Document::NAMESPACES)
if reference
ref_id = strip_tokens(
"#{HQMF2::Utilities.attr_val(reference, 'cda:id/@extension')}_#{HQMF2::Utilities.attr_val(reference, 'cda:id/@root')}")
end
reference_criteria = @data_criteria_references[ref_id] if ref_id
# if the reference is derived, pull from the original variable
if reference_criteria && reference_criteria.definition == 'derived'
reference_criteria = @data_criteria_references["GROUP_#{ref_id}"]
end
return unless reference_criteria
handle_specific_variable_ref(reference_criteria)
end
# Apply additional information to a specific occurrence's elements from the criteria it references.
def handle_specific_variable_ref(reference_criteria)
# if there are no referenced children, then it's a variable representing
# a single data criteria, so just reference it
if reference_criteria.children_criteria.empty?
@children_criteria = [reference_criteria.id]
# otherwise pull all the data criteria info from the reference
else
@field_values = reference_criteria.field_values
@temporal_references = reference_criteria.temporal_references
@subset_operators = reference_criteria.subset_operators
@derivation_operator = reference_criteria.derivation_operator
@definition = reference_criteria.definition
@description = reference_criteria.description
@status = reference_criteria.status
@children_criteria = reference_criteria.children_criteria
end
end
# Generate the definition and/or status from the entry type in most cases.
# If the entry type is nil, and the value is a specific occurrence, more parsing may be necessary.
def handle_entry_type(entry_type)
# settings is required to trigger exceptions, which set the definition
HQMF::DataCriteria.get_settings_for_definition(entry_type, @status)
@definition = entry_type
rescue
# if no exact match then try a string match just using entry definition value
case entry_type
when 'Medication', 'Medications'
@definition = 'medication'
@status = 'active' unless @status
when 'RX'
@definition = 'medication'
@status = 'dispensed' unless @status
when nil
definition_for_nil_entry
else
@definition = extract_definition_from_entry_type(entry_type)
end
end
# If there is no entry type, extract the entry type from what it references, and extract additional information for
# specific occurrences. If there are no outbound references, print an error and mark it as variable.
def definition_for_nil_entry
reference = @entry.at_xpath('./*/cda:outboundRelationship/cda:criteriaReference', HQMF2::Document::NAMESPACES)
ref_id = nil
unless reference.nil?
ref_id = "#{HQMF2::Utilities.attr_val(reference, 'cda:id/@extension')}_#{HQMF2::Utilities.attr_val(reference, 'cda:id/@root')}"
end
reference_criteria = @data_criteria_references[strip_tokens(ref_id)] unless ref_id.nil?
if reference_criteria
# we only want to copy the reference criteria definition, status, and code_list_id if this is this is not a grouping criteria (i.e., there are no children)
if @children_criteria.blank?
@definition = reference_criteria.definition
@status = reference_criteria.status
if @specific_occurrence
@title = reference_criteria.title
@description = reference_criteria.description
@code_list_id = reference_criteria.code_list_id
end
else
# if this is a grouping data criteria (has children) mark it as derived and only pull title and description from the reference criteria
@definition = 'derived'
if @specific_occurrence
@title = reference_criteria.title
@description = reference_criteria.description
end
end
else
puts "MISSING_DC_REF: #{ref_id}" unless @variable
@definition = 'variable'
end
end
# Given an entry type (which describes the criteria's purpose) return the appropriate defintino
def extract_definition_from_entry_type(entry_type)
case entry_type
when 'Problem', 'Problems'
'diagnosis'
when 'Encounter', 'Encounters'
'encounter'
when 'LabResults', 'Results'
'laboratory_test'
when 'Procedure', 'Procedures'
'procedure'
when 'Demographics'
definition_for_demographic
when 'Derived'
'derived'
else
fail "Unknown data criteria template identifier [#{entry_type}]"
end
end
# Return the definition for a known subset of patient characteristics
def definition_for_demographic
demographic_type = attr_val('./cda:observationCriteria/cda:code/@code')
demographic_translation = {
'21112-8' => 'patient_characteristic_birthdate',
'424144002' => 'patient_characteristic_age',
'263495000' => 'patient_characteristic_gender',
'102902016' => 'patient_characteristic_languages',
'125680007' => 'patient_characteristic_marital_status',
'103579009' => 'patient_characteristic_race'
}
if demographic_translation[demographic_type]
demographic_translation[demographic_type]
else
fail "Unknown demographic identifier [#{demographic_type}]"
end
end
end
end