fhir_models 4.2.2 → 4.3.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.
@@ -25,13 +25,14 @@ module FHIR
25
25
  # Inspired by active-support `blank` but in our case false isn't blank ...
26
26
  # https://github.com/rails/rails/blob/v5.2.3/activesupport/lib/active_support/core_ext/object/blank.rb
27
27
  blank = ->(obj) { obj.respond_to?(:empty?) ? obj.empty? : obj.nil? }
28
- if thing.is_a?(Array)
28
+ case thing
29
+ when Array
29
30
  return nil if thing.empty?
30
31
 
31
32
  thing
32
33
  .map { |i| prune(i) }
33
34
  .reject(&blank)
34
- elsif thing.is_a?(Hash)
35
+ when Hash
35
36
  return {} if thing.empty?
36
37
 
37
38
  new_thing = {}
@@ -59,11 +60,12 @@ module FHIR
59
60
  key = key.to_s
60
61
  meta = self.class::METADATA[key]
61
62
  next if meta.nil?
63
+
62
64
  local_name = key
63
65
  local_name = meta['local_name'] if meta['local_name']
64
66
  begin
65
67
  instance_variable_set("@#{local_name}", value)
66
- rescue
68
+ rescue StandardError
67
69
  # TODO: this appears to be a dead code branch
68
70
  nil
69
71
  end
@@ -102,7 +104,7 @@ module FHIR
102
104
  if child['resourceType'] && !klass::METADATA['resourceType']
103
105
  klass = begin
104
106
  FHIR.const_get(child['resourceType'])
105
- rescue => _exception
107
+ rescue StandardError => _e
106
108
  # TODO: this appears to be a dead code branch
107
109
  # TODO: should this log / re-raise the exception if encountered instead of silently swallowing it?
108
110
  FHIR.logger.error("Unable to identify embedded class #{child['resourceType']}\n#{exception.backtrace}")
@@ -111,9 +113,9 @@ module FHIR
111
113
  end
112
114
  begin
113
115
  obj = klass.new(child)
114
- rescue => exception
116
+ rescue StandardError => e
115
117
  # TODO: should this re-raise the exception if encountered instead of silently swallowing it?
116
- FHIR.logger.error("Unable to inflate embedded class #{klass}\n#{exception.backtrace}")
118
+ FHIR.logger.error("Unable to inflate embedded class #{klass}\n#{e.backtrace}")
117
119
  end
118
120
  obj
119
121
  end
@@ -125,7 +127,7 @@ module FHIR
125
127
  if meta['type'] == 'boolean'
126
128
  rval = value.strip == 'true'
127
129
  elsif FHIR::PRIMITIVES.include?(meta['type'])
128
- if %w[decimal integer positiveInt unsignedInt].include?(meta['type'])
130
+ if ['decimal', 'integer', 'positiveInt', 'unsignedInt'].include?(meta['type'])
129
131
  rval = BigDecimal(value.to_s)
130
132
  rval = rval.frac.zero? ? rval.to_i : rval.to_f
131
133
  end # primitive is number
@@ -17,7 +17,7 @@ module FHIR
17
17
  resource_type = hash['resourceType']
18
18
  klass = Module.const_get("FHIR::#{resource_type}")
19
19
  resource = klass.new(hash)
20
- rescue => e
20
+ rescue StandardError => e
21
21
  FHIR.logger.error("Failed to deserialize JSON:\n#{e.backtrace}")
22
22
  FHIR.logger.debug("JSON:\n#{json}")
23
23
  resource = nil
@@ -22,40 +22,39 @@ module FHIR
22
22
  to_hash.hash
23
23
  end
24
24
 
25
+ def respond_to_missing?(method_name, *)
26
+ (defined?(self.class::MULTIPLE_TYPES) && self.class::MULTIPLE_TYPES[method_name.to_s]) ||
27
+ (!@extension.nil? && !@extension.empty? && !find_extension(@extension, method_name).first.nil?) ||
28
+ (!@modifierExtension.nil? && !@modifierExtension.empty? && !find_extension(@modifierExtension, method_name).first.nil?) ||
29
+ super
30
+ end
31
+
25
32
  # allow two FHIR models to be compared for equality
