cqm-parsers 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +29 -0
  3. data/README.md +21 -0
  4. data/Rakefile +19 -0
  5. data/lib/ext/code.rb +10 -0
  6. data/lib/ext/data_element.rb +24 -0
  7. data/lib/hqmf-model/attribute.rb +63 -0
  8. data/lib/hqmf-model/data_criteria.rb +467 -0
  9. data/lib/hqmf-model/document.rb +253 -0
  10. data/lib/hqmf-model/population_criteria.rb +102 -0
  11. data/lib/hqmf-model/precondition.rb +94 -0
  12. data/lib/hqmf-model/types.rb +457 -0
  13. data/lib/hqmf-model/utilities.rb +52 -0
  14. data/lib/hqmf-parser.rb +116 -0
  15. data/lib/hqmf-parser/1.0/attribute.rb +121 -0
  16. data/lib/hqmf-parser/1.0/comparison.rb +34 -0
  17. data/lib/hqmf-parser/1.0/data_criteria.rb +92 -0
  18. data/lib/hqmf-parser/1.0/document.rb +195 -0
  19. data/lib/hqmf-parser/1.0/expression.rb +60 -0
  20. data/lib/hqmf-parser/1.0/observation.rb +61 -0
  21. data/lib/hqmf-parser/1.0/population_criteria.rb +75 -0
  22. data/lib/hqmf-parser/1.0/precondition.rb +90 -0
  23. data/lib/hqmf-parser/1.0/range.rb +76 -0
  24. data/lib/hqmf-parser/1.0/restriction.rb +162 -0
  25. data/lib/hqmf-parser/1.0/utilities.rb +55 -0
  26. data/lib/hqmf-parser/2.0/data_criteria.rb +372 -0
  27. data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_base_extract.rb +80 -0
  28. data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_definition_from_template_or_type_extract.rb +201 -0
  29. data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_post_processing.rb +85 -0
  30. data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_specific_occurrences_and_source_data_criteria_extract.rb +117 -0
  31. data/lib/hqmf-parser/2.0/document.rb +304 -0
  32. data/lib/hqmf-parser/2.0/document_helpers/doc_population_helper.rb +173 -0
  33. data/lib/hqmf-parser/2.0/document_helpers/doc_utilities.rb +131 -0
  34. data/lib/hqmf-parser/2.0/field_value_helper.rb +251 -0
  35. data/lib/hqmf-parser/2.0/population_criteria.rb +134 -0
  36. data/lib/hqmf-parser/2.0/precondition.rb +73 -0
  37. data/lib/hqmf-parser/2.0/source_data_criteria_helper.rb +112 -0
  38. data/lib/hqmf-parser/2.0/types.rb +448 -0
  39. data/lib/hqmf-parser/2.0/utilities.rb +45 -0
  40. data/lib/hqmf-parser/2.0/value_set_helper.rb +104 -0
  41. data/lib/hqmf-parser/converter/pass1/data_criteria_converter.rb +257 -0
  42. data/lib/hqmf-parser/converter/pass1/document_converter.rb +133 -0
  43. data/lib/hqmf-parser/converter/pass1/population_criteria_converter.rb +185 -0
  44. data/lib/hqmf-parser/converter/pass1/precondition_converter.rb +173 -0
  45. data/lib/hqmf-parser/converter/pass1/precondition_extractor.rb +201 -0
  46. data/lib/hqmf-parser/converter/pass1/simple_data_criteria.rb +26 -0
  47. data/lib/hqmf-parser/converter/pass1/simple_operator.rb +89 -0
  48. data/lib/hqmf-parser/converter/pass1/simple_population_criteria.rb +10 -0
  49. data/lib/hqmf-parser/converter/pass1/simple_precondition.rb +51 -0
  50. data/lib/hqmf-parser/converter/pass1/simple_restriction.rb +64 -0
  51. data/lib/hqmf-parser/converter/pass2/comparison_converter.rb +112 -0
  52. data/lib/hqmf-parser/converter/pass2/operator_converter.rb +102 -0
  53. data/lib/hqmf-parser/cql/data_criteria.rb +57 -0
  54. data/lib/hqmf-parser/cql/data_criteria_helpers/dc_definition_from_template_or_type_extract.rb +79 -0
  55. data/lib/hqmf-parser/cql/data_criteria_helpers/dc_post_processing.rb +43 -0
  56. data/lib/hqmf-parser/cql/document.rb +78 -0
  57. data/lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb +124 -0
  58. data/lib/hqmf-parser/cql/value_set_helper.rb +103 -0
  59. data/lib/hqmf-parser/parser.rb +100 -0
  60. data/lib/qrda-export/catI-r5/qrda1_r5.rb +125 -0
  61. data/lib/qrda-export/helper/cat_1_view_helper.rb +142 -0
  62. data/lib/qrda-export/helper/code_system_helper.rb +77 -0
  63. data/lib/qrda-export/helper/date_helper.rb +81 -0
  64. data/lib/qrda-import/base-importers/demographics_importer.rb +47 -0
  65. data/lib/qrda-import/base-importers/medication_importer.rb +22 -0
  66. data/lib/qrda-import/base-importers/section_importer.rb +196 -0
  67. data/lib/qrda-import/cda_identifier.rb +19 -0
  68. data/lib/qrda-import/data-element-importers/adverse_event_importer.rb +23 -0
  69. data/lib/qrda-import/data-element-importers/allergy_intolerance_importer.rb +21 -0
  70. data/lib/qrda-import/data-element-importers/assessment_performed_importer.rb +23 -0
  71. data/lib/qrda-import/data-element-importers/communication_from_patient_to_provider_importer.rb +18 -0
  72. data/lib/qrda-import/data-element-importers/communication_from_provider_to_patient_importer.rb +18 -0
  73. data/lib/qrda-import/data-element-importers/communication_from_provider_to_provider_importer.rb +20 -0
  74. data/lib/qrda-import/data-element-importers/device_applied_importer.rb +23 -0
  75. data/lib/qrda-import/data-element-importers/device_order_importer.rb +18 -0
  76. data/lib/qrda-import/data-element-importers/diagnosis_importer.rb +23 -0
  77. data/lib/qrda-import/data-element-importers/diagnostic_study_order_importer.rb +20 -0
  78. data/lib/qrda-import/data-element-importers/diagnostic_study_performed_importer.rb +30 -0
  79. data/lib/qrda-import/data-element-importers/encounter_order_importer.rb +20 -0
  80. data/lib/qrda-import/data-element-importers/encounter_performed_importer.rb +41 -0
  81. data/lib/qrda-import/data-element-importers/immunization_administered_importer.rb +18 -0
  82. data/lib/qrda-import/data-element-importers/intervention_order_importer.rb +18 -0
  83. data/lib/qrda-import/data-element-importers/intervention_performed_importer.rb +22 -0
  84. data/lib/qrda-import/data-element-importers/laboratory_test_order_importer.rb +20 -0
  85. data/lib/qrda-import/data-element-importers/laboratory_test_performed_importer.rb +28 -0
  86. data/lib/qrda-import/data-element-importers/medication_active_importer.rb +17 -0
  87. data/lib/qrda-import/data-element-importers/medication_administered_importer.rb +17 -0
  88. data/lib/qrda-import/data-element-importers/medication_discharge_importer.rb +19 -0
  89. data/lib/qrda-import/data-element-importers/medication_dispensed_importer.rb +19 -0
  90. data/lib/qrda-import/data-element-importers/medication_order_importer.rb +16 -0
  91. data/lib/qrda-import/data-element-importers/patient_characteristic_expired.rb +21 -0
  92. data/lib/qrda-import/data-element-importers/physical_exam_performed_importer.rb +26 -0
  93. data/lib/qrda-import/data-element-importers/procedure_order_importer.rb +26 -0
  94. data/lib/qrda-import/data-element-importers/procedure_performed_importer.rb +34 -0
  95. data/lib/qrda-import/data-element-importers/substance_administered_importer.rb +16 -0
  96. data/lib/qrda-import/entry_finder.rb +20 -0
  97. data/lib/qrda-import/entry_package.rb +16 -0
  98. data/lib/qrda-import/narrative_reference_handler.rb +33 -0
  99. data/lib/qrda-import/patient_importer.rb +105 -0
  100. data/lib/util/code_system_helper.rb +76 -0
  101. data/lib/util/counter.rb +20 -0
  102. data/lib/util/hqmf_template_helper.rb +39 -0
  103. metadata +340 -0
