inferno_core 0.5.3 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '090f68164e2fc19d1f97f62dd0fb13c12c77eb12c29bb9b528c9b9cb56f48770'
4
- data.tar.gz: e239a1702ee11a85229db5355ad7c8a415d71b40018c052bb3e2c972c824d12c
3
+ metadata.gz: e11d6b274778016418f7189d8ec9e724cf20861c6e03385dc9c302299f198d18
4
+ data.tar.gz: '09c65484d51b2f7be0a3985b374d51593d59c432ba11c21bd10d54c798ccafa4'
5
5
  SHA512:
6
- metadata.gz: 2491100649bba23576a442fdeeef561b407e5f7b0b89fbd0827b55ced37e1dcf29c1f5b908c316e44c38301a74d760b5fa8bba4b2cfdf5e039d36fab4c3c181f
7
- data.tar.gz: e05eb12863387acecd5782267f25700d3a2e233ed8f581bda98627a76822c33b5e6a1f0ed8e770a6a9d971c88be610453f0aac9a13245b8412f2cb7673431327
6
+ metadata.gz: 0daf93ce97d8a5a8e9b409200d7c001e4ac49107887db05073399a74795a94b449d3c1eb1d139214c1402e1ea10a954ee1271b80c642909c379cd7bb0ba7a1f0
7
+ data.tar.gz: 3a70bb18128af1494e0fcd1a023d8e18e8043dd535ae9c00f8471c8eb85e23678fa7c8bcb19591852c3593c6588ba92af206a90644cf6288659179fef98c1a41
@@ -1,14 +1,21 @@
1
1
  require_relative '../../../inferno/dsl/fhir_evaluation/evaluator'
2
+ require_relative '../../../inferno/entities'
3
+ require_relative '../../utils/ig_downloader'
4
+
5
+ require 'tempfile'
2
6
 
3
7
  module Inferno
4
8
  module CLI
5
- class Evaluate
6
- def run(ig_path, data_path, _log_level)
9
+ class Evaluate < Thor::Group
10
+ include Thor::Actions
11
+ include Inferno::Utils::IgDownloader
12
+
13
+ def evaluate(ig_path, data_path, _log_level)
7
14
  validate_args(ig_path, data_path)
15
+ _ig = get_ig(ig_path)
8
16
 
9
- # IG Import, rule execution, and result output below will be integrated at phase 2 and 3.
17
+ # Rule execution, and result output below will be integrated soon.
10
18
 
11
- # @ig = File.join(__dir__, 'ig', ig_path)
12
19
  # if data_path
13
20
  # DatasetLoader.from_path(File.join(__dir__, data_path))
14
21
  # else
@@ -30,6 +37,32 @@ module Inferno
30
37
  raise "Provided path '#{data_path}' is not a directory"
31
38
  end
32
39
 
40
+ def get_ig(ig_path)
41
+ if File.exist?(ig_path)
42
+ ig = Inferno::Entities::IG.from_file(ig_path)
43
+ elsif in_user_package_cache?(ig_path.sub('@', '#'))
44
+ # NPM syntax for a package identifier is id@version (eg, hl7.fhir.us.core@3.1.1)
45
+ # but in the cache the separator is # (hl7.fhir.us.core#3.1.1)
46
+ cache_directory = File.join(user_package_cache, ig_path.sub('@', '#'))
47
+ ig = Inferno::Entities::IG.from_file(cache_directory)
48
+ else
49
+ Tempfile.create('package.tgz') do |temp_file|
50
+ load_ig(ig_path, nil, { force: true }, temp_file.path)
51
+ ig = Inferno::Entities::IG.from_file(temp_file.path)
52
+ end
53
+ end
54
+ ig.add_self_to_repository
55
+ ig
56
+ end
57
+
58
+ def user_package_cache
59
+ File.join(Dir.home, '.fhir', 'packages')
60
+ end
61
+
62
+ def in_user_package_cache?(ig_identifier)
63
+ File.directory?(File.join(user_package_cache, ig_identifier))
64
+ end
65
+
33
66
  def output_results(results, output)
34
67
  if output&.end_with?('json')
35
68
  oo = FhirEvaluator::EvaluationResult.to_operation_outcome(results)
@@ -45,7 +45,7 @@ module Inferno
45
45
  type: :string,
46
46
  desc: 'Export evaluation result to outcome.json as an OperationOutcome'
47
47
  def evaluate(ig_path)
48
- Evaluate.new.run(ig_path, options[:data_path], Logger::INFO)
48
+ Evaluate.new.evaluate(ig_path, options[:data_path], Logger::INFO)
49
49
  end
50
50
 