26
33
  def ==(other)
27
34
  self.class == other.class && to_hash == other.to_hash
28
35
  end
29
36
  alias eql? ==
30
37
 
31
- def method_missing(method, *_args, &_block)
32
- if defined?(self.class::MULTIPLE_TYPES) && self.class::MULTIPLE_TYPES[method.to_s]
33
- self.class::MULTIPLE_TYPES[method.to_s].each do |type|
38
+ def method_missing(method_name, *_args, &_block)
39
+ if defined?(self.class::MULTIPLE_TYPES) && self.class::MULTIPLE_TYPES[method_name.to_s]
40
+ self.class::MULTIPLE_TYPES[method_name.to_s].each do |type|
34
41
  type[0] = type[0].upcase
35
- value = send("#{method}#{type}".to_sym)
42
+ value = send("#{method_name}#{type}".to_sym)
36
43
  return value unless value.nil?
37
44
  end
38
45
  return nil
39
46
  elsif !@extension.nil? && !@extension.empty?
40
- ext = @extension.select do |x|
41
- name = x.url.tr('-', '_').split('/').last
42
- anchor = name.split('#').last
43
- (method.to_s == name || method.to_s == anchor)
44
- end
45
- unless ext.first.nil?
46
- return ext.first.value.nil? ? ext.first : ext.first.value
47
+ desired_extension = find_extension(@extension, method_name)
48
+ unless desired_extension.first.nil?
49
+ return desired_extension.first.value.nil? ? desired_extension.first : desired_extension.first.value
47
50
  end
48
51
  elsif !@modifierExtension.nil? && !@modifierExtension.empty?
49
- ext = @modifierExtension.select do |x|
50
- name = x.url.tr('-', '_').split('/').last
51
- anchor = name.split('#').last
52
- (method.to_s == name || method.to_s == anchor)
53
- end
54
- unless ext.first.nil?
55
- return ext.first.value.nil? ? ext.first : ext.first.value
52
+ desired_extension = find_extension(@modifierExtension, method_name)
53
+ unless desired_extension.first.nil?
54
+ return desired_extension.first.value.nil? ? desired_extension.first : desired_extension.first.value
56
55
  end
57
56
  end
58
- raise NoMethodError.new("undefined method `#{method}' for #{self.class.name}", method)
57
+ raise NoMethodError.new("undefined method `#{method_name}' for #{self.class.name}", method_name)
59
58
  end
60
59
 
61
60
  def to_reference
@@ -141,14 +140,14 @@ module FHIR
141
140
  end # metadata.each
142
141
  # check multiple types
143
142
  multiple_types = begin
144
- self.class::MULTIPLE_TYPES
145
- rescue
146
- {}
147
- end
143
+ self.class::MULTIPLE_TYPES
144
+ rescue StandardError
145
+ {}
146
+ end
148
147
  multiple_types.each do |prefix, suffixes|
149
148
  present = []
150
149
  suffixes.each do |suffix|
151
- typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..-1]}"
150
+ typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..]}"
152
151
  # check which multiple data types are actually present, not just errors
153
152
  # actually, this might be allowed depending on cardinality
154
153
  value = instance_variable_get("@#{typename}")
@@ -157,8 +156,9 @@ module FHIR
157
156
  errors[prefix] = ["#{prefix}[x]: more than one type present."] if present.length > 1
158
157
  # remove errors for suffixes that are not present
159
158
  next unless present.length == 1
159
+
160
160
  suffixes.each do |suffix|
161
- typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..-1]}"
161
+ typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..]}"
162
162
  errors.delete(typename) unless present.include?(typename)
163
163
  end
164
164
  end
@@ -221,10 +221,12 @@ module FHIR
221
221
  # check binding
222
222
  next unless meta['binding']
223
223
  next unless meta['binding']['strength'] == 'required'
224
+
224
225
  the_codes = [v]
225
- if meta['type'] == 'Coding'
226
+ case meta['type']
227
+ when 'Coding'
226
228
  the_codes = [v.code]
