health-data-standards 3.4.6 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/Gemfile +2 -2
  2. data/README.md +4 -0
  3. data/lib/health-data-standards.rb +1 -0
  4. data/lib/health-data-standards/export/cat_1.rb +4 -4
  5. data/lib/health-data-standards/export/helper/scooped_view_helper.rb +16 -16
  6. data/lib/health-data-standards/export/qrda/hqmf-qrda-oids.json +6 -0
  7. data/lib/health-data-standards/export/view_helper.rb +8 -1
  8. data/lib/health-data-standards/import/bulk_record_importer.rb +45 -13
  9. data/lib/health-data-standards/import/bundle/importer.rb +2 -4
  10. data/lib/health-data-standards/import/cda/provider_importer.rb +2 -2
  11. data/lib/health-data-standards/import/green_c32/section_importer.rb +2 -2
  12. data/lib/health-data-standards/import/provider_import_utils.rb +2 -2
  13. data/lib/health-data-standards/models/cda_identifier.rb +1 -0
  14. data/lib/health-data-standards/models/cqm/bundle.rb +4 -1
  15. data/lib/health-data-standards/models/cqm/measure.rb +40 -25
  16. data/lib/health-data-standards/models/cqm/patient_cache.rb +61 -60
  17. data/lib/health-data-standards/models/encounter.rb +4 -12
  18. data/lib/health-data-standards/models/entry.rb +4 -8
  19. data/lib/health-data-standards/models/facility.rb +1 -0
  20. data/lib/health-data-standards/models/fulfillment_history.rb +6 -18
  21. data/lib/health-data-standards/models/guarantor.rb +1 -0
  22. data/lib/health-data-standards/models/lab_result.rb +2 -6
  23. data/lib/health-data-standards/models/medical_equipment.rb +2 -7
  24. data/lib/health-data-standards/models/medication.rb +11 -31
  25. data/lib/health-data-standards/models/metadata/link_info.rb +1 -0
  26. data/lib/health-data-standards/models/order_information.rb +5 -13
  27. data/lib/health-data-standards/models/organization.rb +1 -0
  28. data/lib/health-data-standards/models/procedure.rb +1 -4
  29. data/lib/health-data-standards/models/provider.rb +2 -1
  30. data/lib/health-data-standards/models/provider_performance.rb +1 -0
  31. data/lib/health-data-standards/models/qrda/legal_authenticator.rb +1 -0
  32. data/lib/health-data-standards/models/qrda/organization.rb +2 -0
  33. data/lib/health-data-standards/models/record.rb +7 -7
  34. data/lib/health-data-standards/models/result_value.rb +1 -0
  35. data/lib/health-data-standards/models/svs/concept.rb +1 -0
  36. data/lib/health-data-standards/models/svs/value_set.rb +1 -0
  37. data/lib/health-data-standards/models/telecom.rb +1 -0
  38. data/lib/health-data-standards/models/transfer.rb +1 -0
  39. data/lib/health-data-standards/tasks/bundle.rake +3 -3
  40. data/lib/health-data-standards/util/vs_api.rb +2 -2
  41. data/lib/hqmf-generator/attribute.xml.erb +9 -11
  42. data/lib/hqmf-generator/characteristic_criteria.xml.erb +5 -5
  43. data/lib/hqmf-generator/code.xml.erb +6 -2
  44. data/lib/hqmf-generator/condition_criteria.xml.erb +4 -5
  45. data/lib/hqmf-generator/derivation.xml.erb +6 -6
  46. data/lib/hqmf-generator/description.xml.erb +1 -1
  47. data/lib/hqmf-generator/document.xml.erb +46 -11
  48. data/lib/hqmf-generator/encounter_criteria.xml.erb +4 -5
  49. data/lib/hqmf-generator/field.xml.erb +13 -1
  50. data/lib/hqmf-generator/grouper_criteria.xml.erb +17 -0
  51. data/lib/hqmf-generator/hqmf-generator.rb +75 -8
  52. data/lib/hqmf-generator/local_variable.xml.erb +1 -0
  53. data/lib/hqmf-generator/measure_observation_definition.xml.erb +25 -0
  54. data/lib/hqmf-generator/observation_criteria.xml.erb +4 -5
  55. data/lib/hqmf-generator/population_criteria.xml.erb +2 -3
  56. data/lib/hqmf-generator/precondition.xml.erb +2 -2
  57. data/lib/hqmf-generator/precondition_cv.xml.erb +8 -0
  58. data/lib/hqmf-generator/procedure_criteria.xml.erb +4 -5
  59. data/lib/hqmf-generator/reference.xml.erb +2 -2
  60. data/lib/hqmf-generator/source.xml.erb +2 -2
  61. data/lib/hqmf-generator/specific_occurrence.xml.erb +4 -5
  62. data/lib/hqmf-generator/subset.xml.erb +16 -3
  63. data/lib/hqmf-generator/substance_criteria.xml.erb +4 -5
  64. data/lib/hqmf-generator/supply_criteria.xml.erb +4 -5
  65. data/lib/hqmf-generator/temporal_relationship.xml.erb +1 -1
  66. data/lib/hqmf-generator/value.xml.erb +35 -9
  67. data/lib/hqmf-generator/variable_criteria.xml.erb +2 -3
  68. data/lib/hqmf-model/attribute.rb +36 -8
  69. data/lib/hqmf-model/data_criteria.json +38 -204
  70. data/lib/hqmf-model/data_criteria.rb +40 -16
  71. data/lib/hqmf-model/document.rb +61 -2
  72. data/lib/hqmf-model/population_criteria.rb +11 -7
  73. data/lib/hqmf-model/precondition.rb +1 -1
  74. data/lib/hqmf-model/types.rb +91 -8
  75. data/lib/hqmf-parser/1.0/attribute.rb +55 -2
  76. data/lib/hqmf-parser/1.0/document.rb +10 -23
  77. data/lib/hqmf-parser/1.0/population_criteria.rb +2 -2
  78. data/lib/hqmf-parser/1.0/range.rb +0 -1
  79. data/lib/hqmf-parser/2.0/data_criteria.rb +90 -21
  80. data/lib/hqmf-parser/2.0/document.rb +122 -7
  81. data/lib/hqmf-parser/2.0/population_criteria.rb +18 -6
  82. data/lib/hqmf-parser/2.0/precondition.rb +4 -1
  83. data/lib/hqmf-parser/2.0/types.rb +36 -15
  84. data/lib/hqmf-parser/converter/pass1/document_converter.rb +4 -56
  85. data/lib/hqmf-parser/converter/pass1/population_criteria_converter.rb +24 -8
  86. data/lib/hqmf-parser/converter/pass1/precondition_extractor.rb +15 -2
  87. data/lib/hqmf-parser/converter/pass2/comparison_converter.rb +1 -1
  88. data/lib/hqmf-parser/parser.rb +64 -41
  89. data/templates/cat1/_2.16.840.1.113883.10.20.22.4.85.cat1.erb +0 -1
  90. data/templates/cat1/_address.cat1.erb +9 -0
  91. data/templates/cat1/_author.cat1.erb +28 -0
  92. data/templates/cat1/_id.cat1.erb +1 -0
  93. data/templates/cat1/_organization.cat1.erb +8 -0
  94. data/templates/cat1/_patient_data.cat1.erb +0 -3
  95. data/templates/cat1/_telecom.cat1.erb +1 -0
  96. data/templates/cat1/show.cat1.erb +96 -58
  97. metadata +115 -66
  98. checksums.yaml +0 -7
