fhir_stu3_models 3.1.1 → 3.2.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.
@@ -39,11 +39,12 @@ module FHIR
39
39
  key = key.to_s
40
40
  meta = self.class::METADATA[key]
41
41
  next if meta.nil?
42
+
42
43
  local_name = key
43
44
  local_name = meta['local_name'] if meta['local_name']
44
45
  begin
45
46
  instance_variable_set("@#{local_name}", value)
46
- rescue
47
+ rescue StandardError
47
48
  # TODO: this appears to be a dead code branch
48
49
  nil
49
50
  end
@@ -86,7 +87,7 @@ module FHIR
86
87
  if child['resourceType'] && !klass::METADATA['resourceType']
87
88
  klass = begin
88
89
  FHIR::STU3.const_get(child['resourceType'])
89
- rescue => _exception
90
+ rescue StandardError => _e
90
91
  # TODO: this appears to be a dead code branch
91
92
  # TODO: should this log / re-raise the exception if encountered instead of silently swallowing it?
92
93
  FHIR::STU3.logger.error("Unable to identify embedded class #{child['resourceType']}\n#{exception.backtrace}")
@@ -95,10 +96,10 @@ module FHIR
95
96
  end
96
97
  begin
97
98
  obj = klass.new(child)
98
- rescue => exception
99
+ rescue StandardError => e
99
100
  # TODO: this appears to be a dead code branch
100
101
  # TODO: should this re-raise the exception if encountered instead of silently swallowing it?
101
- FHIR::STU3.logger.error("Unable to inflate embedded class #{klass}\n#{exception.backtrace}")
102
+ FHIR::STU3.logger.error("Unable to inflate embedded class #{klass}\n#{e.backtrace}")
102
103
  end
103
104
  obj
104
105
  end
@@ -7,7 +7,7 @@ module FHIR
7
7
  # This module includes methods to serialize or deserialize FHIR resources to and from JSON.
8
8
  #
9
9
 
10
- def to_json
10
+ def to_json(*_args)
11
11
  JSON.pretty_unparse(to_hash)
12
12
  end
13
13
 
@@ -18,7 +18,7 @@ module FHIR
18
18
  resource_type = hash['resourceType']
19
19
  klass = Module.const_get("FHIR::STU3::#{resource_type}")
20
20
  resource = klass.new(hash)
21
- rescue => e
21
+ rescue StandardError => e
22
22
  FHIR::STU3.logger.error("Failed to deserialize JSON:\n#{e.backtrace}")
23
23
  FHIR::STU3.logger.debug("JSON:\n#{json}")
24
24
  resource = nil
@@ -23,40 +23,39 @@ module FHIR
23
23
  to_hash.hash
24
24
  end
25
25
 
26
+ def respond_to_missing?(method_name, *)
27
+ (defined?(self.class::MULTIPLE_TYPES) && self.class::MULTIPLE_TYPES[method_name.to_s]) ||
28
+ (!@extension.nil? && !@extension.empty? && !find_extension(@extension, method_name).first.nil?) ||
29
+ (!@modifierExtension.nil? && !@modifierExtension.empty? && !find_extension(@modifierExtension, method_name).first.nil?) ||
30
+ super
31
+ end
32
+
26
33
  # allow two FHIR models to be compared for equality
27
34
  def ==(other)
28
35
  self.class == other.class && to_hash == other.to_hash
29
36
  end
30
37
  alias eql? ==
31
38
 
32
- def method_missing(method, *_args, &_block)
33
- if defined?(self.class::MULTIPLE_TYPES) && self.class::MULTIPLE_TYPES[method.to_s]
34
- self.class::MULTIPLE_TYPES[method.to_s].each do |type|
39
+ def method_missing(method_name, *_args, &_block)
40
+ if defined?(self.class::MULTIPLE_TYPES) && self.class::MULTIPLE_TYPES[method_name.to_s]
41
+ self.class::MULTIPLE_TYPES[method_name.to_s].each do |type|
35
42
  type[0] = type[0].upcase
36
- value = send("#{method}#{type}".to_sym)
43
+ value = send("#{method_name}#{type}".to_sym)
37
44
  return value unless value.nil?
38
45
  end
39
46
  return nil
40
47
  elsif !@extension.nil? && !@extension.empty?