227
- elsif meta['type'] == 'CodeableConcept'
229
+ when 'CodeableConcept'
228
230
  the_codes = v.coding.map(&:code).compact
229
231
  end
230
232
  has_valid_code = false
@@ -247,6 +249,7 @@ module FHIR
247
249
  def validate_reference_type(ref, meta, contained_here, errors)
248
250
  return unless ref.reference && meta['type_profiles']
249
251
  return if ref.reference.start_with?('urn:uuid:', 'urn:oid:')
252
+
250
253
  matches_one_profile = false
251
254
  meta['type_profiles'].each do |p|
252
255
  basetype = p.split('/').last
@@ -258,7 +261,7 @@ module FHIR
258
261
  matches_one_profile = true if meta['type_profiles'].include?('http://hl7.org/fhir/StructureDefinition/Resource')
259
262
  if !matches_one_profile && ref.reference.start_with?('#')
260
263
  # we need to look at the local contained resources
261
- r = contained_here.find { |x| x.id == ref.reference[1..-1] }
264
+ r = contained_here.find { |x| x.id == ref.reference[1..] }
262
265
  if !r.nil?
263
266
  meta['type_profiles'].each do |p|
264
267
  p = p.split('/').last
@@ -280,15 +283,15 @@ module FHIR
280
283
  def check_binding_uri(uri, value)
281
284
  valid = false
282
285
  # Strip off the |4.0.0 or |4.0.1 or |2014-03-26 or similar from the ends of URLs
283
- uri&.gsub!(/\|[A-Za-z0-9\.\-]*/, '')
286
+ uri&.gsub!(/\|[A-Za-z0-9.\-]*/, '')
284
287
  valueset = FHIR::Definitions.get_codes(uri)
285
288
 
286
- if uri == 'http://hl7.org/fhir/ValueSet/mimetypes' || uri == 'http://www.rfc-editor.org/bcp/bcp13.txt'
289
+ if ['http://hl7.org/fhir/ValueSet/mimetypes', 'http://www.rfc-editor.org/bcp/bcp13.txt'].include?(uri)
287
290
  matches = MIME::Types[value]
288
291
  json_or_xml = value.downcase.include?('xml') || value.downcase.include?('json')
289
292
  known_weird = ['text/cql', 'application/cql+text', 'application/hl7-v2'].include?(value)
290
293
  valid = json_or_xml || known_weird || (!matches.nil? && !matches.empty?)
291
- elsif uri == 'http://hl7.org/fhir/ValueSet/languages' || uri == 'http://tools.ietf.org/html/bcp47'
294
+ elsif ['http://hl7.org/fhir/ValueSet/languages', 'http://tools.ietf.org/html/bcp47'].include?(uri)
292
295
  has_region = !(value =~ /-/).nil?
293
296
  valid = !BCP47::Language.identify(value.downcase).nil? && (!has_region || !BCP47::Region.identify(value.upcase).nil?)
294
297
  elsif valueset.nil?
@@ -321,6 +324,14 @@ module FHIR
321
324
  self
322
325
  end
323
326
 
324
- private :validate_reference_type, :check_binding_uri, :validate_field
327
+ def find_extension(extension_source, method_name)
328
+ extension_source.select do |extension|
329
+ name = extension.url.tr('-', '_').split('/').last
330
+ anchor = name.split('#').last
331
+ (method_name.to_s == name || method_name.to_s == anchor)
332
+ end
333
+ end
334
+
335
+ private :validate_reference_type, :check_binding_uri, :validate_field, :find_extension
325
336
  end
326
337
  end
@@ -11,16 +11,17 @@ module FHIR
11
11
 
12
12
  # Remove entries that do not interest us: CompartmentDefinitions, OperationDefinitions, Conformance statements
13
13
  hash['entry'].select! do |entry|
14
- %w[StructureDefinition ValueSet CodeSystem SearchParameter].include? entry['resource']['resourceType']
14
+ ['StructureDefinition', 'ValueSet', 'CodeSystem', 'SearchParameter'].include? entry['resource']['resourceType']
15
15
  end