@@ -5,16 +5,28 @@ module HQMF2
5
5
 
6
6
  include HQMF2::Utilities
7
7
 
8
- attr_reader :preconditions, :id, :hqmf_id, :title, :type
9
-
8
+ attr_reader :preconditions, :id, :hqmf_id, :title, :aggregator, :comments
9
+ #need to do this to allow for setting the type to OBSERV for
10
+ attr_accessor :type
10
11
  # Create a new population criteria from the supplied HQMF entry
11
12
  # @param [Nokogiri::XML::Element] the HQMF entry
12
13
  def initialize(entry, doc)
13
14
  @doc = doc
14
15
  @entry = entry
15
- @hqmf_id = attr_val('./*/cda:id/@extension')
16
+ @hqmf_id = attr_val('./*/cda:id/@extension') || attr_val('./*/cda:typeId/@extension')
16
17
  @title = attr_val('./*/cda:code/cda:displayName/@value')
17
18
  @type = attr_val('./*/cda:code/@code')
19
+ @aggregator = nil
20
+ @comments = @entry.xpath("./*/cda:text/cda:xml/cda:qdmUserComments/cda:item/text()", HQMF2::Document::NAMESPACES)
21
+ .map{ |v| v.content }
22
+ obs_test = attr_val('./cda:measureObservationDefinition/@classCode')
23
+ if !@title && obs_test.to_s == "OBS"
24
+ @title = attr_val('../cda:code/cda:displayName/@value')
25
+ @aggregator = attr_val('./cda:measureObservationDefinition/cda:methodCode/cda:item/@code')
26
+ end
27
+ if(!@hqmf_id) # The id extension is not required, if it's not provided use the code
28
+ @hqmf_id = @type
29
+ end
18
30
  @preconditions = @entry.xpath('./*/cda:precondition[not(@nullFlavor)]', HQMF2::Document::NAMESPACES).collect do |precondition|