41
- ext = @extension.select do |x|
42
- name = x.url.tr('-', '_').split('/').last
43
- anchor = name.split('#').last
44
- (method.to_s == name || method.to_s == anchor)
45
- end
46
- unless ext.first.nil?
47
- return ext.first.value.nil? ? ext.first : ext.first.value
48
+ desired_extension = find_extension(@extension, method_name)
49
+ unless desired_extension.first.nil?
50
+ return desired_extension.first.value.nil? ? desired_extension.first : desired_extension.first.value
48
51
  end
49
52
  elsif !@modifierExtension.nil? && !@modifierExtension.empty?
50
- ext = @modifierExtension.select do |x|
51
- name = x.url.tr('-', '_').split('/').last
52
- anchor = name.split('#').last
53
- (method.to_s == name || method.to_s == anchor)
54
- end
55
- unless ext.first.nil?
56
- return ext.first.value.nil? ? ext.first : ext.first.value
53
+ desired_extension = find_extension(@modifierExtension, method_name)
54
+ unless desired_extension.first.nil?
55
+ return desired_extension.first.value.nil? ? desired_extension.first : desired_extension.first.value
57
56
  end
58
57
  end
59
- raise NoMethodError.new("undefined method `#{method}' for #{self.class.name}", method)
58
+ raise NoMethodError.new("undefined method `#{method_name}' for #{self.class.name}", method_name)
60
59
  end
61
60
 
62
61
  def to_reference
@@ -142,14 +141,14 @@ module FHIR
142
141
  end # metadata.each
143
142
  # check multiple types
144
143
  multiple_types = begin
145
- self.class::MULTIPLE_TYPES
146
- rescue
147
- {}
148
- end
144
+ self.class::MULTIPLE_TYPES
145
+ rescue StandardError
146
+ {}
147
+ end
149
148
  multiple_types.each do |prefix, suffixes|
150
149
  present = []
151
150
  suffixes.each do |suffix|
152
- typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..-1]}"
151
+ typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..]}"
153
152
  # check which multiple data types are actually present, not just errors
154
153
  # actually, this might be allowed depending on cardinality
155
154
  value = instance_variable_get("@#{typename}")
@@ -158,8 +157,9 @@ module FHIR
158
157
  errors[prefix] = ["#{prefix}[x]: more than one type present."] if present.length > 1
159
158
  # remove errors for suffixes that are not present
160
159
  next unless present.length == 1
160
+
161
161
  suffixes.each do |suffix|
162
- typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..-1]}"
162
+ typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..]}"
163
163
  errors.delete(typename) unless present.include?(typename)
164
164
  end
165
165
  end
@@ -222,10 +222,12 @@ module FHIR
222
222
  # check binding
223
223
  next unless meta['binding']
224
224
  next unless meta['binding']['strength'] == 'required'
225
+
225
226
  the_codes = [v]
226
- if meta['type'] == 'Coding'
227
+ case meta['type']
228
+ when 'Coding'
227
229
  the_codes = [v.code]
228
- elsif meta['type'] == 'CodeableConcept'
230
+ when 'CodeableConcept'
229
231
  the_codes = v.coding.map(&:code).compact
230
232
  end
231
233
  has_valid_code = false
@@ -248,6 +250,7 @@ module FHIR
248
250
  def validate_reference_type(ref, meta, contained_here, errors)
249
251
  return unless ref.reference && meta['type_profiles']
250
252
  return if ref.reference.start_with?('urn:uuid:', 'urn:oid:')
253
+
251
254
  matches_one_profile = false
252
255
  meta['type_profiles'].each do |p|
253
256
  basetype = p.split('/').last
@@ -259,7 +262,7 @@ module FHIR
259
262
  matches_one_profile = true if meta['type_profiles'].include?('http://hl7.org/fhir/StructureDefinition/Resource')
260
263
  if !matches_one_profile && ref.reference.start_with?('#')
261
264
  # we need to look at the local contained resources
262
- r = contained_here.find { |x| x.id == ref.reference[1..-1] }
265
+ r = contained_here.find { |x| x.id == ref.reference[1..] }
263
266
  if !r.nil?
264
267
  meta['type_profiles'].each do |p|
265
268
  p = p.split('/').last
@@ -280,12 +283,13 @@ module FHIR
280
283
 
281
284
  def check_binding_uri(uri, value)
282
285
  valid = false
