Class: HQMF::PreconditionExtractor

Inherits:
Object
  • Object
show all
Defined in:
lib/hqmf-parser/converter/pass1/precondition_extractor.rb

Overview

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

Class Method Summary collapse

Class Method Details

.convert_comparison_to_precondition(comparison, data_criteria_converter) ⇒ Object

we want the comparisons to be converted to the leaf preconditions



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# 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) ⇒ Object

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

restriction.preconditions
restriction.comparison
restriction.restriction


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# 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) ⇒ Object



16
17
18
19
20
21
22
23
# 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) ⇒ Object

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



185
186
187
188
189
190
191
192
193
194
195
196
197
198
# 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