19
31
  Precondition.new(precondition, @doc)
20
32
  end
@@ -34,7 +46,7 @@ module HQMF2
34
46
  # @return [String] conjunction code
35
47
  def conjunction_code
36
48
  case @type
37
- when HQMF::PopulationCriteria::IPP, HQMF::PopulationCriteria::DENOM, HQMF::PopulationCriteria::NUMER
49
+ when HQMF::PopulationCriteria::IPP, HQMF::PopulationCriteria::DENOM, HQMF::PopulationCriteria::NUMER,HQMF::PopulationCriteria::MSRPOPL
38
50
  HQMF::Precondition::ALL_TRUE
39
51
  when HQMF::PopulationCriteria::DENEXCEP, HQMF::PopulationCriteria::DENEX
40
52
  HQMF::Precondition::AT_LEAST_ONE_TRUE
@@ -45,9 +57,9 @@ module HQMF2
45
57
 
46
58
  def to_model
47
59
  mps = preconditions.collect {|p| p.to_model}
48
- HQMF::PopulationCriteria.new(id, hqmf_id, type, mps, title)
60
+ HQMF::PopulationCriteria.new(id, hqmf_id, type, mps, title, aggregator, comments)
49
61
  end
50
62
 
51
63
  end
52
64
 
53
- end
65
+ end
@@ -13,6 +13,9 @@ module HQMF2
13
13
  Precondition.new(precondition, @doc)
14
14
  end
15
15
  reference_def = @entry.at_xpath('./*/cda:id', HQMF2::Document::NAMESPACES)
16
+ if !reference_def
17
+ reference_def = @entry.at_xpath('./cda:join/cda:templateId/cda:item', HQMF2::Document::NAMESPACES)
18
+ end
16
19
  if reference_def
17
20
  @reference = Reference.new(reference_def)
18
21
  end
@@ -41,4 +44,4 @@ module HQMF2
41
44
  end
42
45
  end
43
46
 
44
- end
47
+ end
@@ -20,20 +20,16 @@ module HQMF2
20
20
 
21
21
  attr_reader :type, :unit, :value
22
22
 
23
- def initialize(entry, default_type='PQ')
23
+ def initialize(entry, default_type='PQ', force_inclusive=false)
24
24
  @entry = entry
25
25
  @type = attr_val('./@xsi:type') || default_type
26
26
  @unit = attr_val('./@unit')
27
27
  @value = attr_val('./@value')
28
+ @force_inclusive = force_inclusive
28
29
  end