283
- if uri == 'http://hl7.org/fhir/ValueSet/content-type' || uri == 'http://www.rfc-editor.org/bcp/bcp13.txt'
286
+ case uri
287
+ when 'http://hl7.org/fhir/ValueSet/content-type', 'http://www.rfc-editor.org/bcp/bcp13.txt'
284
288
  matches = MIME::Types[value]
285
289
  json_or_xml = value.downcase.include?('xml') || value.downcase.include?('json')
286
290
  known_weird = ['text/cql', 'application/cql+text'].include?(value)
287
291
  valid = json_or_xml || known_weird || (!matches.nil? && !matches.empty?)
288
- elsif uri == 'http://hl7.org/fhir/ValueSet/languages' || uri == 'http://tools.ietf.org/html/bcp47'
292
+ when 'http://hl7.org/fhir/ValueSet/languages', 'http://tools.ietf.org/html/bcp47'
289
293
  has_region = !(value =~ /-/).nil?
290
294
  valid = !BCP47::Language.identify(value.downcase).nil? && (!has_region || !BCP47::Region.identify(value.upcase).nil?)
291
295
  else
@@ -315,7 +319,15 @@ module FHIR
315
319
  self
316
320
  end
317
321
 
318
- private :validate_reference_type, :check_binding_uri, :validate_field
322
+ def find_extension(extension_source, method_name)
323
+ extension_source.select do |extension|
324
+ name = extension.url.tr('-', '_').split('/').last
325
+ anchor = name.split('#').last
326
+ (method_name.to_s == name || method_name.to_s == anchor)
327
+ end
328
+ end
329
+
330
+ private :validate_reference_type, :check_binding_uri, :validate_field, :find_extension
319
331
  end
320
332
  end
321
333
  end
@@ -12,16 +12,17 @@ module FHIR
12
12
 
13
13
  # Remove entries that do not interest us: CompartmentDefinitions, OperationDefinitions, Conformance statements
14
14
  hash['entry'].select! do |entry|
15
- %w[StructureDefinition ValueSet CodeSystem SearchParameter].include? entry['resource']['resourceType']
15
+ ['StructureDefinition', 'ValueSet', 'CodeSystem', 'SearchParameter'].include? entry['resource']['resourceType']
16
16
  end
17
17
 
18
18
  # Remove unnecessary elements from the hash
19
19
  hash['entry'].each do |entry|
20
20
  next unless entry['resource']
21
- pre_process_structuredefinition(entry['resource']) if 'StructureDefinition' == entry['resource']['resourceType']
22
- pre_process_valueset(entry['resource']) if 'ValueSet' == entry['resource']['resourceType']
23
- pre_process_codesystem(entry['resource']) if 'CodeSystem' == entry['resource']['resourceType']
24
- pre_process_searchparam(entry['resource']) if 'SearchParameter' == entry['resource']['resourceType']
21
+
22
+ pre_process_structuredefinition(entry['resource']) if entry['resource']['resourceType'] == 'StructureDefinition'
23
+ pre_process_valueset(entry['resource']) if entry['resource']['resourceType'] == 'ValueSet'
24
+ pre_process_codesystem(entry['resource']) if entry['resource']['resourceType'] == 'CodeSystem'
25
+ pre_process_searchparam(entry['resource']) if entry['resource']['resourceType'] == 'SearchParameter'
25
26
  remove_fhir_comments(entry['resource'])
26
27
  end
27
28
 
@@ -35,26 +36,30 @@ module FHIR
35
36
 
36
37
  def self.pre_process_structuredefinition(hash)
37
38
  # Remove large HTML narratives and unused content
38
- %w[text publisher contact description requirements mapping].each { |key| hash.delete(key) }
39
+ ['text', 'publisher', 'contact', 'description', 'requirements', 'mapping'].each { |key| hash.delete(key) }
39
40
 
40
41
  # Remove unused descriptions within the snapshot and differential elements
41
- %w[snapshot differential].each do |key|
42
+ ['snapshot', 'differential'].each do |key|
42
43
  next unless hash[key]
44
+
43
45
  hash[key]['element'].each do |element|
44
- %w[short definition comments requirements alias mapping].each { |subkey| element.delete(subkey) }
46
+ ['short', 'definition', 'comments', 'requirements', 'alias', 'mapping'].each { |subkey| element.delete(subkey) }
45
47
  end
46
48
  end
47
49
  end
48
50
 
49
51
  def self.pre_process_valueset(hash)
50
52
  # Remove large HTML narratives and unused content