51
51
  desc 'console', 'Start an interactive console session with Inferno'
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fhir_models'
4
+ require 'pathname'
5
+ require 'rubygems/package'
6
+ require 'zlib'
7
+
8
+ require_relative '../repositories/igs'
9
+
10
+ module Inferno
11
+ module Entities
12
+ # IG is a wrapper class around the relevant concepts inside an IG.
13
+ # Not everything within an IG is currently used by Inferno.
14
+ class IG < Entity
15
+ ATTRIBUTES = [
16
+ :id,
17
+ :profiles,
18
+ :extensions,
19
+ :value_sets,
20
+ :search_params,
21
+ :examples
22
+ ].freeze
23
+
24
+ include Inferno::Entities::Attributes
25
+
26
+ def initialize(**params)
27
+ super(params, ATTRIBUTES)
28
+
29
+ @profiles = []
30
+ @extensions = []
31
+ @value_sets = []
32
+ @examples = []
33
+ @search_params = []
34
+ end
35
+
36
+ def self.from_file(ig_path)
37
+ raise "#{ig_path} does not exist" unless File.exist?(ig_path)
38
+
39
+ # fhir_models by default logs the entire content of non-FHIR files
40
+ # which could be things like a package.json
41
+ original_logger = FHIR.logger
42
+ FHIR.logger = Logger.new('/dev/null')
43
+
44
+ if File.directory?(ig_path)
45
+ from_directory(ig_path)
46
+ elsif ig_path.end_with? '.tgz'
47
+ from_tgz(ig_path)
48
+ else
49
+ raise "Unable to load #{ig_path} as it does not appear to be a directory or a .tgz file"
50
+ end
51
+ ensure
52
+ FHIR.logger = original_logger if defined? original_logger
53
+ end
54
+
55
+ def self.from_tgz(ig_path)
56
+ tar = Gem::Package::TarReader.new(
57
+ Zlib::GzipReader.open(ig_path)
58
+ )
59
+
60
+ ig = IG.new
61
+
62
+ tar.each do |entry|
63
+ next if skip_item?(entry.full_name, entry.directory?)
64
+
65
+ begin
66
+ resource = FHIR::Json.from_json(entry.read)
67
+ next if resource.nil?
68
+
69
+ ig.handle_resource(resource, entry.full_name)
70
+ rescue StandardError
71
+ next
72
+ end
73
+ end
74
+ ig
75
+ end
76
+
77
+ def self.from_directory(ig_directory)
78
+ ig = IG.new
79
+
80
+ ig_path = Pathname.new(ig_directory)
81
+ Dir.glob("#{ig_path}/**/*") do |f|
82
+ relative_path = Pathname.new(f).relative_path_from(ig_path).to_s
83
+ next if skip_item?(relative_path, File.directory?(f))
84
+
85
+ begin
86
+ resource = FHIR::Json.from_json(File.read(f))
87
+ next if resource.nil?
88
+
89
+ ig.handle_resource(resource, relative_path)
90
+ rescue StandardError
91
+ next
92
+ end
93
+ end
94
+ ig
95
+ end
96
+
97
+ # These files aren't FHIR resources
98
+ FILES_TO_SKIP = ['package.json', 'validation-summary.json'].freeze
99
+
100
+ def self.skip_item?(relative_path, is_directory)
101
+ return true if is_directory
102
+
103
+ file_name = relative_path.split('/').last
104
+
105
+ return true unless file_name.end_with? '.json'
106
+ return true unless relative_path.start_with? 'package/'
107
+
108
+ return true if file_name.start_with? '.' # ignore hidden files
109
+ return true if file_name.end_with? '.openapi.json'
110
+ return true if FILES_TO_SKIP.include? file_name
111
+
112
+ false
113
+ end
114
+
115
+ def handle_resource(resource, relative_path)
116
+ case resource.resourceType
117
+ when 'StructureDefinition'
118
+ if resource.type == 'Extension'
119
+ extensions.push resource
120
+ else
121
+ profiles.push resource
122
+ end
123
+ when 'ValueSet'
124
+ value_sets.push resource
125
+ when 'SearchParameter'
126
+ search_params.push resource
127
+ when 'ImplementationGuide'
128
+ @id = extract_package_id(resource)
129
+ else
130
+ examples.push(resource) if relative_path.start_with? 'package/example'
131
+ end
132
+ end
133
+
134
+ def extract_package_id(ig_resource)
135
+ "#{ig_resource.id}##{ig_resource.version || 'current'}"
136
+ end
137
+
138
+ # @private
139
+ def add_self_to_repository
140
+ repository.insert(self)
141
+ end
142
+
143
+ # @private
144
+ def repository
145
+ Inferno::Repositories::IGs.new
146
+ end
147
+ end
148
+ end
149
+ end
@@ -2,6 +2,7 @@ require_relative 'entities/attributes'
2
2
  require_relative 'entities/has_runnable'
3
3
  require_relative 'entities/entity'
4
4
  require_relative 'entities/header'
5
+ require_relative 'entities/ig'
5
6
  require_relative 'entities/message'
6
7
  require_relative 'entities/request'
7
8
  require_relative 'entities/result'