29
30
 
30
31
  def inclusive?
31
- case attr_val('./@inclusive')
32
- when 'false'
33
- false
34
- else
35
- true
36
- end
32
+ attr_val("../@#{@entry.name}Closed") == 'true' || @force_inclusive
37
33
  end
38
34
 
39
35
  def derived?
@@ -67,9 +63,9 @@ module HQMF2
67
63
  @type = type
68
64
  @entry = entry
69
65
  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')
66
+ @low = optional_value("#{default_element_name}/cda:low", default_bounds_type)
67
+ @high = optional_value("#{default_element_name}/cda:high", default_bounds_type)
68
+ @width = optional_value("#{default_element_name}/cda:width", 'PQ')
73
69
  end
74
70
  end
75
71
 
@@ -81,7 +77,11 @@ module HQMF2
81
77
  lm = low ? low.to_model : nil
82
78
  hm = high ? high.to_model : nil
83
79
  wm = width ? width.to_model : nil
84
- HQMF::Range.new(type, lm, hm, wm)
80
+ model_type = type
81
+ if @entry.at_xpath('./cda:uncertainRange', HQMF2::Document::NAMESPACES)
82
+ model_type = 'IVL_PQ'
83
+ end
84
+ HQMF::Range.new(model_type, lm, hm, wm)
85
85
  end
86
86
 
87
87
  private
@@ -94,6 +94,17 @@ module HQMF2
94
94
  nil
95
95
  end
96
96
  end
97
+
98
+ def default_element_name
99
+ case type
100
+ when 'IVL_PQ'
101
+ '.'
102
+ when 'IVL_TS'
103
+ 'cda:phase'
104
+ else
105
+ 'cda:uncertainRange'
106
+ end
107
+ end
97
108
 
98
109
  def default_bounds_type
99
110
  case type
@@ -141,7 +152,7 @@ module HQMF2
141
152
  end
142
153
 
143
154
  def title
144
- attr_val('./@displayName')
155
+ attr_val('./*/@value')
145
156
  end
146
157
 
147
158
  def value
@@ -171,8 +182,18 @@ module HQMF2
171
182
  @entry = entry
172
183
  @type = attr_val('./cda:subsetCode/@code')
173
184
  value_def = @entry.at_xpath('./*/cda:repeatNumber', HQMF2::Document::NAMESPACES)
185
+ if !value_def
186
+ value_def = @entry.at_xpath('./*/cda:value', HQMF2::Document::NAMESPACES)
187
+ end
174
188
  if value_def
175
- @value = HQMF2::Range.new(value_def, 'IVL_INT')
189
+ value_type = value_def.at_xpath('./@xsi:type', HQMF2::Document::NAMESPACES)
190
+ if String.try_convert(value_type) == "ANY"
191
+ @value = HQMF2::AnyValue.new()
192
+ end
193
+ end
194
+
195
+ if value_def && !@value
196
+ @value = HQMF2::Range.new(value_def, 'IVL_PQ')
176
197
  end
177
198
  end
178
199
 
@@ -193,7 +214,7 @@ module HQMF2
193
214
  @reference = Reference.new(@entry.at_xpath('./*/cda:id', HQMF2::Document::NAMESPACES))
194
215
  range_def = @entry.at_xpath('./cda:pauseQuantity', HQMF2::Document::NAMESPACES)
195
216
  if range_def
196
- @range = HQMF2::Range.new(range_def, 'IVL_PQ')
217
+ @range = HQMF2::Range.new(range_def, 'PQ')
197
218
  end
198
219
  end
199
220
 
@@ -220,4 +241,4 @@ module HQMF2
220
241
  end
221
242
  end
222
243
 
223
- end
244
+ end
@@ -9,9 +9,9 @@ module HQMF
9
9
  title = json[:title]
10
10
  description = json[:description]
11
11
 
12
+ # TODO: Investigate why we never use json[:attributes]
12
13
  metadata = json[:metadata]
13
14
  metadata.keys.each {|key| metadata[key.to_s] = metadata[key]; metadata.delete(key.to_sym)}
