class HQMF::PreconditionExtractor

preconditions can be in several places.

precondition -> preconditions restriction -> preconditions

also, restrictions can be on the following, which can then have preconditions

restrictions
comparisons
preconditions

Public Class Methods

convert_comparison_to_precondition(comparison, data_criteria_converter) click to toggle source

we want the comparisons to be converted to the leaf preconditions

# File lib/hqmf-parser/converter/pass1/precondition_extractor.rb, line 156
    def self.convert_comparison_to_precondition(comparison, data_criteria_converter)

      data_criteria = data_criteria_converter.v1_data_criteria_by_id[comparison[:data_criteria_id]]
      reference = HQMF::Reference.new(data_criteria.id)
#      conjunction_code = "#{data_criteria.type.to_s.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }}Reference"
      conjunction_code = nil

      preconditions = []
      if comparison[:restrictions]
         # check for preconditions on restrictions
         preconditions = extract_preconditions_from_restrictions(comparison[:restrictions], data_criteria_converter) 
      end
      
      precondition = HQMF::Converter::SimplePrecondition.new(nil,preconditions,reference,conjunction_code, false)
      precondition.klass = HQMF::Converter::SimplePrecondition::COMPARISON
      
      if (comparison[:subset])
        # create a restriction for a comparison subset... this is for things like first, second, etc.
        type = comparison[:subset]
        operator = HQMF::Converter::SimpleOperator.new(HQMF::Converter::SimpleOperator.find_category(type), type, nil)
        restriction = HQMF::Converter::SimpleRestriction.new(operator, reference.id, nil)
        precondition.preconditions ||= []
        precondition.preconditions << restriction
      end

      precondition
    end
extract_preconditions_from_restriction(restriction,data_criteria_converter) click to toggle source

get all the preconditions for a restriction we need to iterate down

