hqmf-parser 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. data/Gemfile +23 -0
  2. data/README.md +903 -0
  3. data/Rakefile +19 -0
  4. data/VERSION +1 -0
  5. data/lib/hqmf-generator/hqmf-generator.rb +308 -0
  6. data/lib/hqmf-model/attribute.rb +35 -0
  7. data/lib/hqmf-model/data_criteria.rb +322 -0
  8. data/lib/hqmf-model/document.rb +172 -0
  9. data/lib/hqmf-model/population_criteria.rb +90 -0
  10. data/lib/hqmf-model/precondition.rb +85 -0
  11. data/lib/hqmf-model/types.rb +318 -0
  12. data/lib/hqmf-model/utilities.rb +52 -0
  13. data/lib/hqmf-parser.rb +54 -0
  14. data/lib/hqmf-parser/1.0/attribute.rb +68 -0
  15. data/lib/hqmf-parser/1.0/comparison.rb +34 -0
  16. data/lib/hqmf-parser/1.0/data_criteria.rb +105 -0
  17. data/lib/hqmf-parser/1.0/document.rb +209 -0
  18. data/lib/hqmf-parser/1.0/expression.rb +52 -0
  19. data/lib/hqmf-parser/1.0/population_criteria.rb +79 -0
  20. data/lib/hqmf-parser/1.0/precondition.rb +89 -0
  21. data/lib/hqmf-parser/1.0/range.rb +65 -0
  22. data/lib/hqmf-parser/1.0/restriction.rb +157 -0
  23. data/lib/hqmf-parser/1.0/utilities.rb +41 -0
  24. data/lib/hqmf-parser/2.0/data_criteria.rb +319 -0
  25. data/lib/hqmf-parser/2.0/document.rb +165 -0
  26. data/lib/hqmf-parser/2.0/population_criteria.rb +53 -0
  27. data/lib/hqmf-parser/2.0/precondition.rb +44 -0
  28. data/lib/hqmf-parser/2.0/types.rb +223 -0
  29. data/lib/hqmf-parser/2.0/utilities.rb +30 -0
  30. data/lib/hqmf-parser/converter/pass1/data_criteria_converter.rb +254 -0
  31. data/lib/hqmf-parser/converter/pass1/document_converter.rb +183 -0
  32. data/lib/hqmf-parser/converter/pass1/population_criteria_converter.rb +135 -0
  33. data/lib/hqmf-parser/converter/pass1/precondition_converter.rb +164 -0
  34. data/lib/hqmf-parser/converter/pass1/precondition_extractor.rb +159 -0
  35. data/lib/hqmf-parser/converter/pass1/simple_data_criteria.rb +35 -0
  36. data/lib/hqmf-parser/converter/pass1/simple_operator.rb +89 -0
  37. data/lib/hqmf-parser/converter/pass1/simple_population_criteria.rb +10 -0
  38. data/lib/hqmf-parser/converter/pass1/simple_precondition.rb +63 -0
  39. data/lib/hqmf-parser/converter/pass1/simple_restriction.rb +64 -0
  40. data/lib/hqmf-parser/converter/pass2/comparison_converter.rb +91 -0
  41. data/lib/hqmf-parser/converter/pass2/operator_converter.rb +169 -0
  42. data/lib/hqmf-parser/converter/pass3/specific_occurrence_converter.rb +86 -0
  43. data/lib/hqmf-parser/converter/pass3/specific_occurrence_converter_bak.rb +70 -0
  44. data/lib/hqmf-parser/parser.rb +22 -0
  45. data/lib/hqmf-parser/value_sets/value_set_parser.rb +206 -0
  46. data/lib/tasks/coverme.rake +8 -0
  47. data/lib/tasks/hqmf.rake +141 -0
  48. data/lib/tasks/value_sets.rake +23 -0
  49. metadata +159 -0