14
-
15
15
  id = metadata["NQF_ID_NUMBER"][:value] if metadata["NQF_ID_NUMBER"]
16
16
  emeasure_id = metadata['EMEASURE_IDENTIFIER'][:value] if metadata['EMEASURE_IDENTIFIER']
17
17
  attributes = parse_attributes(metadata)
@@ -45,73 +45,21 @@ module HQMF
45
45
 
46
46
  doc = HQMF::Document.new(id, hqmf_id, hqmf_set_id, hqmf_version_number, cms_id, title, description, population_criteria, data_criteria, source_data_criteria, attributes, measure_period, populations)
47
47
 
48
- backfill_patient_characteristics_with_codes(doc, codes)
49
-
50
- HQMF::DocumentConverter.validate(doc, codes)
48
+ HQMF::DocumentConverter.validate(doc, codes) if codes
51
49
 
52
50
  doc
53
51
 
54
52
  end
55
53
 
56
54
  private
57
-
55
+
58
56
  def self.parse_attributes(metadata)
59
57
  attributes = []
60
58
  metadata.keys.each do |key|
61
- attribute_hash = metadata[key]
62
- code = attribute_hash[:code]
63
- value = attribute_hash[:value]
64
- unit = attribute_hash[:unit]
65
- name = attribute_hash[:name]
66
- attributes << HQMF::Attribute.new(key,code,value,unit,name)
59
+ attributes << HQMF::Attribute.from_json(metadata[key])
67
60
  end
68
61
  attributes
69
62
  end
70
-
71
-
72
- # patient characteristics data criteria such as GENDER require looking at the codes to determine if the
73
- # measure is interested in Males or Females. This process is awkward, and thus is done as a separate
74
- # step after the document has been converted.
75
- def self.backfill_patient_characteristics_with_codes(doc, codes)
76
-
77
- [].concat(doc.all_data_criteria).concat(doc.source_data_criteria).each do |data_criteria|
78
- if (data_criteria.type == :characteristic and !data_criteria.property.nil?)
79
- if (codes)
80
- value_set = codes[data_criteria.code_list_id]
81
- puts "\tno value set for unknown patient characteristic: #{data_criteria.id}" unless value_set
82
- else
83
- puts "\tno code set to back fill: #{data_criteria.title}"
84
- next
85
- end
86
-
87
- if (data_criteria.property == :gender)
88
- key = value_set.keys[0]
89
- data_criteria.value = HQMF::Coded.new('CD','Administrative Sex',value_set[key].first)
90
- else
91
- data_criteria.inline_code_list = value_set
92
- end
93
-
94
- elsif (data_criteria.type == :characteristic)
95
- if (codes)
96
- value_set = codes[data_criteria.code_list_id]
97
- if (value_set)
98
- # this is looking for a birthdate characteristic that is set as a generic characteristic but points to a loinc code set
99
- if (value_set['LOINC'] and value_set['LOINC'].first == '21112-8')
100
- data_criteria.definition = 'patient_characteristic_birthdate'
101
- end
102
- # this is looking for a gender characteristic that is set as a generic characteristic
103
- gender_key = (value_set.keys.select {|set| set == 'Administrative Sex' || set == 'AdministrativeSex'}).first
104
- if (gender_key and ['M','F'].include? value_set[gender_key].first)
105
- data_criteria.definition = 'patient_characteristic_gender'
106
- data_criteria.value = HQMF::Coded.new('CD','Gender',value_set[gender_key].first)
107
- end
108
- end
109
- end
110
-
111
- end
112
- end
113
- end
114
-
115
63
 
116
64
  def self.parse_measure_period(json)
117
65
 
@@ -29,6 +29,8 @@ module HQMF
29
29
  observs = @population_criteria_by_id.select {|key, value| value.type == HQMF::PopulationCriteria::OBSERV}
30
30
  excls = @population_criteria_by_id.select {|key, value| value.type == HQMF::PopulationCriteria::DENEX}