16
16
 
17
17
  # Remove unnecessary elements from the hash
18
18
  hash['entry'].each do |entry|
19
19
  next unless entry['resource']
20
- pre_process_structuredefinition(entry['resource']) if 'StructureDefinition' == entry['resource']['resourceType']
21
- pre_process_valueset(entry['resource']) if 'ValueSet' == entry['resource']['resourceType']
22
- pre_process_codesystem(entry['resource']) if 'CodeSystem' == entry['resource']['resourceType']
23
- pre_process_searchparam(entry['resource']) if 'SearchParameter' == entry['resource']['resourceType']
20
+
21
+ pre_process_structuredefinition(entry['resource']) if entry['resource']['resourceType'] == 'StructureDefinition'
22
+ pre_process_valueset(entry['resource']) if entry['resource']['resourceType'] == 'ValueSet'
23
+ pre_process_codesystem(entry['resource']) if entry['resource']['resourceType'] == 'CodeSystem'
24
+ pre_process_searchparam(entry['resource']) if entry['resource']['resourceType'] == 'SearchParameter'
24
25
  remove_fhir_comments(entry['resource'])
25
26
  end
26
27
 
@@ -34,26 +35,30 @@ module FHIR
34
35
 
35
36
  def self.pre_process_structuredefinition(hash)
36
37
  # Remove large HTML narratives and unused content
37
- %w[text publisher contact description requirements mapping].each { |key| hash.delete(key) }
38
+ ['text', 'publisher', 'contact', 'description', 'requirements', 'mapping'].each { |key| hash.delete(key) }
38
39
 
39
40
  # Remove unused descriptions within the snapshot and differential elements
40
- %w[snapshot differential].each do |key|
41
+ ['snapshot', 'differential'].each do |key|
41
42
  next unless hash[key]
43
+
42
44
  hash[key]['element'].each do |element|
43
- %w[short definition comments requirements alias mapping].each { |subkey| element.delete(subkey) }
45
+ ['short', 'definition', 'comments', 'requirements', 'alias', 'mapping'].each { |subkey| element.delete(subkey) }
44
46
  end
45
47
  end
46
48
  end
47
49
 
48
50
  def self.pre_process_valueset(hash)
49
51
  # Remove large HTML narratives and unused content
50
- %w[meta text publisher contact description requirements].each { |key| hash.delete(key) }
52
+ ['meta', 'text', 'publisher', 'contact', 'description', 'requirements'].each { |key| hash.delete(key) }
51
53
 
52
54
  return unless hash['compose']
53
- %w[include exclude].each do |key|
55
+
56
+ ['include', 'exclude'].each do |key|
54
57
  next unless hash['compose'][key]
58
+
55
59
  hash['compose'][key].each do |element|
56
60
  next unless element['concept']
61
+
57
62
  element['concept'].each do |concept|
58
63
  concept.delete('designation')
59
64
  end
@@ -63,16 +68,18 @@ module FHIR
63
68
 
64
69
  def self.pre_process_codesystem(hash)
65
70
  # Remove large HTML narratives and unused content
66
- %w[meta text publisher contact description requirements].each { |key| hash.delete(key) }
71
+ ['meta', 'text', 'publisher', 'contact', 'description', 'requirements'].each { |key| hash.delete(key) }
67
72
  return unless hash['concept']
73
+
68
74
  hash['concept'].each do |concept|
69
75
  pre_process_codesystem_concept(concept)
70
76
  end
71
77
  end
72
78
 
73
79
  def self.pre_process_codesystem_concept(hash)
74
- %w[extension definition designation].each { |key| hash.delete(key) }
80
+ ['extension', 'definition', 'designation'].each { |key| hash.delete(key) }
75
81
  return unless hash['concept']
82
+
76
83
  hash['concept'].each do |concept|
77
84
  pre_process_codesystem_concept(concept)
78
85
  end
@@ -80,15 +87,16 @@ module FHIR
80
87
 
81
88
  def self.pre_process_searchparam(hash)
82
89
  # Remove large HTML narratives and unused content