51
- %w[meta text publisher contact description requirements].each { |key| hash.delete(key) }
53
+ ['meta', 'text', 'publisher', 'contact', 'description', 'requirements'].each { |key| hash.delete(key) }
52
54
 
53
55
  return unless hash['compose']
54
- %w[include exclude].each do |key|
56
+
57
+ ['include', 'exclude'].each do |key|
55
58
  next unless hash['compose'][key]
59
+
56
60
  hash['compose'][key].each do |element|
57
61
  next unless element['concept']
62
+
58
63
  element['concept'].each do |concept|
59
64
  concept.delete('designation')
60
65
  end
@@ -64,16 +69,18 @@ module FHIR
64
69
 
65
70
  def self.pre_process_codesystem(hash)
66
71
  # Remove large HTML narratives and unused content
67
- %w[meta text publisher contact description requirements].each { |key| hash.delete(key) }
72
+ ['meta', 'text', 'publisher', 'contact', 'description', 'requirements'].each { |key| hash.delete(key) }
68
73
  return unless hash['concept']
74
+
69
75
  hash['concept'].each do |concept|
70
76
  pre_process_codesystem_concept(concept)
71
77
  end
72
78
  end
73
79
 
74
80
  def self.pre_process_codesystem_concept(hash)
75
- %w[extension definition designation].each { |key| hash.delete(key) }
81
+ ['extension', 'definition', 'designation'].each { |key| hash.delete(key) }
76
82
  return unless hash['concept']
83
+
77
84
  hash['concept'].each do |concept|
78
85
  pre_process_codesystem_concept(concept)
79
86
  end
@@ -81,15 +88,16 @@ module FHIR
81
88
 
82
89
  def self.pre_process_searchparam(hash)
83
90
  # Remove large HTML narratives and unused content
84
- %w[id url name date publisher contact description xpathUsage].each { |key| hash.delete(key) }
91
+ ['id', 'url', 'name', 'date', 'publisher', 'contact', 'description', 'xpathUsage'].each { |key| hash.delete(key) }
85
92
  end
86
93
 
87
94
  def self.remove_fhir_comments(hash)
88
95
  hash.delete('fhir_comments')
89
96
  hash.each do |_key, value|
90
- if value.is_a?(Hash)
97
+ case value
98
+ when Hash
91
99
  remove_fhir_comments(value)
92
- elsif value.is_a?(Array)
100
+ when Array
93
101
  value.each do |v|
94
102
  remove_fhir_comments(v) if v.is_a?(Hash)
95
103
  end
@@ -25,7 +25,7 @@ module FHIR
25
25
  # if hash contains resourceType
26
26
  # create a child node with the name==resourceType
27
27
  # fill that, and place the child under the above `node`
28
- if hash['resourceType'] && hash['resourceType'].is_a?(String)
28
+ if hash['resourceType'].is_a?(String)
29
29
  child_name = hash['resourceType']
30
30
  hash.delete('resourceType')
31
31
  child = hash_to_xml_node(child_name, hash, doc)
@@ -34,11 +34,13 @@ module FHIR
34
34
  end
35
35
 
36
36
  hash.each do |key, value|
37
- next if %w[extension modifierExtension].include?(name) && key == 'url'
37
+ next if ['extension', 'modifierExtension'].include?(name) && key == 'url'
38
38
  next if key == 'id' && !FHIR::STU3::RESOURCES.include?(name)
39
- if value.is_a?(Hash)
39
+
40
+ case value
41
+ when Hash
40
42
  node.add_child(hash_to_xml_node(key, value, doc))
41
- elsif value.is_a?(Array)
43
+ when Array
42
44
  value.each do |v|
43
45
  if v.is_a?(Hash)
44
46
  node.add_child(hash_to_xml_node(key, v, doc))
@@ -63,7 +65,7 @@ module FHIR
63
65
  node.add_child(child)
64
66
  end
65
67
  end
66
- node.set_attribute('url', hash['url']) if %w[extension modifierExtension].include?(name)
68
+ node.set_attribute('url', hash['url']) if ['extension', 'modifierExtension'].include?(name)
67
69
  node.set_attribute('id', hash['id']) if hash['id'] && !FHIR::STU3::RESOURCES.include?(name)
68
70
  node
69
71
  end
@@ -79,7 +81,7 @@ module FHIR
79
81
  resource_type = doc.root.name
80
82
  klass = Module.const_get("FHIR::STU3::#{resource_type}")