31
31
  denexcs = @population_criteria_by_id.select {|key, value| value.type == HQMF::PopulationCriteria::DENEXCEP}
32
+
33
+ stratifications = @population_criteria_by_id.values.select {|value| value.type == HQMF::PopulationCriteria::STRAT}
32
34
 
33
35
  if (ipps.size<=1 and denoms.size<=1 and nums.size<=1 and excls.size<=1 and denexcs.size<=1 and msrpopls.size<=1 and observs.size<=1 )
34
36
  sub_measure = {}
@@ -70,22 +72,38 @@ module HQMF
70
72
  reference = @population_criteria_by_id[reference_id] if reference_id
71
73
  if (reference)
72
74
  criteria = @population_criteria_by_key[sub[reference.type]]
73
- value['stratification'] = criteria.stratification_id if criteria.stratification_id
74
- value = nil if (sub[reference.type] != reference.id and criteria.stratification_id.nil?)
75
+ value = nil if (sub[reference.type] != reference.id)
75
76
  end
76
77
  end
77
78
  end
78
79
  keep << value if (value)
79
80
  end
80
81
 
81
- keep.each_with_index do |sub, i|
82
+ @sub_measures = keep
83
+
84
+ end
85
+
86
+ # add stratifications if we have them
87
+ if (stratifications.size > 0)
88
+ strat_subs = []
89
+ @sub_measures.each do |sub|
90
+ stratifications.each do |stratification|
91
+ new_sub = sub.dup
92
+ new_sub[HQMF::PopulationCriteria::STRAT] = stratification.id
93
+ new_sub['stratification'] = stratification.hqmf_id
94
+ strat_subs << new_sub
95
+ end
96
+ end
97
+ @sub_measures.concat strat_subs
98
+ end
99
+
100
+ if (@sub_measures.length > 1)
101
+ @sub_measures.each_with_index do |sub, i|
82
102
  sub['title'] = "Population #{i+1}"
83
103
  sub['id'] = "Population#{i+1}"
84
104
  end
85
-
86
- @sub_measures = keep
87
-
88
105
  end
106
+
89
107
  end
90
108
 
91
109
  # source are things like exceptions or exclusions, target are IPP, or denom
@@ -151,8 +169,6 @@ module HQMF
151
169
  title = population_criteria[:title]
152
170
 
153
171
  criteria = HQMF::Converter::SimplePopulationCriteria.new(key, hqmf_id, type, preconditions, title)
154
- # mark the 2.0 simple population criteria as a stratification... this allows us to create the cartesian product for this in the populations
155
- criteria.stratification_id = population_criteria[:stratification_id]
156
172
 
157
173
  @population_criteria_by_id[id] = criteria
158
174
  @population_reference[key] = reference
@@ -47,15 +47,19 @@ module HQMF
47
47
  # if we reference the measurement period, then we want to check if the reference is to the start or end of the measurement period
48
48
  # if we SBS of the END of the measurement period, we want to convert that to SBE of the measurement period
49
49
  if target_id == HQMF::Document::MEASURE_PERIOD_ID
50
- references_start = {'SBS'=>'SBE','SAS'=>'SAE','EBS'=>'EBE','EAS'=>'EAE'}
51
- references_end = {'EBE'=>'EBS','EAE'=>'EAS','SBE'=>'SBS','SAE'=>'SAS'}
50
+ references_start = {'SBS'=>'SBE','SAS'=>'SAE','EBS'=>'EBE','EAS'=>'EAE','SCW'=>'SCWE'}
51
+ references_end = {'EBE'=>'EBS','EAE'=>'EAS','SBE'=>'SBS','SAE'=>'SAS','ECW'=>'ECWS'}
52
52
  if data_criteria_converter.measure_period_v1_keys[:measure_start] == restriction[:target_id] and references_end[type]
53
53
  # before or after the END of the measurement period START. Convert to before or after the START of the measurement period.
54
54
  # SAE of MPS => SAS of MP