83
- %w[id url name date publisher contact description xpathUsage].each { |key| hash.delete(key) }
90
+ ['id', 'url', 'name', 'date', 'publisher', 'contact', 'description', 'xpathUsage'].each { |key| hash.delete(key) }
84
91
  end
85
92
 
86
93
  def self.remove_fhir_comments(hash)
87
94
  hash.delete('fhir_comments')
88
95
  hash.each do |_key, value|
89
- if value.is_a?(Hash)
96
+ case value
97
+ when Hash
90
98
  remove_fhir_comments(value)
91
- elsif value.is_a?(Array)
99
+ when Array
92
100
  value.each do |v|
93
101
  remove_fhir_comments(v) if v.is_a?(Hash)
94
102
  end
@@ -126,7 +134,7 @@ module FHIR
126
134
  hash = JSON.parse(json)
127
135
 
128
136
  # Remove narratives
129
- %w[text].each { |key| hash.delete(key) }
137
+ ['text'].each { |key| hash.delete(key) }
130
138
 
131
139
  # Output the post processed file
132
140
  f = File.open(filename, 'w:UTF-8')
@@ -156,7 +164,7 @@ module FHIR
156
164
  # Remove the weird parantheses on xml example filenames
157
165
  # we do this so they match the names of the json examples
158
166
  if filename.include?('(') && filename.include?(')')
159
- rename = filename.gsub(/\([A-Za-z0-9\-\.]*\)/, '')
167
+ rename = filename.gsub(/\([A-Za-z0-9\-.]*\)/, '')
160
168
  File.rename(filename, rename)
161
169
  filename = rename
162
170
  end
@@ -24,7 +24,7 @@ module FHIR
24
24
  # if hash contains resourceType
25
25
  # create a child node with the name==resourceType
26
26
  # fill that, and place the child under the above `node`
27
- if hash['resourceType'] && hash['resourceType'].is_a?(String) && name != 'instance'
27
+ if hash['resourceType'].is_a?(String) && name != 'instance'
28
28
  child_name = hash['resourceType']
29
29
  hash.delete('resourceType')
30
30
  child = hash_to_xml_node(child_name, hash, doc)
@@ -33,11 +33,13 @@ module FHIR
33
33
  end
34
34
 
35
35
  hash.each do |key, value|
36
- next if %w[extension modifierExtension].include?(name) && key == 'url'
36
+ next if ['extension', 'modifierExtension'].include?(name) && key == 'url'
37
37
  next if key == 'id' && !FHIR::RESOURCES.include?(name)
38
- if value.is_a?(Hash)
38
+
39
+ case value
40
+ when Hash
39
41
  node.add_child(hash_to_xml_node(key, value, doc))
40
- elsif value.is_a?(Array)
42
+ when Array
41
43
  value.each do |v|
42
44
  if v.is_a?(Hash)
43
45
  node.add_child(hash_to_xml_node(key, v, doc))
@@ -62,7 +64,7 @@ module FHIR
62
64
  node.add_child(child)
63
65
  end
64
66
  end
65
- node.set_attribute('url', hash['url']) if %w[extension modifierExtension].include?(name)
67
+ node.set_attribute('url', hash['url']) if ['extension', 'modifierExtension'].include?(name)
66
68
  node.set_attribute('id', hash['id']) if hash['id'] && !FHIR::RESOURCES.include?(name)
67
69
  node
68
70
  end
@@ -78,7 +80,7 @@ module FHIR
78
80
  resource_type = doc.root.name
79
81
  klass = Module.const_get("FHIR::#{resource_type}")
80
82
  resource = klass.new(hash)
81
- rescue => e
83
+ rescue StandardError => e
82
84
  FHIR.logger.error("Failed to deserialize XML:\n#{e.backtrace}")
83
85
  FHIR.logger.debug("XML:\n#{xml}")
84
86
  resource = nil
@@ -108,7 +110,7 @@ module FHIR
108
110
  end
109
111
  end
110
112
  end
111
- hash['url'] = node.get_attribute('url') if %w[extension modifierExtension].include?(node.name)
113
+ hash['url'] = node.get_attribute('url') if ['extension', 'modifierExtension'].include?(node.name)
112
114
  hash['id'] = node.get_attribute('id') if node.get_attribute('id') # Testscript fixture ids (applies to any BackboneElement)
