fhir_models 4.2.2 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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?