55
+ # ends concurrent with measurement period START. Convert to concurrent with START of measurement period.
56
+ # ECW of MPS => ECWS
55
57
  type = references_end[type]
56
58
  elsif data_criteria_converter.measure_period_v1_keys[:measure_end] == restriction[:target_id] and references_start[type]
57
59
  # before or after the START of the measurement period END. Convert to before or after the END of the measurement period.
58
60
  # SBS of MPE => SBE of MP
61
+ # starts concurrent with measurement period END. Convert to concurrent with END of measurement period.
62
+ # SCW of MPE => SCWE
59
63
  type = references_start[type]
60
64
  end
61
65
  end
@@ -132,6 +136,15 @@ module HQMF
132
136
  container = HQMF::Converter::SimpleRestriction.new(operator, nil, [comparison_precondition])
133
137
  else
134
138
  container = HQMF::Converter::SimpleRestriction.new(operator, target_id)
139
+ # handle transitive restrictions... this is where we are adding a field to a target of a timing restriction
140
+ if (restrictions && !restrictions.empty? && children.nil?)
141
+ children = []
142
+ restrictions.each do |child|
143
+ comparison_precondition = HQMF::Converter::SimplePrecondition.new(nil,[child],HQMF::Reference.new(target_id),nil, false)
144
+ comparison_precondition.klass = HQMF::Converter::SimplePrecondition::COMPARISON
145
+ children << comparison_precondition
146
+ end
147
+ end
135
148
  container.preconditions = children
136
149
  end
137
150
 
@@ -62,7 +62,7 @@ module HQMF
62
62
  restriction.converted=true
63
63
  when 'SUBJ'
64
64
  new_data_criteria.field_values ||= {}
65
- new_data_criteria.field_values[operator.field_value_key] = operator.value
65
+ new_data_criteria.field_values[operator.field_value_key] = operator.value || HQMF::AnyValue.new
66
66
  restriction.converted=true
67
67
  else
68
68
  puts "\tOperator is unknown: #{operator.type}"
@@ -4,49 +4,72 @@ module HQMF
4
4
  HQMF_VERSION_1 = "1.0"
5
5
  HQMF_VERSION_2 = "2.0"
6
6
 
7
- def self.parse(hqmf_contents, version, codes = nil)
8
-
9
- HQMF::Counter.instance.reset()
10
- case version
11
- when HQMF_VERSION_1
12
- puts("\tCodes not passed in, cannot backfill properties like gender") unless codes
13
- HQMF::DocumentConverter.convert(HQMF1::Document.new(hqmf_contents).to_json, codes)
14
- when HQMF_VERSION_2
15
- HQMF2::Document.new(hqmf_contents).to_model
16
- else
17
- raise "Unsupported HQMF version specified: #{version}"
7
+ class V2Parser
8
+ def initialize
18
9
  end
10
+
11
+ def parse(xml_contents, codes=nil)
12
+ HQMF::Counter.instance.reset()
13
+ HQMF2::Document.new(xml_contents).to_model
14
+ end
15
+
16
+ def parse_fileds(xml_contents)
17
+ result = {}
18
+ doc = HQMF2::Document.parse(xml_contents)
19
+ type = doc.at_xpath('/cda:QualityMeasureDocument/cda:code/@code').value
20
+ if type == '57024-2'
21
+ id = doc.at_xpath('cda:QualityMeasureDocument/cda:id/@extension', HQMF2::Document::NAMESPACES).value.upcase
22
+ set_id = doc.at_xpath('cda:QualityMeasureDocument/cda:setId/@extension').value.upcase
23
+ version_number = doc.at_xpath('cda:QualityMeasureDocument/cda:versionNumber/@value').value.to_i
24
+ title = doc.at_xpath('cda:QualityMeasureDocument/cda:title/@value').inner_text
25
+ description = doc.at_xpath('cda:QualityMeasureDocument/cda:text/@value').inner_text
26
+ result= {'id' => id, 'set_id' => set_id, 'version' => version_number, 'title' => title, 'description' => description}
27
+ end
28
+ result
29
+ end
30
+
31
+ def version
32
+ HQMF_VERSION_2
33
+ end
34
+
35
+ def self.valid?(xml_contents)
36
+ doc = HQMF2::Document.parse(xml_contents)
37
+ !doc.at_xpath("/cda:QualityMeasureDocument/cda:typeId[@root='2.16.840.1.113883.1.3' and @extension='POQM_MT000001UV03']").nil?
38
+ end
39
+
19
40
  end