113
115
  hash['resourceType'] = node.name if FHIR::RESOURCES.include?(node.name)
114
116
 
@@ -10,6 +10,7 @@ module FHIR
10
10
  end
11
11
  end
12
12
  return unless methods.include? new_method
13
+
13
14
  (class << self; self; end).instance_eval do
14
15
  define_method(old_method) do |*args, &block|
15
16
  message = "DEPRECATED: `#{old_method}` has been deprecated. Use `#{new_method}` instead. Called from #{caller.first}"
@@ -1,5 +1,6 @@
1
1
  require 'nokogiri'
2
2
  require 'logger'
3
+ require 'uri'
3
4
 
4
5
  module FHIR
5
6
  def self.logger
@@ -11,7 +12,7 @@ module FHIR
11
12
  end
12
13
 
13
14
  def self.default_logger
14
- @default_logger ||= Logger.new(ENV['FHIR_LOGGER'] || STDOUT)
15
+ @default_logger ||= Logger.new(ENV['FHIR_LOGGER'] || $stdout)
15
16
  end
16
17
 
17
18
  def self.from_contents(contents)
@@ -38,7 +39,7 @@ module FHIR
38
39
  when 'uri'
39
40
  begin
40
41
  !URI.parse(value).nil?
41
- rescue
42
+ rescue StandardError
42
43
  false
43
44
  end
44
45
  when 'base64binary'
@@ -47,7 +48,7 @@ module FHIR
47
48
  # whitespace is not significant so we strip it out before doing the regex so that we can be sure that
48
49
  # the number of characters is a multiple of 4.
49
50
  # https://tools.ietf.org/html/rfc4648
50
- !(value.to_s.gsub(/\s/, '') =~ %r{\A(|[0-9a-zA-Z\+=/]{4}+)\Z}).nil?
51
+ !(value.to_s.gsub(/\s/, '') =~ %r{\A(|[0-9a-zA-Z+=/]{4}+)\Z}).nil?
51
52
  when 'instant'
52
53
  formatted_value = value.respond_to?(:xmlschema) ? value.xmlschema : value.to_s
53
54
  !(formatted_value =~ /\A([0-9]{4}(-(0[1-9]|1[0-2])(-(0[0-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))))))\Z/).nil?
@@ -62,16 +63,16 @@ module FHIR
62
63
  when 'time'