81
83
  resource = klass.new(hash)
82
- rescue => e
84
+ rescue StandardError => e
83
85
  FHIR::STU3.logger.error("Failed to deserialize XML:\n#{e.backtrace}")
84
86
  FHIR::STU3.logger.debug("XML:\n#{xml}")
85
87
  resource = nil
@@ -109,7 +111,7 @@ module FHIR
109
111
  end
110
112
  end
111
113
  end
112
- hash['url'] = node.get_attribute('url') if %w[extension modifierExtension].include?(node.name)
114
+ hash['url'] = node.get_attribute('url') if ['extension', 'modifierExtension'].include?(node.name)
113
115
  hash['id'] = node.get_attribute('id') if node.get_attribute('id') # Testscript fixture ids (applies to any BackboneElement)
114
116
  hash['resourceType'] = node.name if FHIR::STU3::RESOURCES.include?(node.name)
115
117
 
@@ -11,6 +11,7 @@ module FHIR
11
11
  end
12
12
  end
13
13
  return unless methods.include? new_method
14
+
14
15
  (class << self; self; end).instance_eval do
15
16
  define_method(old_method) do |*args, &block|
16
17
  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
  module STU3
@@ -12,7 +13,7 @@ module FHIR
12
13
  end
13
14
 
14
15
  def self.default_logger
15
- @default_logger ||= Logger.new(ENV['FHIR_LOGGER'] || STDOUT)
16
+ @default_logger ||= Logger.new(ENV['FHIR_LOGGER'] || $stdout)
16
17
  end
17
18
 
18
19
  def self.from_contents(contents)
@@ -35,11 +36,11 @@ module FHIR
35
36
  when 'string', 'markdown'
36
37
  value.is_a?(String)
37
38
  when 'decimal'
38
- !(value.to_s =~ /\A([-+]?([0]|([1-9][0-9]*))(\.[0-9]+)?)\Z/).nil?
39
+ !(value.to_s =~ /\A([-+]?(0|([1-9][0-9]*))(\.[0-9]+)?)\Z/).nil?
39
40
  when 'uri'
40
41
  begin
41
42
  !URI.parse(value).nil?
42
- rescue
43
+ rescue StandardError
43
44
  false
44
45
  end
45
46
  when 'base64binary'
@@ -48,7 +49,7 @@ module FHIR
48
49
  # whitespace is not significant so we strip it out before doing the regex so that we can be sure that
49
50
  # the number of characters is a multiple of 4.
50
51
  # https://tools.ietf.org/html/rfc4648
51
- !(value.to_s.gsub(/\s/, '') =~ %r{\A(|[0-9a-zA-Z\+=/]{4}+)\Z}).nil?
52
+ !(value.to_s.gsub(/\s/, '') =~ %r{\A(|[0-9a-zA-Z+=/]{4}+)\Z}).nil?
52
53
  when 'instant'
53
54
  formatted_value = value.respond_to?(:xmlschema) ? value.xmlschema : value.to_s