restriction.preconditions
restriction.comparison
restriction.restriction
# File lib/hqmf-parser/converter/pass1/precondition_extractor.rb, line 30
def self.extract_preconditions_from_restriction(restriction,data_criteria_converter)
  target_id=nil
  if restriction[:target_id] and data_criteria_converter.v1_data_criteria_by_id[restriction[:target_id]]
    target_id = data_criteria_converter.v1_data_criteria_by_id[restriction[:target_id]].id
  elsif restriction[:target_id]
    puts "\tPrecondition Data Criteria MISSING: #{restriction[:target_id]}"
  end
  type = restriction[:type]
  if (restriction[:negation]) 
    inverted = HQMF::TemporalReference::INVERSION[type] 
    if (inverted)
      type = inverted
    else
      puts "\tdon't know how to invert #{type}"
    end
  end
  
  # if we reference the measurement period, then we want to check if the reference is to the start or end of the measurement period
  # if we SBS of the END of the measurement period, we want to convert that to SBE of the measurement period
  if target_id == HQMF::Document::MEASURE_PERIOD_ID
    references_start = {'SBS'=>'SBE','SAS'=>'SAE','EBS'=>'EBE','EAS'=>'EAE','SCW'=>'SCWE'}
    references_end = {'EBE'=>'EBS','EAE'=>'EAS','SBE'=>'SBS','SAE'=>'SAS','ECW'=>'ECWS'}
    if data_criteria_converter.measure_period_v1_keys[:measure_start] == restriction[:target_id] and references_end[type]
      # before or after the END of the measurement period START.  Convert to before or after the START of the measurement period.
      # SAE of MPS => SAS of MP
      # ends concurrent with measurement period START. Convert to concurrent with START of measurement period.
      # ECW of MPS => ECWS
      type = references_end[type]
    elsif data_criteria_converter.measure_period_v1_keys[:measure_end] == restriction[:target_id] and references_start[type]
      # before or after the START of the measurement period END.  Convert to before or after the END of the measurement period.
      # SBS of MPE => SBE of MP
      # starts concurrent with measurement period END. Convert to concurrent with END of measurement period.
      # SCW of MPE => SCWE
      type = references_start[type]
    end
  end
  
  value = nil
  if (restriction[:range])
    value = HQMF::Range.from_json(JSON.parse(restriction[:range].to_json)) if (restriction[:range])
  elsif(restriction[:value])
    value = HQMF::Converter::SimpleOperator.parse_value(restriction[:value])
  end
  field = restriction[:field]
  field_code = restriction[:field_code]
  field_time = restriction[:field_time]
  operator = HQMF::Converter::SimpleOperator.new(HQMF::Converter::SimpleOperator.find_category(type), type, value, field, field_code, field_time)
  
  # get the precondtions off of the restriction
  children = HQMF::PreconditionConverter.parse_and_merge_preconditions(restriction[:preconditions],data_criteria_converter) if restriction[:preconditions]
  
  if restriction[:comparison]
    children ||= []
    # check comparison and convert it to a precondition
    comparison = convert_comparison_to_precondition(restriction[:comparison], data_criteria_converter)
    children << comparison
  end
  
  # check restrictions
  restrictions = extract_preconditions_from_restrictions(restriction[:restrictions], data_criteria_converter) if restriction[:restrictions]
  if (children)
    HQMF::PreconditionConverter.apply_restrictions_to_comparisons(children, restrictions) unless restrictions.nil? or restrictions.empty?
  end
  
  
  container = nil
  # check if there is an expression on the restriction
  if (restriction[:expression])
    # this is for things like TIMEDIFF
    type = restriction[:expression][:type]
    exp_operator = HQMF::Converter::SimpleOperator.new(HQMF::Converter::SimpleOperator.find_category(type), type, HQMF::Converter::SimpleOperator.parse_value(restriction[:expression][:value]))
    preconditions = []
    
    driv_preconditions = []
    restrictions.each {|element| driv_preconditions << element if element.is_a? HQMF::Converter::SimpleRestriction and element.operator.type == 'DRIV'}
    
    if driv_preconditions and !driv_preconditions.empty?
      preconditions = driv_preconditions.map(&:preconditions).flatten
    end
  
    reference = nil
    conjunction_code = nil
    
    comparison_precondition = HQMF::Converter::SimplePrecondition.new(nil,[HQMF::Converter::SimpleRestriction.new(exp_operator, nil, preconditions)],reference,conjunction_code, false)
    comparison_precondition.klass = HQMF::Converter::SimplePrecondition::COMPARISON

    comparison_precondition.subset_comparison = true
    container = HQMF::Converter::SimpleRestriction.new(operator, nil, [comparison_precondition])
  
  # check if there is a subset on the restriction
  elsif restriction[:subset]
    # if we have a subset, we want to create a Comparison Precondition for the subset and have it be the child of the operator on the restriction.
    # the reason for this is that we want the order of operations to be SBS the FIRST of a data criteria, rather than FIRST of SBS of a data criteria
    
    subset_type = restriction[:subset]
    subset_operator = HQMF::Converter::SimpleOperator.new(HQMF::Converter::SimpleOperator.find_category(subset_type), subset_type, nil)
    
    reference = nil
    conjunction_code = nil
    
    restriction = HQMF::Converter::SimpleRestriction.new(subset_operator, target_id)
    restriction.preconditions = children
    
    comparison_precondition = HQMF::Converter::SimplePrecondition.new(nil, [restriction], reference, conjunction_code, false)
    comparison_precondition.klass = HQMF::Converter::SimplePrecondition::COMPARISON
    
    container = HQMF::Converter::SimpleRestriction.new(operator, nil, [comparison_precondition])
  else
    container = HQMF::Converter::SimpleRestriction.new(operator, target_id)
    # handle transitive restrictions... this is where we are adding a field to a target of a timing restriction
    if (restrictions && !restrictions.empty? && children.nil?)
      children = []
      restrictions.each do |child|
        comparison_precondition = HQMF::Converter::SimplePrecondition.new(nil,[child],HQMF::Reference.new(target_id),nil, false)
        comparison_precondition.klass = HQMF::Converter::SimplePrecondition::COMPARISON
        children << comparison_precondition
      end
    end
    container.preconditions = children
  end
  
  [container]
end
extract_preconditions_from_restrictions(restrictions,data_criteria_converter) click to toggle source
# File lib/hqmf-parser/converter/pass1/precondition_extractor.rb, line 16
def self.extract_preconditions_from_restrictions(restrictions,data_criteria_converter)
  return [] unless restrictions
  preconditions = []
  restrictions.each do |restriction|
    preconditions.concat(extract_preconditions_from_restriction(restriction,data_criteria_converter))
  end
  preconditions      
end
flatten_v2_preconditions(preconditions) click to toggle source

flatten a tree of preconditions into an array… if we are doing something like a count, we just want the flat list

# File lib/hqmf-parser/converter/pass1/precondition_extractor.rb, line 185
def self.flatten_v2_preconditions(preconditions)
  flattened = []
  preconditions.each do |precondition|
    if (precondition.reference and precondition.has_preconditions?)
      raise "don't know how to handle a condition with a reference that has preconditions" if (precondition.reference and precondition.has_preconditions?)
    end
    if (precondition.reference) 
      flattened << precondition
    else
      flattened.concat(flatten_v2_preconditions(precondition.preconditions))
    end
  end
  flattened
end