Class: Inferno::DSL::FHIREvaluation::Rules::DifferentialContentHasExamples

Inherits:
Inferno::DSL::FHIREvaluation::Rule show all
Defined in:
lib/inferno/dsl/fhir_evaluation/rules/differential_content_has_examples.rb

Instance Method Summary collapse

Instance Method Details

#check(context) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/inferno/dsl/fhir_evaluation/rules/differential_content_has_examples.rb', line 8

def check(context)
  unused_differential = Hash.new { |field, url| field[url] = Set.new }
  collect_profile_differential_content(unused_differential, context.ig.profiles)
  collect_profile_differential_content(unused_differential, context.ig.extensions)
  remove_found_differential_content(unused_differential, context.data)

  if unused_differential.any? { |_url, diff| !diff.empty? }
    message = gen_differential_fail_message(unused_differential)
    result = EvaluationResult.new(message, rule: self)
  else
    message = 'All differential fields are represented in instances'
    result = EvaluationResult.new(message, severity: 'success', rule: self)
  end

  context.add_result result
end

#clean_value(value) ⇒ Object

rubocop:enable Metrics/CyclomaticComplexity



80
81
82
83
84
85
86
87
88
# File 'lib/inferno/dsl/fhir_evaluation/rules/differential_content_has_examples.rb', line 80

def clean_value(value)
  stripped_val = value.id.partition('.').last
  stripped_val = stripped_val.partition('[').first if stripped_val.end_with? ']'
  stripped_val.split('.').map do |field|
    field = field.partition(':').first if field.include?(':')
    field = field.partition('[').first if field.include?('[')
    field
  end.join('.')
end

#collect_profile_differential_content(unused_differential, profiles) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/inferno/dsl/fhir_evaluation/rules/differential_content_has_examples.rb', line 25

def collect_profile_differential_content(unused_differential, profiles)
  profiles.each do |profile|
    profile.each_element do |value, , path|
      next unless path.start_with? 'differential'

      next unless value.is_a? FHIR::ElementDefinition
      next unless value.id.include? '.'

      # Skip fields that are disallowed by the profile (cardinality 0..0)
      # Note that max is a string to allow for "*", not an int
      next if value.max == '0'

      # TODO: discriminate between extensions
      # if you have field.extension:A and field.extension:B
      # only field.extension is recorded and checked for
      # if A and B are not defined in the IG,they may be missed
      clean_val = clean_value(value)

      unused_differential[profile.url].add(clean_val)
    end
  end
end

#gen_differential_fail_message(unused_differential) ⇒ Object



112
113
114
115
116
117
118
119
# File 'lib/inferno/dsl/fhir_evaluation/rules/differential_content_has_examples.rb', line 112

def gen_differential_fail_message(unused_differential)
  "Found fields highlighted in the differential view, but not used in instances: #{
                  unused_differential.map do |url, field|
                    next if field.empty?

                    "\n Profile/Extension: #{url}  \n\tFields: #{field.join(', ')}"
                  end.compact.join}"
end

#plain_value(path) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/inferno/dsl/fhir_evaluation/rules/differential_content_has_examples.rb', line 90

def plain_value(path)
  if path.include? '.'
    path_array = path.split('.').map! do |field|
      field.start_with?('value') ? 'value' : field
    end
    path_array.join('.')
  elsif path.start_with?('value')
    'value'
  elsif path.end_with?(']')
    path.rpartition('[').first
  else
    path
  end
end

#remove_found_differential_content(unused_differential, examples) ⇒ Object

rubocop:disable Metrics/CyclomaticComplexity



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/inferno/dsl/fhir_evaluation/rules/differential_content_has_examples.rb', line 49

def remove_found_differential_content(unused_differential, examples)
  examples.each do |resource|
    extension_base_path = ''
    extension_url = ''
    resource.each_element do |value, , path|
      profiles = resource&.meta&.profile || []
      profiles.each do |profile|
        processed_path = plain_value(path)
        processed_path = rm_brackets(processed_path)

        if path.match?('extension\[\d+\]\.url$')
          extension_base_path = path.rpartition('.').first
          extension_url = value
          unused_differential[extension_url].delete('url') if unused_differential.key?(extension_url)
          unused_differential[extension_url].delete('extension') if unused_differential.key?(extension_url)
          unused_differential.delete(extension_url) if unused_differential[extension_url].empty?
        elsif path.start_with?(extension_base_path) && !extension_base_path.empty?
          if unused_differential.key?(extension_url)
            unused_differential[extension_url].delete(processed_path.rpartition('.').last)
          end
          unused_differential.delete(extension_url) if unused_differential[extension_url].empty?
        else
          unused_differential[profile].delete(processed_path) if unused_differential.key?(profile)
          unused_differential.delete(profile) if unused_differential[profile].empty?
        end
      end
    end
  end
end

#rm_brackets(path) ⇒ Object



105
106
107
108
109
110
# File 'lib/inferno/dsl/fhir_evaluation/rules/differential_content_has_examples.rb', line 105

def rm_brackets(path)
  path_array = path.split('.').map! do |field|
    field.include?('[') ? field.partition('[').first : field
  end
  path_array.join('.')
end