@@ -0,0 +1,253 @@
1
+ module HQMF
2
+ # Class representing an HQMF document
3
+ class Document
4
+
5
+ MEASURE_PERIOD_ID = "MeasurePeriod"
6
+
7
+ STRATIFIED_POPULATION_TEMPLATE_ID = '2.16.840.1.113883.3.100.1.2'
8
+ STRATIFIED_POPULATION_TEMPLATE_TITLE = 'Stratified'
9
+
10
+ include HQMF::Conversion::Utilities
11
+
12
+ attr_reader :id, :title, :description, :measure_period, :attributes, :populations, :source_data_criteria, :hqmf_id, :hqmf_set_id, :hqmf_version_number, :cms_id, :populations_cql_map, :cql_measure_library, :observations
13
+
14
+ # Create a new HQMF::Document which can be converted to JavaScript
15
+ # @param [String] id
16
+ # @param [String] hqmf_id
17
+ # @param [String] hqmf_set_id
18
+ # @param [String] hqmf_version_number
19
+ # @param [String] title
20
+ # @param [String] description
21
+ # @param [Array#PopulationCritera] population_criteria
22
+ # @param [Array#DataCriteria] data_criteria
23
+ # @param [Array#DataCriteria] source_data_criteria
24
+ # @param [Array#Attribute] attributes
25
+ # @param [Array#Hash] populations
26
+ # @param [Range] measure_period
27
+ def initialize(id, hqmf_id, hqmf_set_id, hqmf_version_number, cms_id, title, description, population_criteria, data_criteria, source_data_criteria, attributes, measure_period, populations=nil, populations_cql_map=nil, cql_measure_library=nil, observations=nil)
28
+ @id = id
29
+ @hqmf_id = hqmf_id
30
+ @hqmf_set_id = hqmf_set_id
31
+ @hqmf_version_number = hqmf_version_number
32
+ @cms_id = cms_id
33
+ @title = title
34
+ @description = description
35
+ @population_criteria = population_criteria
36
+ @data_criteria = data_criteria
37
+ @source_data_criteria = source_data_criteria
38
+ @attributes = attributes
39
+ @populations = populations || [
40
+ {
41
+ HQMF::PopulationCriteria::IPP => HQMF::PopulationCriteria::IPP,
42
+ HQMF::PopulationCriteria::DENOM => HQMF::PopulationCriteria::DENOM,
43
+ HQMF::PopulationCriteria::NUMER => HQMF::PopulationCriteria::NUMER,
44
+ HQMF::PopulationCriteria::DENEXCEP => HQMF::PopulationCriteria::DENEXCEP,
45
+ HQMF::PopulationCriteria::DENEX => HQMF::PopulationCriteria::DENEX
46
+ }
47
+ ]
48
+ @measure_period = measure_period
49
+ @populations_cql_map = populations_cql_map
50
+ @cql_measure_library = cql_measure_library
51
+ @observations = observations
52
+ end
53
+
54
+ # Create a new HQMF::Document from a JSON hash keyed with symbols
55
+ def self.from_json(json)
56
+ id = json["id"]
57
+ hqmf_id = json["hqmf_id"]
58
+ hqmf_set_id = json["hqmf_set_id"]
59
+ hqmf_version_number = json["hqmf_version_number"]
60
+ title = json["title"]
61
+ description = json["description"]
62
+ cms_id = json["cms_id"]
63
+
64
+ population_criterias = []
65
+ json["population_criteria"].each do |key, population_criteria|
66
+ population_criterias << HQMF::PopulationCriteria.from_json(key.to_s, population_criteria)
67
+ end if json['population_criteria']
68
+
69
+ data_criterias = []
70
+ json["data_criteria"].each do |key, data_criteria|
71
+ data_criterias << HQMF::DataCriteria.from_json(key.to_s, data_criteria)
72
+ end
73
+
74
+ source_data_criterias = []
75
+ json["source_data_criteria"].each do |key, data_criteria|
76
+ source_data_criterias << HQMF::DataCriteria.from_json(key.to_s, data_criteria)
77
+ end
78
+
79
+ populations = json["populations"] if json["populations"]
80
+
81
+ attributes = json["attributes"].map {|attribute| HQMF::Attribute.from_json(attribute)} if json["attributes"]
82
+
83
+ measure_period = HQMF::Range.from_json(json["measure_period"]) if json["measure_period"]
84
+ HQMF::Document.new(id, hqmf_id, hqmf_set_id, hqmf_version_number, cms_id, title, description, population_criterias, data_criterias, source_data_criterias, attributes, measure_period,populations)
85
+ end
86
+
87
+ def to_json
88
+ json = build_hash(self, [:id, :hqmf_id, :hqmf_set_id, :hqmf_version_number, :title, :description, :cms_id])
89
+
90
+ json[:population_criteria] = {}
91
+ @population_criteria.each do |population|
92
+ json[:population_criteria].merge! population.to_json
93
+ end
94
+
95
+ json[:data_criteria] = {}
96
+ @data_criteria.each do |data|
97
+ json[:data_criteria].merge! data.to_json
98
+ end
99
+
100
+ json[:source_data_criteria] = {}
101
+ @source_data_criteria.each do |data|
102
+ json[:source_data_criteria].merge! data.to_json
103
+ end
104
+
105
+ x = nil
106
+ json[:attributes] = x if x = json_array(@attributes)
107
+
108
+ json[:populations] = @populations
109
+
110
+ json[:populations_cql_map] = @populations_cql_map
111
+
112
+ json[:observations] = @observations
113
+
114
+ json[:cql_measure_library] = @cql_measure_library
115
+
116
+ json[:measure_period] = @measure_period.to_json
117
+
118
+ json
119
+ end
120
+
121
+
122
+ # Get all the population criteria defined by the measure
123
+ # @return [Array] an array of HQMF::PopulationCriteria
124
+ def all_population_criteria
125
+ @population_criteria
126
+ end
127
+
128
+ # Get a specific population criteria by id.
129
+ # @param [String] id the population identifier
130
+ # @return [HQMF::PopulationCriteria] the matching criteria, raises an Exception if not found
131
+ def population_criteria(id)
132
+ find(@population_criteria, :id, id)
133
+ end
134
+
135
+ def is_cv?
136
+ find(@population_criteria, :type, HQMF::PopulationCriteria::MSRPOPL)
137
+ end
138
+
139
+ def find_population_by_type(type)
140
+ find(@population_criteria, :type, type)
141
+ end
142
+
143
+ # Get all the data criteria defined by the measure
144
+ # @return [Array] an array of HQMF::DataCriteria describing the data elements used by the measure
145
+ def all_data_criteria
146
+ @data_criteria
147
+ end
148
+
149
+ def all_code_set_oids
150
+ (@data_criteria.map {|d| d.all_code_set_oids }).flatten.compact.uniq
151
+ end
152
+
153
+ # Get the source data criteria that are specific occurrences
154
+ # @return [Array] an array of HQMF::DataCriteria describing the data elements used by the measure that are specific occurrences
155
+ def specific_occurrence_source_data_criteria(force_sources=nil)
156
+ return [] if @source_data_criteria.nil?
157
+ matching = @source_data_criteria.select {|dc| !dc.specific_occurrence.nil?}
158
+
159
+ if force_sources
160
+ existing = matching.map(&:id)
161
+ matching.concat @source_data_criteria.select {|dc| !existing.include?(dc.id) && force_sources.include?(dc.id)}
162
+ end
163
+
164
+ matching
165
+ end
166
+
167
+
168
+ # @return [Array] an array of HQMF::DataCriteria ids that are actually used in the measure
169
+ def referenced_data_criteria
170
+ data_criteria_ids = []
171
+ @population_criteria.each do |population|
172
+ data_criteria_ids.concat(population.referenced_data_criteria)
173
+ end
174
+ references = []
175
+ data_criteria_ids.each do |id|
176
+ dc = data_criteria(id)
177
+ references << id
178
+ from_dc = dc.referenced_data_criteria(self)
179
+ references.concat(from_dc)
180
+ end
181
+ used_dc = []
182
+ references.uniq.each do |id|
183
+ used_dc << data_criteria(id)
184
+ end
185
+ used_dc
186
+ end
187
+
188
+ # Get specific attributes by code.
189
+ # @param [String] code the attribute code
190
+ # @param [String] code_system the attribute code system
191
+ # @return [Array#Attribute] the matching attributes, raises an Exception if not found
192
+ def attributes_for_code(code, code_system)
193
+ @attributes.find_all { |e| e.send(:code) == code && e.send(:code_obj).send(:system) == code_system }
194
+ end
195
+
196
+ # Get a specific data criteria by id.
197
+ # @param [String] id the data criteria identifier
198
+ # @return [HQMF::DataCriteria] the matching data criteria, raises an Exception if not found
199
+ def data_criteria(id)
200
+ find(@data_criteria, :id, id)
201
+ end
202
+
203
+ # patient characteristics data criteria such as GENDER require looking at the codes to determine if the
204
+ # measure is interested in Males or Females. This process is awkward, and thus is done as a separate
205
+ # step after the document has been converted.
206
+ def backfill_patient_characteristics_with_codes(codes)
207
+
208
+ [].concat(self.all_data_criteria).concat(self.source_data_criteria).each do |data_criteria|
209
+ if (data_criteria.type == :characteristic and !data_criteria.property.nil?)
210
+ if (codes)
211
+ value_set = codes[data_criteria.code_list_id]
212
+ puts "\tno value set for unknown patient characteristic: #{data_criteria.id}" unless value_set
213
+ else
214
+ puts "\tno code set to back fill: #{data_criteria.title}"
215
+ next
216
+ end
217
+
218
+ if (data_criteria.property == :gender)
219
+ next if value_set.nil?
220
+ key = value_set.keys[0]
221
+ data_criteria.value = HQMF::Coded.new('CD','Administrative Sex',value_set[key].first)
222
+ else
223
+ data_criteria.inline_code_list = value_set
224
+ end
225
+
226
+ elsif (data_criteria.type == :characteristic)
227
+ if (codes)
228
+ value_set = codes[data_criteria.code_list_id]
229
+ if (value_set)
230
+ # this is looking for a birthdate characteristic that is set as a generic characteristic but points to a loinc code set
231
+ if (value_set['LOINC'] and value_set['LOINC'].first == '21112-8')
232
+ data_criteria.definition = 'patient_characteristic_birthdate'
233
+ end
234
+ # this is looking for a gender characteristic that is set as a generic characteristic
235
+ gender_key = (value_set.keys.select {|set| set == 'Administrative Sex' || set == 'AdministrativeSex'}).first
236
+ if (gender_key and ['M','F'].include? value_set[gender_key].first)
237
+ data_criteria.definition = 'patient_characteristic_gender'
238
+ data_criteria.value = HQMF::Coded.new('CD','Gender',value_set[gender_key].first)
239
+ end
240
+ end
241
+ end
242
+
243
+ end
244
+ end
245
+ end
246
+
247
+ private
248
+
249
+ def find(collection, attribute, value)
250
+ collection.find {|e| e.send(attribute)==value}
251
+ end
252
+ end
253
+ end
@@ -0,0 +1,102 @@
1
+ module HQMF
2
+ # Represents an HQMF population criteria, also supports all the same methods as
3
+ # HQMF::Precondition
4
+ class PopulationCriteria
5
+
6
+ include HQMF::Conversion::Utilities
7
+
8
+ attr_reader :preconditions, :id, :type, :title, :hqmf_id, :comments
9
+ attr_accessor :aggregator
10
+
11
+ IPP = 'IPP'
12
+ DENOM = 'DENOM'
13
+ NUMER = 'NUMER'
14
+ NUMEX = 'NUMEX'
15
+ DENEXCEP = 'DENEXCEP'
16
+ DENEX = 'DENEX'
17
+ MSRPOPL = 'MSRPOPL'
18
+ OBSERV = 'OBSERV'
19
+ MSRPOPLEX = 'MSRPOPLEX'
20
+
21
+ STRAT = 'STRAT'
22
+
23
+ ALL_POPULATION_CODES = [STRAT, IPP, DENOM, DENEX, NUMER, NUMEX, DENEXCEP, MSRPOPL, OBSERV, MSRPOPLEX]
24
+
25
+ # Create a new population criteria
26
+ # @param [String] id
27
+ # @param [String] hqmf_id
28
+ # @param [Array#Precondition] preconditions
29
+ # @param [String] title (optional)
30
+ def initialize(id, hqmf_id, type, preconditions, title='', aggregator=nil, comments=nil)
31
+ @id = id
32
+ @hqmf_id = hqmf_id
33
+ @preconditions = preconditions
34
+ @type = type
35
+ @title = title
36
+ @aggregator = aggregator
37
+ @comments = comments
38
+ end
39
+
40
+ # Create a new population criteria from a JSON hash keyed off symbols
41
+ def self.from_json(id, json)
42
+ preconditions = json["preconditions"].map do |precondition|
43
+ HQMF::Precondition.from_json(precondition)
44
+ end if json['preconditions']
45
+ type = json["type"]
46
+ title = json['title']
47
+ hqmf_id = json['hqmf_id']
48
+ aggregator = json['aggregator']
49
+ comments = json['comments']
50
+
51
+ HQMF::PopulationCriteria.new(id, hqmf_id, type, preconditions, title, aggregator, comments)
52
+ end
53
+
54
+ def to_json
55
+ {self.id.to_sym => base_json}
56
+ end
57
+
58
+ def base_json
59
+ x = nil
60
+ json = build_hash(self, [:conjunction?, :type, :title, :hqmf_id, :aggregator, :comments])
61
+ json[:preconditions] = x if x = json_array(@preconditions)
62
+ json
63
+ end
64
+
65
+ # Return true of this precondition represents a conjunction with nested preconditions
66
+ # or false of this precondition is a reference to a data criteria
67
+ # if it is an observation population criteria, then it is not a conjunction, it is instead doing a calculation
68
+ def conjunction?
69
+ type != HQMF::PopulationCriteria::OBSERV
70
+ end
71
+
72
+ # Get the conjunction code, e.g. allTrue, atLeastOneTrue
73
+ # @return [String] conjunction code
74
+ def conjunction_code
75
+
76
+ case @type
77
+ when IPP, STRAT, DENOM, NUMER, MSRPOPL
78
+ HQMF::Precondition::ALL_TRUE
79
+ when DENEXCEP, DENEX, MSRPOPLEX, NUMEX
80
+ HQMF::Precondition::AT_LEAST_ONE_TRUE
81
+ else
82
+ raise "Unknown population type [#{@type}]"
83
+ end
84
+
85
+ end
86
+
87
+ # Can't have negation on population so this is the same as conjunction_code
88
+ def conjunction_code_with_negation
89
+ conjunction_code
90
+ end
91
+
92
+ def referenced_data_criteria
93
+ data_criteria_ids = []
94
+ @preconditions.each do |precondition|
95
+ data_criteria_ids.concat(precondition.referenced_data_criteria)
96
+ end if @preconditions
97
+ data_criteria_ids
98
+ end
99
+
100
+ end
101
+
102
+ end
@@ -0,0 +1,94 @@
1
+ module HQMF
2
+
3
+ class Precondition
4
+
5
+ include HQMF::Conversion::Utilities
6
+
7
+ AT_LEAST_ONE_TRUE = 'atLeastOneTrue'
8
+ AT_LEAST_ONE_FALSE = 'atLeastOneFalse'
9
+ ALL_TRUE = 'allTrue'
10
+ ALL_FALSE = 'allFalse'
11
+ NEGATIONS = {
12
+ AT_LEAST_ONE_TRUE => ALL_FALSE,
13
+ ALL_FALSE => AT_LEAST_ONE_TRUE,
14
+ ALL_TRUE => AT_LEAST_ONE_FALSE,
15
+ AT_LEAST_ONE_FALSE => ALL_TRUE
16
+ }
17
+ INVERSIONS = {
18
+ AT_LEAST_ONE_TRUE => ALL_TRUE,
19
+ ALL_FALSE => AT_LEAST_ONE_FALSE,
20
+ ALL_TRUE => AT_LEAST_ONE_TRUE,
21
+ AT_LEAST_ONE_FALSE => ALL_FALSE
22
+ }
23
+
24
+ attr_reader :id, :preconditions, :reference, :conjunction_code
25
+ attr_accessor :negation, :comments
26
+
27
+ # Create a new population criteria
28
+ # @param [Array#Precondition] preconditions
29
+ # @param [Reference] reference
30
+ # @param [String] conjunction_code
31
+ def initialize(id, preconditions, reference, conjunction_code, negation, comments=nil)
32
+ @preconditions = preconditions || []
33
+ @reference = reference
34
+ @conjunction_code = conjunction_code
35
+ @negation = negation
36
+ @id = id
37
+ @comments = comments
38
+ end
39
+
40
+ def conjunction_code_with_negation
41
+ if negation
42
+ NEGATIONS[conjunction_code]
43
+ else
44
+ conjunction_code
45
+ end
46
+ end
47
+
48
+ # Create a new population criteria from a JSON hash keyed off symbols
49
+ def self.from_json(json)
50
+ preconditions = []
51
+ id = json["id"] if json["id"]
52
+ preconditions = json["preconditions"].map {|precondition| HQMF::Precondition.from_json(precondition)} if json["preconditions"]
53
+ reference = Reference.new(json["reference"]) if json["reference"]
54
+ conjunction_code = json["conjunction_code"] if json["conjunction_code"]
55
+ negation = json["negation"] if json["negation"]
56
+ comments = json['comments'] if json['comments']
57
+
58
+ HQMF::Precondition.new(id, preconditions, reference, conjunction_code, negation, comments)
59
+ end
60
+
61
+ def to_json
62
+ x = nil
63
+ json = {}
64
+ json[:id] = self.id
65
+ json[:reference] = self.reference.id if self.reference
66
+ json[:preconditions] = x if x = json_array(@preconditions)
67
+ json[:conjunction_code] = self.conjunction_code if self.conjunction_code && self.preconditions.length > 0
68
+ json[:negation] = self.negation if self.negation
69
+ json[:comments] = self.comments if self.comments
70
+ json
71
+ end
72
+
73
+ # Return true of this precondition represents a conjunction with nested preconditions
74
+ # or false of this precondition is a reference to a data criteria
75
+ def conjunction?
76
+ @preconditions.length>0
77
+ end
78
+
79
+ def referenced_data_criteria
80
+ data_criteria_ids = []
81
+ if @preconditions.empty?
82
+ data_criteria_ids << self.reference.id
83
+ else
84
+ @preconditions.each do |precondition|
85
+ data_criteria_ids.concat(precondition.referenced_data_criteria)
86
+ end
87
+ end
88
+ data_criteria_ids
89
+ end
90
+
91
+ end
92
+
93
+
94
+ end