63
64
  !(value.to_s =~ /\A(([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?)\Z/).nil?
64
65
  when 'code'
65
- !(value.to_s =~ /\A[^\s]+([\s]?[^\s]+)*\Z/).nil?
66
+ !(value.to_s =~ /\A[^\s]+(\s?[^\s]+)*\Z/).nil?
66
67
  when 'oid'
67
68
  !(value.to_s =~ /\Aurn:oid:[0-2](\.[1-9]\d*)+\Z/).nil?
68
69
  when 'id'
69
- !(value.to_s =~ /\A[A-Za-z0-9\-\.]{1,64}\Z/).nil?
70
+ !(value.to_s =~ /\A[A-Za-z0-9\-.]{1,64}\Z/).nil?
70
71
  when 'xhtml'
71
72
  fragment = Nokogiri::HTML::DocumentFragment.parse(value)
72
73
  value.is_a?(String) && fragment.errors.size.zero?
73
74
  when 'unsignedint'
74
- !(value.to_s =~ /\A([0]|([1-9][0-9]*))\Z/).nil?
75
+ !(value.to_s =~ /\A(0|([1-9][0-9]*))\Z/).nil?
75
76
  when 'positiveint'
76
77
  !(value.to_s =~ /\A+?[1-9][0-9]*\Z/).nil?
77
78
  else
@@ -25,6 +25,7 @@ module FHIR
25
25
  def keep_children(whitelist = [])
26
26
  @marked_for_keeping = true if whitelist.include?(path)
27
27
  return unless @children
28
+
28
29
  @children.each do |child|
29
30
  child.keep_children(whitelist)
30
31
  end
@@ -32,14 +33,16 @@ module FHIR
32
33
 
33
34
  def sweep_children
34
35
  return unless @children
36
+
35
37
  @children.each(&:sweep_children)
36
- @children = @children.keep_if(&:marked_for_keeping)
38
+ @children.keep_if(&:marked_for_keeping)
37
39
  @marked_for_keeping = !@children.empty? || @marked_for_keeping
38
40
  end
39
41
 
40
42
  def print_children(spaces = 0)
41
43
  puts "#{' ' * spaces}+#{local_name || path}"
42
44
  return nil unless @children
45
+
43
46
  @children.each do |child|
44
47
  child.print_children(spaces + 2)
45
48
  end
@@ -59,7 +59,7 @@ module FHIR
59
59
  if json.is_a? String
60
60
  begin
61
61
  json = JSON.parse(json)
62
- rescue => e
62
+ rescue StandardError => e
63
63
  @errors << "Failed to parse JSON: #{e.message} %n #{h} %n #{e.backtrace.join("\n")}"
64
64
  return false
65
65
  end
@@ -99,13 +99,15 @@ module FHIR
99
99
  def get_json_nodes(json, path)
100
100
  results = []
101
101
  return [json] if path.nil?
102
+
102
103
  steps = path.split('.')
103
104
  steps.each.with_index do |step, index|
104
- if json.is_a? Hash
105
+ case json
106
+ when Hash
105
107
  json = json[step]
106
- elsif json.is_a? Array
108
+ when Array
107
109
  json.each do |e|
108
- results << get_json_nodes(e, steps[index..-1].join('.'))
110
+ results << get_json_nodes(e, steps[index..].join('.'))
109
111
  end
110
112
  return results.flatten!
111
113
  else
@@ -125,7 +127,7 @@ module FHIR
125
127
 
126
128
  def verify_element(element, json)
127
129
  path = element.local_name || element.path
128
- path = path[(@hierarchy.path.size + 1)..-1] if path.start_with? @hierarchy.path
130
+ path = path[(@hierarchy.path.size + 1)..] if path.start_with? @hierarchy.path
129
131
 
130
132
  if element.type && !element.type.empty?
131
133
  data_type_found = element.type.first.code
@@ -157,10 +159,11 @@ module FHIR
157
159
  verify_cardinality(element, nodes)
158
160
 
159
161
  return if nodes.empty?
162
+
160
163
  # Check the datatype for each node, only if the element has one declared, and it isn't the root element
161
164
  if !element.type.empty? && element.path != id
162
165
  # element.type not being empty implies data_type_found != nil, for valid profiles
163
- codeable_concept_pattern = element.pattern && element.pattern.is_a?(FHIR::CodeableConcept)
166
+ codeable_concept_pattern = element.pattern&.is_a?(FHIR::CodeableConcept)
164
167
  matching_pattern = false
165
168
  nodes.each do |value|
166
169
  matching_type = 0
@@ -197,7 +200,7 @@ module FHIR
197
200
  matching_pattern = true if vcoding.system == pcoding.system && vcoding.code == pcoding.code
198
201
  end
199
202
  end
200
- elsif %w[CodeableConcept Coding Quantity].include? data_type_found
203
+ elsif ['CodeableConcept', 'Coding', 'Quantity'].include? data_type_found
201
204
  required_strength = element&.binding&.strength == 'required'
202
205
  binding_issues = required_strength ? @errors : @warnings
203
206
 
@@ -275,20 +278,20 @@ module FHIR
275
278
  # elsewhere. There is no good way to determine "where" you should evaluate the expression.
276
279
  element.constraint.each do |constraint|
277
280
  next unless constraint.expression && !nodes.empty?
281
+
278
282
  nodes.each do |node|
279
- begin
280
- result = FHIRPath.evaluate(constraint.expression, node)
281
- if !result && constraint.severity == 'error'
282
- @errors << "#{describe_element(element)}: FHIRPath expression evaluates to false for #{name} (containing: #{node}) invariant rule #{constraint.key}: #{constraint.human}"
283
- end
284
- rescue
285
- @warnings << "#{describe_element(element)}: unable to evaluate FHIRPath expression against JSON for #{name} (containing: #{node}) invariant rule #{constraint.key}: #{constraint.human}"
283
+ result = FHIRPath.evaluate(constraint.expression, node)
284
+ if !result && constraint.severity == 'error'
285
+ @errors << "#{describe_element(element)}: FHIRPath expression evaluates to false for #{name} (containing: #{node}) invariant rule #{constraint.key}: #{constraint.human}"
286
286
  end
287
+ rescue StandardError
288
+ @warnings << "#{describe_element(element)}: unable to evaluate FHIRPath expression against JSON for #{name} (containing: #{node}) invariant rule #{constraint.key}: #{constraint.human}"
287
289
  end
288
290
  end
289
291
 
290
292
  # check children if the element has any
291
293
  return unless element.children
294
+
292
295
  nodes.each do |node|
293
296
  element.children.each do |child|
294
297
  verify_element(child, node)
@@ -323,7 +326,7 @@ module FHIR
323
326
  @errors += definition.errors
324
327
  @warnings += definition.warnings
325
328
  end
326
- rescue
329
+ rescue StandardError
327
330
  @errors << "Unable to verify #{data_type_code} as a FHIR Resource."
328
331
  end
329
332
  return ret_val
@@ -347,7 +350,7 @@ module FHIR
347
350
  @errors += definition.errors
348
351
  @warnings += definition.warnings
349
352
  end
350
- rescue
353
+ rescue StandardError
351
354
  @errors << "Unable to verify #{resource_type} as a FHIR Resource."
352
355
  end
353
356
  ret_val
@@ -373,7 +376,7 @@ module FHIR
373
376
  @errors += definition.errors
374
377
  @warnings += definition.warnings
375
378
  end
376
- rescue
379
+ rescue StandardError
377
380
  @errors << "Unable to verify #{data_type_code} as a FHIR type."
378
381
  end
379
382
  ret_val
@@ -395,14 +398,14 @@ module FHIR
395
398
 
396
399
  matching_type = 0
397
400
 
398
- if vs_uri == 'http://hl7.org/fhir/ValueSet/mimetypes' || vs_uri == 'http://www.rfc-editor.org/bcp/bcp13.txt'
401
+ if ['http://hl7.org/fhir/ValueSet/mimetypes', 'http://www.rfc-editor.org/bcp/bcp13.txt'].include?(vs_uri)
399
402
  matches = MIME::Types[value]
400
403
  known_weird = ['text/cql', 'application/cql+text', 'application/hl7-v2'].include?(value)
401
404
  if (matches.nil? || matches.size.zero? || known_weird) && !some_type_of_xml_or_json?(value)
402
405
  @errors << "#{element.path} has invalid mime-type: '#{value}'"
403
406
  matching_type -= 1 if element.binding.strength == 'required'
404
407
  end
405
- elsif vs_uri == 'http://hl7.org/fhir/ValueSet/languages' || vs_uri == 'http://tools.ietf.org/html/bcp47'
408
+ elsif ['http://hl7.org/fhir/ValueSet/languages', 'http://tools.ietf.org/html/bcp47'].include?(vs_uri)
406
409
  has_region = !(value =~ /-/).nil?
407
410
  valid = !BCP47::Language.identify(value.downcase).nil? && (!has_region || !BCP47::Region.identify(value.upcase).nil?)
408
411
  unless valid
@@ -435,9 +438,10 @@ module FHIR
435
438
 
436
439
  def some_type_of_xml_or_json?(code)
437
440
  m = code.downcase
438
- return true if m == 'xml' || m == 'json'
441
+ return true if ['xml', 'json'].include?(m)
439
442
  return true if m.start_with?('application/', 'text/') && m.end_with?('json', 'xml')
440
443
  return true if m.start_with?('application/xml', 'text/xml', 'application/json', 'text/json')
444
+
441
445
  false
442
446
  end
443
447
  deprecate :is_some_type_of_xml_or_json, :some_type_of_xml_or_json?