54
55
  !(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?
@@ -63,16 +64,16 @@ module FHIR
63
64
  when 'time'
64
65
  !(value.to_s =~ /\A(([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?)\Z/).nil?
65
66
  when 'code'
66
- !(value.to_s =~ /\A[^\s]+([\s]?[^\s]+)*\Z/).nil?
67
+ !(value.to_s =~ /\A[^\s]+(\s?[^\s]+)*\Z/).nil?
67
68
  when 'oid'
68
69
  !(value.to_s =~ /\Aurn:oid:[0-2](\.[1-9]\d*)+\Z/).nil?
69
70
  when 'id'
70
- !(value.to_s =~ /\A[A-Za-z0-9\-\.]{1,64}\Z/).nil?
71
+ !(value.to_s =~ /\A[A-Za-z0-9\-.]{1,64}\Z/).nil?
71
72
  when 'xhtml'
72
73
  fragment = Nokogiri::HTML::DocumentFragment.parse(value)
73
74
  value.is_a?(String) && fragment.errors.size.zero?
74
75
  when 'unsignedint'
75
- !(value.to_s =~ /\A([0]|([1-9][0-9]*))\Z/).nil?
76
+ !(value.to_s =~ /\A(0|([1-9][0-9]*))\Z/).nil?
76
77
  when 'positiveint'
77
78
  !(value.to_s =~ /\A+?[1-9][0-9]*\Z/).nil?
78
79
  else
@@ -26,6 +26,7 @@ module FHIR
26
26
  def keep_children(whitelist = [])
27
27
  @marked_for_keeping = true if whitelist.include?(path)
28
28
  return unless @children
29
+
29
30
  @children.each do |child|
30
31
  child.keep_children(whitelist)
31
32
  end
@@ -33,14 +34,16 @@ module FHIR
33
34
 
34
35
  def sweep_children
35
36
  return unless @children
37
+
36
38
  @children.each(&:sweep_children)
37
- @children = @children.keep_if(&:marked_for_keeping)
39
+ @children.keep_if(&:marked_for_keeping)
38
40
  @marked_for_keeping = !@children.empty? || @marked_for_keeping
39
41
  end
40
42
 
41
43
  def print_children(spaces = 0)
42
44
  puts "#{' ' * spaces}+#{local_name || path}"
43
45
  return nil unless @children
46
+
44
47
  @children.each do |child|
45
48
  child.print_children(spaces + 2)
46
49
  end
@@ -60,7 +60,7 @@ module FHIR
60
60
  if json.is_a? String
61
61
  begin
62
62
  json = JSON.parse(json)
63
- rescue => e
63
+ rescue StandardError => e
64
64
  @errors << "Failed to parse JSON: #{e.message} %n #{h} %n #{e.backtrace.join("\n")}"
65
65
  return false
66
66
  end
@@ -100,13 +100,15 @@ module FHIR
100
100
  def get_json_nodes(json, path)
101
101
  results = []
102
102
  return [json] if path.nil?
103
+
103
104
  steps = path.split('.')
104
105
  steps.each.with_index do |step, index|
105
- if json.is_a? Hash
106
+ case json
107
+ when Hash
106
108
  json = json[step]
107
- elsif json.is_a? Array
109
+ when Array
108
110
  json.each do |e|
109
- results << get_json_nodes(e, steps[index..-1].join('.'))
111
+ results << get_json_nodes(e, steps[index..].join('.'))
110
112
  end
111
113
  return results.flatten!
112
114
  else
@@ -126,7 +128,7 @@ module FHIR
126
128
 
127
129
  def verify_element(element, json)
128
130
  path = element.local_name || element.path
129
- path = path[(@hierarchy.path.size + 1)..-1] if path.start_with? @hierarchy.path
131
+ path = path[(@hierarchy.path.size + 1)..] if path.start_with? @hierarchy.path
130
132
 
131
133
  if element.type && !element.type.empty?
132
134
  data_type_found = element.type.first.code
@@ -158,10 +160,11 @@ module FHIR
158
160
  verify_cardinality(element, nodes)
159
161
 
160
162
  return if nodes.empty?
163
+
161
164
  # Check the datatype for each node, only if the element has one declared, and it isn't the root element
162
165
  if !element.type.empty? && element.path != id
163
166
  # element.type not being empty implies data_type_found != nil, for valid profiles
164
- codeable_concept_pattern = element.pattern && element.pattern.is_a?(FHIR::STU3::CodeableConcept)
167
+ codeable_concept_pattern = element.pattern&.is_a?(FHIR::STU3::CodeableConcept)
165
168
  codeable_concept_binding = element.binding
166
169
  matching_pattern = false
167
170
  nodes.each do |value|
@@ -201,19 +204,20 @@ module FHIR
201
204
  end
202
205
  elsif data_type_found == 'CodeableConcept' && codeable_concept_binding
203
206
  binding_issues =
204
- if element.binding.strength == 'extensible'
207
+ case element.binding.strength
208
+ when 'extensible'
205
209
  @warnings
206
- elsif element.binding.strength == 'required'
210
+ when 'required'
207
211
  @errors
208
212
  else # e.g., example-strength or unspecified
209
213
  [] # Drop issues errors on the floor, in throwaway array
210
214
  end
211
215
 
212
- valueset_uri = element.binding && element.binding.valueSetReference && element.binding.valueSetReference.reference
216
+ valueset_uri = element.binding&.valueSetReference && element.binding.valueSetReference.reference
213
217
  vcc = FHIR::STU3::CodeableConcept.new(value)
214
218
  if valueset_uri && self.class.vs_validators[valueset_uri]
215
219
  check_fn = self.class.vs_validators[valueset_uri]
216
- has_valid_code = vcc.coding && vcc.coding.any? { |c| check_fn.call(c) }
220
+ has_valid_code = vcc.coding&.any? { |c| check_fn.call(c) }
217
221
  unless has_valid_code
218
222
  binding_issues << "#{describe_element(element)} has no codings from #{valueset_uri}. Codings evaluated: #{vcc.to_json}"
219
223
  end
@@ -262,13 +266,14 @@ module FHIR
262
266
  # elsewhere. There is no good way to determine "where" you should evaluate the expression.
263
267
  element.constraint.each do |constraint|
264
268
  next unless constraint.expression && !nodes.empty?
269
+
265
270
  nodes.each do |node|
266
271
  result = FluentPath::STU3.evaluate(constraint.expression, node)
267
272
  if !result && constraint.severity == 'error'
268
273
  @errors << "#{describe_element(element)}: FluentPath expression evaluates to false for #{name} invariant rule #{constraint.key}: #{constraint.human}"
269
274
  @errors << node.to_s
270
275
  end
271
- rescue
276
+ rescue StandardError
272
277
  @warnings << "#{describe_element(element)}: unable to evaluate FluentPath expression against JSON for #{name} invariant rule #{constraint.key}: #{constraint.human}"
273
278
  @warnings << node.to_s
274
279
  end
@@ -276,6 +281,7 @@ module FHIR
276
281
 
277
282
  # check children if the element has any
278
283
  return unless element.children
284
+
279
285
  nodes.each do |node|
280
286
  element.children.each do |child|
281
287
  verify_element(child, node)
@@ -310,7 +316,7 @@ module FHIR
310
316
  @errors += definition.errors
311
317
  @warnings += definition.warnings
312
318
  end
313
- rescue
319
+ rescue StandardError
314
320
  @errors << "Unable to verify #{data_type_code} as a FHIR Resource."
315
321
  end
316
322
  return ret_val
@@ -334,7 +340,7 @@ module FHIR
334
340
  @errors += definition.errors
335
341
  @warnings += definition.warnings
336
342
  end
337
- rescue
343
+ rescue StandardError
338
344
  @errors << "Unable to verify #{resource_type} as a FHIR Resource."
339
345
  end
340
346
  ret_val
@@ -360,7 +366,7 @@ module FHIR
360
366
  @errors += definition.errors
361
367
  @warnings += definition.warnings
362
368
  end
363
- rescue
369
+ rescue StandardError
364
370
  @errors << "Unable to verify #{data_type_code} as a FHIR type."
365
371
  end
366
372
  ret_val
@@ -378,13 +384,13 @@ module FHIR
378
384
 
379
385
  matching_type = 0
380
386
 
381
- if vs_uri == 'http://hl7.org/fhir/ValueSet/content-type' || vs_uri == 'http://www.rfc-editor.org/bcp/bcp13.txt'
387
+ if ['http://hl7.org/fhir/ValueSet/content-type', 'http://www.rfc-editor.org/bcp/bcp13.txt'].include?(vs_uri)
382
388
  matches = MIME::Types[value]
383
389
  if (matches.nil? || matches.size.zero?) && !some_type_of_xml_or_json?(value)
384
390
  @errors << "#{element.path} has invalid mime-type: '#{value}'"
385
391
  matching_type -= 1 if element.binding.strength == 'required'
386
392
  end
387
- elsif vs_uri == 'http://hl7.org/fhir/ValueSet/languages' || vs_uri == 'http://tools.ietf.org/html/bcp47'
393
+ elsif ['http://hl7.org/fhir/ValueSet/languages', 'http://tools.ietf.org/html/bcp47'].include?(vs_uri)
388
394
  has_region = !(value =~ /-/).nil?
389
395
  valid = !BCP47::Language.identify(value.downcase).nil? && (!has_region || !BCP47::Region.identify(value.upcase).nil?)
390
396
  unless valid
@@ -417,9 +423,10 @@ module FHIR
417
423
 
418
424
  def some_type_of_xml_or_json?(code)
419
425
  m = code.downcase
420
- return true if m == 'xml' || m == 'json'
426
+ return true if ['xml', 'json'].include?(m)
421
427
  return true if m.start_with?('application/', 'text/') && m.end_with?('json', 'xml')
422
428
  return true if m.start_with?('application/xml', 'text/xml', 'application/json', 'text/json')
429
+
423
430
  false
424
431
  end
425
432
  deprecate :is_some_type_of_xml_or_json, :some_type_of_xml_or_json?