class HQMF::PreconditionConverter

Class for converting an HQMF 1.0 representation to an HQMF 2.0 representation

Public Class Methods

apply_restrictions_to_comparisons(preconditions, restrictions) click to toggle source
# File lib/hqmf-parser/converter/pass1/precondition_converter.rb, line 100
def self.apply_restrictions_to_comparisons(preconditions, restrictions)
  comparisons = get_comparison_preconditions(preconditions)
  raise "no comparisons to apply restriction to" if comparisons.empty?
  comparisons.each do |comparison|
    comparison.preconditions.concat(restrictions)
  end
end
get_comparison_preconditions(preconditions) click to toggle source
# File lib/hqmf-parser/converter/pass1/precondition_converter.rb, line 86
def self.get_comparison_preconditions(preconditions)
  comparisons = []
  preconditions.each do |precondition|
    if (precondition.comparison? and !precondition.subset_comparison)
      comparisons << precondition
    elsif(precondition.has_preconditions?)
      comparisons.concat(get_comparison_preconditions(precondition.preconditions))
    else
      raise "precondition with no comparison or children... not valid"
    end
  end
  comparisons
end
parse_precondition(precondition,data_criteria_converter) click to toggle source

converts a precondtion to a hqmf model

# File lib/hqmf-parser/converter/pass1/precondition_converter.rb, line 18
def self.parse_precondition(precondition,data_criteria_converter)
  
  # grab child preconditions, and parse recursively
  preconditions = parse_and_merge_preconditions(precondition[:preconditions],data_criteria_converter) if precondition[:preconditions] || []
  
  preconditions_from_restrictions = HQMF::PreconditionExtractor.extract_preconditions_from_restrictions(precondition[:restrictions], data_criteria_converter)
  
  # driv preconditions are preconditions that are the children of an expression
  driv_preconditions = []
  preconditions_from_restrictions.delete_if {|element| driv_preconditions << element if element.is_a? HQMF::Converter::SimpleRestriction and element.operator.type == 'DRIV'}
  
  apply_restrictions_to_comparisons(preconditions, preconditions_from_restrictions) unless preconditions_from_restrictions.empty?

  conjunction_code = convert_logical_conjunction(precondition[:conjunction])

  if (precondition[:expression])
    # this is for things like COUNT
    type = precondition[:expression][:type]
    operator = HQMF::Converter::SimpleOperator.new(HQMF::Converter::SimpleOperator.find_category(type), type, HQMF::Converter::SimpleOperator.parse_value(precondition[:expression][:value]))
    children = []
    if driv_preconditions and !driv_preconditions.empty?
      children = driv_preconditions.map(&:preconditions).flatten
    end
    
    reference = nil
    # take the conjunction code from the parent precondition
    
    restriction = HQMF::Converter::SimpleRestriction.new(operator, nil, children)
    
    comparison_precondition = HQMF::Converter::SimplePrecondition.new(nil,[restriction],reference,conjunction_code, false)
    comparison_precondition.klass = HQMF::Converter::SimplePrecondition::COMPARISON
    comparison_precondition.subset_comparison = true
    preconditions << comparison_precondition
  end
  
  reference = nil
  
  negation = precondition[:negation]
  
  
  if (precondition[:comparison])
    preconditions ||= []
    comparison_precondition = HQMF::PreconditionExtractor.convert_comparison_to_precondition(precondition[:comparison],data_criteria_converter)
    preconditions << comparison_precondition
  end


  if (precondition[:subset])
    # this is for things like FIRST on preconditions
    type = precondition[:subset]
    operator = HQMF::Converter::SimpleOperator.new(HQMF::Converter::SimpleOperator.find_category(type), type, nil)
    children = preconditions
    
    reference = nil
    # take the conjunction code from the parent precondition
    
    restriction = HQMF::Converter::SimpleRestriction.new(operator, nil, children)
    
    comparison_precondition = HQMF::Converter::SimplePrecondition.new(nil,[restriction],reference,conjunction_code, false)
    comparison_precondition.klass = HQMF::Converter::SimplePrecondition::COMPARISON
    preconditions = [comparison_precondition]
  end

  
  HQMF::Converter::SimplePrecondition.new(nil,preconditions,reference,conjunction_code, negation)
  
end
parse_preconditions(source,data_criteria_converter) click to toggle source
# File lib/hqmf-parser/converter/pass1/precondition_converter.rb, line 5
def self.parse_preconditions(source,data_criteria_converter)

  # preconditions = []
  # source.each do |precondition|
  #   preconditions << HQMF::PreconditionConverter.parse_precondition(precondition,data_criteria_converter)
  # end
  #
  # preconditions
  
  parse_and_merge_preconditions(source,data_criteria_converter)
end

Private Class Methods

convert_logical_conjunction(code) click to toggle source
# File lib/hqmf-parser/converter/pass1/precondition_converter.rb, line 159
def self.convert_logical_conjunction(code)
  case code
    when 'OR'
      HQMF::Precondition::AT_LEAST_ONE_TRUE
    when 'AND'
      HQMF::Precondition::ALL_TRUE
    else
      raise "unsupported logical conjunction code conversion: #{code}"
  end
  
end
merge_precondtion_conjunction_groups(preconditions_by_conjunction) click to toggle source
# File lib/hqmf-parser/converter/pass1/precondition_converter.rb, line 123
def self.merge_precondtion_conjunction_groups(preconditions_by_conjunction)
  joined = []
  preconditions_by_conjunction.each do |conjunction_code, preconditions|
    sub_conditions = []
    negated_conditions = []
    preconditions.each do |precondition|
      unless (precondition.negation)
        sub_conditions.concat precondition.preconditions if precondition.preconditions
      else
        negated_conditions.concat precondition.preconditions if precondition.preconditions
      end
    end
    
    if (!sub_conditions.empty?)
      # if we have negated conditions, add them to a new precondition with an inverted conjunction on a negated precondition
      # the reason we invert the conjunction is because we are turning
      # AND: NOT X
      # AND: NOT Y
      # into
      # NOT: X OR Y
      # (i.e, demorgan's law)
      if (!negated_conditions.empty?)
        inverted_conjunction_code = HQMF::Precondition::INVERSIONS[conjunction_code]
        sub_conditions << HQMF::Converter::SimplePrecondition.new(nil,negated_conditions,nil,inverted_conjunction_code, true)
      end
      joined << HQMF::Converter::SimplePrecondition.new(nil,sub_conditions,nil,conjunction_code, false)
    elsif (!negated_conditions.empty?)
      # invert conjunction based on demorgan's law
      inverted_conjunction_code = HQMF::Precondition::INVERSIONS[conjunction_code]
      joined << HQMF::Converter::SimplePrecondition.new(nil,negated_conditions,nil,inverted_conjunction_code, true)
    end
    
  end
  joined
end
parse_and_merge_preconditions(source,data_criteria_converter) click to toggle source
# File lib/hqmf-parser/converter/pass1/precondition_converter.rb, line 111
def self.parse_and_merge_preconditions(source,data_criteria_converter)
  return [] unless source and source.size > 0
  preconditions_by_conjunction = {}
  source.each do |precondition|
    parsed = HQMF::PreconditionConverter.parse_precondition(precondition,data_criteria_converter)
    preconditions_by_conjunction[parsed.conjunction_code] ||= []
    preconditions_by_conjunction[parsed.conjunction_code]  << parsed
  end
  
  merge_precondtion_conjunction_groups(preconditions_by_conjunction)
end