20
-
21
- def self.parse_fields(hqmf_contents, version)
22
- result = {}
23
- case version
24
- when HQMF_VERSION_1
25
- doc = HQMF1::Document.parse(hqmf_contents)
26
- type = doc.at_xpath('//cda:code/@code').value
27
- if type == '57024-2'
28
- id = doc.at_xpath('//cda:id/@root').value.upcase
29
- set_id = doc.at_xpath('//cda:setId/@root').value.upcase
30
- version_number = doc.at_xpath('//cda:versionNumber/@value').value.to_i
31
- title = doc.at_xpath('cda:QualityMeasureDocument/cda:title').inner_text
32
- description = doc.at_xpath('cda:QualityMeasureDocument/cda:text').inner_text
33
- result = {'id' => id, 'set_id' => set_id, 'version' => version_number, 'title' => title, 'description' => description}
34
- end
35
- when HQMF_VERSION_2
36
- doc = HQMF2::Document.parse(hqmf_contents)
37
- type = doc.at_xpath('cda:QualityMeasureDocument/cda:code/@code').value
38
- if type == '57024-2'
39
- id = doc.at_xpath('cda:QualityMeasureDocument/cda:id/@extension', HQMF2::Document::NAMESPACES).value.upcase
40
- set_id = doc.at_xpath('cda:QualityMeasureDocument/cda:setId/@extension').value.upcase
41
- version_number = doc.at_xpath('cda:QualityMeasureDocument/cda:versionNumber/@value').value.to_i
42
- title = doc.at_xpath('cda:QualityMeasureDocument/cda:title/@value').inner_text
43
- description = doc.at_xpath('cda:QualityMeasureDocument/cda:text/@value').inner_text
44
- result = {'id' => id, 'set_id' => set_id, 'version' => version_number, 'title' => title, 'description' => description}
45
- end
46
- else
47
- raise "Unsupported HQMF version specified: #{version}"
48
- end
49
- result
41
+
42
+ class V1Parser
43
+
44
+ def parse(xml_contents, codes=nil)
45
+ HQMF::Counter.instance.reset()
46
+ HQMF::DocumentConverter.convert(HQMF1::Document.new(xml_contents).to_json, codes)
47
+ end
48
+
49
+ def version
50
+ HQMF_VERSION_1
51
+ end
52
+
53
+ def parse_fields(xml_contents)
54
+ doc = HQMF1::Document.parse(xml_contents)
55
+ type = doc.at_xpath('//cda:code/@code').value
56
+ result = {}
57
+ if type == '57024-2'
58
+ id = doc.at_xpath('//cda:id/@root').value.upcase
59
+ set_id = doc.at_xpath('//cda:setId/@root').value.upcase
60
+ version_number = doc.at_xpath('//cda:versionNumber/@value').value.to_i
61
+ title = doc.at_xpath('cda:QualityMeasureDocument/cda:title').inner_text
62
+ description = doc.at_xpath('cda:QualityMeasureDocument/cda:text').inner_text
63
+ result = {'id' => id, 'set_id' => set_id, 'version' => version_number, 'title' => title, 'description' => description}
64
+ end
65
+ result
66
+ end
67
+
68
+ def self.valid?(xml_contents)
69
+ doc = HQMF1::Document.parse(xml_contents)
70
+ !doc.at_xpath("/cda:QualityMeasureDocument/cda:typeId[@root='2.16.840.1.113883.1.3' and @extension='POQM_HD000001']").nil?
71
+ end
72
+
50
73
  end
51
74
 
52
75
  end