@@ -0,0 +1,53 @@
1
+ module HQMF2
2
+ # Represents an HQMF population criteria, also supports all the same methods as
3
+ # HQMF2::Precondition
4
+ class PopulationCriteria
5
+
6
+ include HQMF2::Utilities
7
+
8
+ attr_reader :preconditions, :id, :hqmf_id, :title, :type
9
+
10
+ # Create a new population criteria from the supplied HQMF entry
11
+ # @param [Nokogiri::XML::Element] the HQMF entry
12
+ def initialize(entry, doc)
13
+ @doc = doc
14
+ @entry = entry
15
+ @hqmf_id = attr_val('./*/cda:id/@extension')
16
+ @title = attr_val('./*/cda:code/cda:displayName/@value')
17
+ @type = attr_val('./*/cda:code/@code')
18
+ @preconditions = @entry.xpath('./*/cda:precondition[not(@nullFlavor)]', HQMF2::Document::NAMESPACES).collect do |precondition|
19
+ Precondition.new(precondition, @doc)
20
+ end
21
+ end
22
+
23
+ def create_human_readable_id(id)
24
+ @id = id
25
+ end
26
+
27
+ # Return true of this precondition represents a conjunction with nested preconditions
28
+ # or false of this precondition is a reference to a data criteria
29
+ def conjunction?
30
+ true
31
+ end
32
+
33
+ # Get the conjunction code, e.g. allTrue, allFalse
34
+ # @return [String] conjunction code
35
+ def conjunction_code
36
+ case @type
37
+ when HQMF::PopulationCriteria::IPP, HQMF::PopulationCriteria::DENOM, HQMF::PopulationCriteria::NUMER
38
+ HQMF::Precondition::ALL_TRUE
39
+ when HQMF::PopulationCriteria::EXCEP, HQMF::PopulationCriteria::DENEX
40
+ HQMF::Precondition::AT_LEAST_ONE_TRUE
41
+ else
42
+ raise "Unknown population type [#{@type}]"
43
+ end
44
+ end
45
+
46
+ def to_model
47
+ mps = preconditions.collect {|p| p.to_model}
48
+ HQMF::PopulationCriteria.new(id, hqmf_id, type, mps, title)
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,44 @@
1
+ module HQMF2
2
+
3
+ class Precondition
4
+
5
+ include HQMF2::Utilities
6
+
7
+ attr_reader :preconditions, :reference
8
+
9
+ def initialize(entry, doc)
10
+ @doc = doc
11
+ @entry = entry
12
+ @preconditions = @entry.xpath('./*/cda:precondition', HQMF2::Document::NAMESPACES).collect do |precondition|
13
+ Precondition.new(precondition, @doc)
14
+ end
15
+ reference_def = @entry.at_xpath('./*/cda:id', HQMF2::Document::NAMESPACES)
16
+ if reference_def
17
+ @reference = Reference.new(reference_def)
18
+ end
19
+ end
20
+
21
+ # Return true of this precondition represents a conjunction with nested preconditions
22
+ # or false of this precondition is a reference to a data criteria
23
+ def conjunction?
24
+ @preconditions.length>0
25
+ end
26
+
27
+ # Get the conjunction code, e.g. allTrue, allFalse
28
+ # @return [String] conjunction code
29
+ def conjunction_code
30
+ if conjunction?
31
+ @entry.at_xpath('./*[1]', HQMF2::Document::NAMESPACES).name
32
+ else
33
+ nil
34
+ end
35
+ end
36
+
37
+ def to_model
38
+ pcs = preconditions.collect {|p| p.to_model}
39
+ mr = reference ? reference.to_model : nil
40
+ HQMF::Precondition.new(nil, pcs, mr, conjunction_code, false)
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,223 @@
1
+ module HQMF2
2
+ # Used to represent 'any value' in criteria that require a value be present but
3
+ # don't specify any restrictions on that value
4
+ class AnyValue
5
+ attr_reader :type
6
+
7
+ def initialize(type='ANYNonNull')
8
+ @type = type
9
+ end
10
+
11
+ def to_model
12
+ HQMF::AnyValue.new(@type)
13
+ end
14
+ end
15
+
16
+ # Represents a bound within a HQMF pauseQuantity, has a value, a unit and an
17
+ # inclusive/exclusive indicator
18
+ class Value
19
+ include HQMF2::Utilities
20
+
21
+ attr_reader :type, :unit, :value
22
+
23
+ def initialize(entry, default_type='PQ')
24
+ @entry = entry
25
+ @type = attr_val('./@xsi:type') || default_type
26
+ @unit = attr_val('./@unit')
27
+ @value = attr_val('./@value')
28
+ end
29
+
30
+ def inclusive?
31
+ case attr_val('./@inclusive')
32
+ when 'false'
33
+ false
34
+ else
35
+ true
36
+ end
37
+ end
38
+
39
+ def derived?
40
+ case attr_val('./@nullFlavor')
41
+ when 'DER'
42
+ true
43
+ else
44
+ false
45
+ end
46
+ end
47
+
48
+ def expression
49
+ if !derived?
50
+ nil
51
+ else
52
+ attr_val('./cda:expression/@value')
53
+ end
54
+ end
55
+
56
+ def to_model
57
+ HQMF::Value.new(type,unit,value,inclusive?,derived?,expression)
58
+ end
59
+ end
60
+
61
+ # Represents a HQMF physical quantity which can have low and high bounds
62
+ class Range
63
+ include HQMF2::Utilities
64
+ attr_accessor :low, :high, :width
65
+
66
+ def initialize(entry, type=nil)
67
+ @type = type
68
+ @entry = entry
69
+ if @entry
70
+ @low = optional_value('./cda:low', default_bounds_type)
71
+ @high = optional_value('./cda:high', default_bounds_type)
72
+ @width = optional_value('./cda:width', 'PQ')
73
+ end
74
+ end
75
+
76
+ def type
77
+ @type || attr_val('./@xsi:type')
78
+ end
79
+
80
+ def to_model
81
+ lm = low ? low.to_model : nil
82
+ hm = high ? high.to_model : nil
83
+ wm = width ? width.to_model : nil
84
+ HQMF::Range.new(type, lm, hm, wm)
85
+ end
86
+
87
+ private
88
+
89
+ def optional_value(xpath, type)
90
+ value_def = @entry.at_xpath(xpath, HQMF2::Document::NAMESPACES)
91
+ if value_def
92
+ Value.new(value_def, type)
93
+ else
94
+ nil
95
+ end
96
+ end
97
+
98
+ def default_bounds_type
99
+ case type
100
+ when 'IVL_TS'
101
+ 'TS'
102
+ else
103
+ 'PQ'
104
+ end
105
+ end
106
+ end
107
+
108
+ # Represents a HQMF effective time which is a specialization of a interval
109
+ class EffectiveTime < Range
110
+ def initialize(entry)
111
+ super
112
+ end
113
+
114
+ def type
115
+ 'IVL_TS'
116
+ end
117
+ end
118
+
119
+ # Represents a HQMF CD value which has a code and codeSystem
120
+ class Coded
121
+ include HQMF2::Utilities
122
+
123
+ def initialize(entry)
124
+ @entry = entry
125
+ end
126
+
127
+ def type
128
+ attr_val('./@xsi:type') || 'CD'
129
+ end
130
+
131
+ def system
132
+ attr_val('./@codeSystem')
133
+ end
134
+
135
+ def code
136
+ attr_val('./@code')
137
+ end
138
+
139
+ def code_list_id
140
+ attr_val('./@valueSet')
141
+ end
142
+
143
+ def title
144
+ attr_val('./@displayName')
145
+ end
146
+
147
+ def value
148
+ code
149
+ end
150
+
151
+ def derived?
152
+ false
153
+ end
154
+
155
+ def unit
156
+ nil
157
+ end
158
+
159
+ def to_model
160
+ HQMF::Coded.new(type, system, code, code_list_id, title)
161
+ end
162
+
163
+ end
164
+
165
+ class SubsetOperator
166
+ include HQMF2::Utilities
167
+
168
+ attr_reader :type, :value
169
+
170
+ def initialize(entry)
171
+ @entry = entry
172
+ @type = attr_val('./cda:subsetCode/@code')
173
+ value_def = @entry.at_xpath('./*/cda:repeatNumber', HQMF2::Document::NAMESPACES)
174
+ if value_def
175
+ @value = HQMF2::Range.new(value_def, 'IVL_INT')
176
+ end
177
+ end
178
+
179
+ def to_model
180
+ vm = value ? value.to_model : nil
181
+ HQMF::SubsetOperator.new(type, vm)
182
+ end
183
+ end
184
+
185
+ class TemporalReference
186
+ include HQMF2::Utilities
187
+
188
+ attr_reader :type, :reference, :range
189
+
190
+ def initialize(entry)
191
+ @entry = entry
192
+ @type = attr_val('./@typeCode')
193
+ @reference = Reference.new(@entry.at_xpath('./*/cda:id', HQMF2::Document::NAMESPACES))
194
+ range_def = @entry.at_xpath('./cda:pauseQuantity', HQMF2::Document::NAMESPACES)
195
+ if range_def
196
+ @range = HQMF2::Range.new(range_def, 'IVL_PQ')
197
+ end
198
+ end
199
+
200
+ def to_model
201
+ rm = range ? range.to_model : nil
202
+ HQMF::TemporalReference.new(type, reference.to_model, rm)
203
+ end
204
+ end
205
+
206
+ # Represents a HQMF reference from a precondition to a data criteria
207
+ class Reference
208
+ include HQMF2::Utilities
209
+
210
+ def initialize(entry)
211
+ @entry = entry
212
+ end
213
+
214
+ def id
215
+ attr_val('./@extension')
216
+ end
217
+
218
+ def to_model
219
+ HQMF::Reference.new(id)
220
+ end
221
+ end
222
+
223
+ end
@@ -0,0 +1,30 @@
1
+ module HQMF2
2
+ module Utilities
3
+
4
+ include HQMF::Conversion::Utilities
5
+
6
+ # Utility function to handle optional attributes
7
+ # @param xpath an XPath that identifies an XML attribute
8
+ # @return the value of the attribute or nil if the attribute is missing
9
+ def attr_val(xpath)
10
+ Utilities::attr_val(@entry, xpath)
11
+ end
12
+
13
+ # Utility function to handle optional attributes
14
+ # @param xpath an XPath that identifies an XML attribute
15
+ # @return the value of the attribute or nil if the attribute is missing
16
+ def self.attr_val(node, xpath)
17
+ attr = node.at_xpath(xpath, HQMF2::Document::NAMESPACES)
18
+ if attr
19
+ attr.value
20
+ else
21
+ nil
22
+ end
23
+ end
24
+
25
+ def to_xml
26
+ @entry.to_xml
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,254 @@
1
+ module HQMF
2
+ # Class representing an HQMF document
3
+ class DataCriteriaConverter
4
+
5
+ attr_reader :v1_data_criteria_by_id, :v2_data_criteria, :v2_data_criteria_to_delete, :measure_period_criteria, :measure_period_v1_keys, :specific_occurrences
6
+
7
+ def initialize(doc, measure_period)
8
+ @doc = doc
9
+ @v1_data_criteria_by_id = {}
10
+ @v2_data_criteria = []
11
+ @v2_data_criteria_to_delete = {}
12
+ @specific_occurrences = {}
13
+ @measure_period = measure_period
14
+ parse()
15
+ end
16
+
17
+ def final_v2_data_criteria
18
+ @v2_data_criteria.delete_if {|criteria| @v2_data_criteria_to_delete[criteria.id] }
19
+ end
20
+
21
+ # duplicates a data criteria. This is important because we may be modifying source data criteria like patient characteristic birthdate to add restrictions
22
+ # the restrictions added may be different for the numerator, denominator, different IPP_1, IPP_2, etc.
23
+ def duplicate_data_criteria(data_criteria, parent_id)
24
+
25
+ # if this is a specific occurrence, then we do not want to duplicate it.
26
+ # we may need to duplicate it for a population however.
27
+ # return data_criteria if (specific_occurrences[data_criteria.id])
28
+
29
+ if (data_criteria.is_a? HQMF::Converter::SimpleDataCriteria and data_criteria.precondition_id == parent_id)
30
+ new_data_criteria = data_criteria
31
+ else
32
+ new_data_criteria = HQMF::Converter::SimpleDataCriteria.from_data_criteria(data_criteria)
33
+ new_data_criteria.assign_precondition(parent_id)
34
+ @v2_data_criteria << new_data_criteria
35
+ # we want to delete the original for data criteria that have been duplicated
36
+ @v2_data_criteria_to_delete[data_criteria.id] = true if !@v2_data_criteria_to_delete.keys.include? data_criteria.id
37
+ end
38
+
39
+ new_data_criteria
40
+ end
41
+
42
+ # make sure that if a data criteria is used as a target, that it is not deleted by someone else.
43
+ # this is required for birthdate in NQF0106
44
+ def validate_not_deleted(target)
45
+ @v2_data_criteria_to_delete[target] = false
46
+ end
47
+
48
+ # grouping data criteria are used to allow a single reference off of a temporal reference or subset operator
49
+ # grouping data criteria can reference either regular data criteria as children, or other grouping data criteria
50
+ def create_group_data_criteria(preconditions, type, value, parent_id, id, standard_category, qds_data_type)
51
+ extract_group_data_criteria_tree(HQMF::DataCriteria::UNION,preconditions, type, parent_id)
52
+ end
53
+
54
+ def build_group_data_criteria(children, section, parent_id, derivation_operator)
55
+
56
+ criteria_ids = children.map(&:id)
57
+ # make sure nobody else is going to delete the criteria we've grouped
58
+ criteria_ids.each {|target| validate_not_deleted(target)}
59
+
60
+ id = "#{parent_id}_#{section}_#{@@ids.next}"
61
+ title = "#{id}"
62
+ description = ""
63
+ definition = 'derived'
64
+ _display_name,_code_list_id,_status,_value,_field_values,_effective_time,_inline_code_list,_negation_code_list_id, = nil
65
+ _negation = false
66
+
67
+ group_criteria = HQMF::DataCriteria.new(id, title, _display_name, description, _code_list_id, criteria_ids, derivation_operator, definition, _status,
68
+ _value, _field_values, _effective_time, _inline_code_list,_negation,_negation_code_list_id,nil,nil,nil,nil)
69
+
70
+ @v2_data_criteria << group_criteria
71
+
72
+ group_criteria
73
+
74
+ end
75
+
76
+ # pull the children data criteria out of a set of preconditions
77
+ def extract_group_data_criteria_tree(conjunction, preconditions, type, parent_id)
78
+
79
+ children = []
80
+ preconditions.each do |precondition|
81
+ if (precondition.comparison?)
82
+ if (precondition.reference.id == HQMF::Document::MEASURE_PERIOD_ID)
83
+ children << measure_period_criteria
84
+ else
85
+ children << v2_data_criteria_by_id[precondition.reference.id]
86
+ end
87
+ else
88
+ converted_conjunction = convert_grouping_conjunction(precondition.conjunction_code)
89
+ children << extract_group_data_criteria_tree(converted_conjunction, precondition.preconditions, type, parent_id)
90
+ end
91
+ end
92
+
93
+ # if we have just one child element, just return it. An AND or OR of a single item is not useful.
94
+ if (children.size > 1)
95
+ build_group_data_criteria(children, type, parent_id, conjunction)
96
+ else
97
+ children.first
98
+ end
99
+
100
+ end
101
+
102
+ def convert_grouping_conjunction(conjunction)
103
+ case conjunction
104
+ when HQMF::Precondition::AT_LEAST_ONE_TRUE
105
+ HQMF::DataCriteria::UNION
106
+ when HQMF::Precondition::ALL_TRUE
107
+ HQMF::DataCriteria::XPRODUCT
108
+ else
109
+ 'unknown'
110
+ end
111
+ end
112
+
113
+ # pull the children data criteria out of a set of preconditions
114
+ def self.extract_data_criteria(preconditions, data_criteria_converter)
115
+ flattened = []
116
+ preconditions.each do |precondition|
117
+ if (precondition.comparison?)
118
+ if (precondition.reference.id == HQMF::Document::MEASURE_PERIOD_ID)
119
+ flattened << data_criteria_converter.measure_period_criteria
120
+ else
121
+ flattened << data_criteria_converter.v2_data_criteria_by_id[precondition.reference.id]
122
+ end
123
+ else
124
+ flattened.concat(extract_data_criteria(precondition.preconditions,data_criteria_converter))
125
+ end
126
+ end
127
+ flattened
128
+ end
129
+
130
+ def v2_data_criteria_by_id
131
+ criteria_by_id = {}
132
+ @v2_data_criteria.each do |criteria|
133
+ criteria_by_id[criteria.id] = criteria
134
+ end
135
+ criteria_by_id
136
+ end
137
+
138
+ private
139
+
140
+ def parse()
141
+ @doc[:data_criteria].each do |key,criteria|
142
+ parsed_criteria = HQMF::DataCriteriaConverter.convert(key, criteria)
143
+ @v2_data_criteria << parsed_criteria
144
+ @v1_data_criteria_by_id[criteria[:id]] = parsed_criteria
145
+ @specific_occurrences[parsed_criteria.id] = criteria[:derived_from] != nil
146
+ end
147
+ create_measure_period_v1_data_criteria(@doc,@measure_period,@v1_data_criteria_by_id)
148
+ end
149
+
150
+ def self.convert(key, criteria)
151
+
152
+ # @param [String] id
153
+ # @param [String] title
154
+ # @param [String] standard_category
155
+ # @param [String] qds_data_type
156
+ # @param [String] subset_code
157
+ # @param [String] code_list_id
158
+ # @param [String] property
159
+ # @param [String] type
160
+ # @param [String] status
161
+ # @param [boolean] negation
162
+ # @param [String] negation_code_list_id
163
+ # @param [Value|Range|Coded] value
164
+ # @param [Range] effective_time
165
+ # @param [Hash<String,String>] inline_code_list
166
+
167
+ id = convert_key(key)
168
+ title = criteria[:title]
169
+ title = title.match(/.*:\s+(.+)/)[1]
170
+ description = criteria[:description]
171
+ code_list_id = criteria[:code_list_id]
172
+ definition = criteria[:definition]
173
+ status = criteria[:status]
174
+ negation = criteria[:negation]
175
+ negation_code_list_id = criteria[:negation_code_list_id]
176
+ specific_occurrence = criteria[:specific_occurrence]
177
+ specific_occurrence_const = criteria[:specific_occurrence_const]
178
+
179
+ value = nil # value is filled out by backfill_patient_characteristics for things like gender and by REFR restrictions
180
+ effective_time = nil # filled out by temporal reference code
181
+ temporal_references = # filled out by operator code
182
+ subset_operators = nil # filled out by operator code
183
+ children_criteria = nil # filled out by operator and temporal reference code
184
+ derivation_operator = nil # filled out by operator and temporal reference code
185
+ negation_code_list_id = nil # filled out by RSON restrictions
186
+ field_values = nil # field values are filled out by SUBJ and REFR restrictions
187
+ inline_code_list = nil # inline code list is only used in HQMF V2, so we can just pass in nil
188
+ display_name=nil
189
+
190
+ HQMF::DataCriteria.new(id, title, display_name, description, code_list_id, children_criteria, derivation_operator, definition, status,
191
+ value, field_values, effective_time, inline_code_list, negation, negation_code_list_id, temporal_references, subset_operators,specific_occurrence,specific_occurrence_const)
192
+
193
+ end
194
+
195
+
196
+ # this method creates V1 data criteria for the measurement period. These data criteria can be
197
+ # referenced properly within the restrictions
198
+ def create_measure_period_v1_data_criteria(doc,measure_period,v1_data_criteria_by_id)
199
+
200
+ attributes = doc[:attributes]
201
+ attributes.keys.each {|key| attributes[key.to_s] = attributes[key]}
202
+
203
+ measure_period_key = attributes['MEASUREMENT_PERIOD'][:id]
204
+ measure_start_key = attributes['MEASUREMENT_START_DATE'][:id]
205
+ measure_end_key = attributes['MEASUREMENT_END_DATE'][:id]
206
+
207
+ @measure_period_v1_keys = {measure_start: measure_start_key, measure_end: measure_end_key, measure_period: measure_period_key}
208
+
209
+ type = 'variable'
210
+ code_list_id,negation_code_list_id,property,status,field_values,effective_time,inline_code_list,children_criteria,derivation_operator,temporal_references,subset_operators=nil
211
+
212
+ #####
213
+ ##
214
+ ######### SET MEASURE PERIOD
215
+ ##
216
+ #####
217
+
218
+ measure_period_id = HQMF::Document::MEASURE_PERIOD_ID
219
+ value = measure_period
220
+ measure_criteria = HQMF::DataCriteria.new(measure_period_id,measure_period_id,nil,measure_period_id,code_list_id,children_criteria,derivation_operator,measure_period_id,status,
221
+ value,field_values,effective_time,inline_code_list, false, nil, temporal_references,subset_operators,nil,nil)
222
+
223
+ # set the measure period data criteria for all measure period keys
224
+ v1_data_criteria_by_id[measure_period_key] = measure_criteria
225
+ v1_data_criteria_by_id[measure_start_key] = measure_criteria
226
+ v1_data_criteria_by_id[measure_end_key] = measure_criteria
227
+ @measure_period_criteria = measure_criteria
228
+
229
+ end
230
+
231
+
232
+ def self.title_from_description(title, description)
233
+ title.gsub(/^#{Regexp.escape(description).gsub('\\ ',':?,?\\ ')}:\s*/i,'')
234
+ end
235
+
236
+ def self.convert_key(key)
237
+ key.to_s.downcase.gsub('_', ' ').split(' ').map {|w| w.capitalize }.join('')
238
+ end
239
+
240
+ # Simple class to issue monotonically increasing integer identifiers
241
+ class Counter
242
+ def initialize
243
+ @count = 0
244
+ end
245
+
246
+ def next
247
+ @count+=1
248
+ end
249
+ end
250
+ @@ids = Counter.new
251
+
252
+
253
+ end
254
+ end