fhir_client 1.0.2 → 1.6.0

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
  SHA1:
3
- metadata.gz: 7e798b19840921ad0695ecacbb3dcd0d7f662da9
4
- data.tar.gz: c176b2138418157c1fc357c4c1fd18c335625692
3
+ metadata.gz: d0b559d338d7f9f46f075f1b81519fedaf482ffe
4
+ data.tar.gz: 5dae2a7c67ee80258a9c56c5c88179dab7dbe44e
5
5
  SHA512:
6
- metadata.gz: f05664d0b45e1657d7147069ef1d04c59af7b722e0a9f043729ca66e8af4a58df9d822f4ca4f01c13dfc99a97cfedb418057b94531eaf608858db1ed6de2991f
7
- data.tar.gz: 8417ee48735581a8bb2daef931af22bb0309e261dd163cabd6be225bfb4fbc61a6e10f33520d099581b2efe1fdfbfe6a5fc5bc908cc79772052d2623d7029eea
6
+ metadata.gz: eb511574de6b71e63af45ac89b6fb282ccdd1136b1934d24e68885afd3b9a29a4791beefde800c645dbb1de47de640ac50219f8d6773c7fba39905e46b02723a
7
+ data.tar.gz: b70ac6d8e90671845411f85af80db521174b33d5a8f5e8c1989a7d9c1eba50eb56f7849e8d65031b6095b3ef2abbb5623da1a9343c8579e7922726674ba248bd
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fhir_client (1.0.2)
4
+ fhir_client (1.6.0)
5
5
  activesupport (>= 3)
6
6
  addressable (>= 2.3)
7
- fhir_models (>= 0.3.1)
7
+ fhir_models (>= 1.6.0)
8
8
  oauth2 (~> 1.1)
9
9
  rest-client (~> 1.8)
10
10
  tilt (>= 1.1)
@@ -26,11 +26,11 @@ GEM
26
26
  coderay (1.1.1)
27
27
  date_time_precision (0.8.1)
28
28
  docile (1.1.5)
29
- domain_name (0.5.20160310)
29
+ domain_name (0.5.20160615)
30
30
  unf (>= 0.0.5, < 1.0.0)
31
31
  faraday (0.9.2)
32
32
  multipart-post (>= 1.2, < 3)
33
- fhir_models (0.3.1)
33
+ fhir_models (1.6.0)
34
34
  bcp47 (>= 0.3)
35
35
  date_time_precision (>= 0.8)
36
36
  mime-types (>= 1.16, < 3)
@@ -40,7 +40,7 @@ GEM
40
40
  domain_name (~> 0.5)
41
41
  i18n (0.7.0)
42
42
  json (1.8.2)
43
- jwt (1.5.1)
43
+ jwt (1.5.4)
44
44
  method_source (0.8.2)
45
45
  mime-types (2.99.2)
46
46
  mini_portile2 (2.1.0)
@@ -52,9 +52,9 @@ GEM
52
52
  nokogiri (1.6.8)
53
53
  mini_portile2 (~> 2.1.0)
54
54
  pkg-config (~> 1.1.7)
55
- oauth2 (1.1.0)
55
+ oauth2 (1.2.0)
56
56
  faraday (>= 0.8, < 0.10)
57
- jwt (~> 1.0, < 1.5.2)
57
+ jwt (~> 1.0)
58
58
  multi_json (~> 1.3)
59
59
  multi_xml (~> 0.5)
60
60
  rack (>= 1.2, < 3)
@@ -64,7 +64,7 @@ GEM
64
64
  method_source (~> 0.8.1)
65
65
  slop (~> 3.4)
66
66
  rack (1.6.4)
67
- rake (11.1.2)
67
+ rake (11.2.2)
68
68
  rest-client (1.8.0)
69
69
  http-cookie (>= 1.0.2, < 2.0)
70
70
  mime-types (>= 1.16, < 3.0)
data/README.md CHANGED
@@ -11,35 +11,50 @@ Supports:
11
11
  * Operations (e.g. `$everything`, `$validate`)
12
12
  * Support for OAuth2
13
13
 
14
- ### Getting Started
14
+ ## Getting Started
15
15
 
16
16
  $ bundle install
17
17
  $ bundle exec rake fhir:console
18
18
 
19
- ### Creating a Client
19
+ ## Creating a Client
20
20
  ```ruby
21
21
  client = FHIR::Client.new(url)
22
22
  ```
23
23
 
24
- ### Searching
24
+ This client supports two modes of operation: basic and advanced. The basic mode is useful for simple operations
25
+ because it promotes an ActiveRecord-like style of interaction. The advanced mode is less developer-friendly, but is currently necessary if you would like to use the entire range of operations exposed by FHIR.
26
+
27
+ ## Basic Usage
28
+
29
+ Associate the client with the model:
30
+
25
31
  ```ruby
26
- reply = client.search(FHIR::Patient, search: {parameters: {name: 'P'}})
27
- bundle = reply.resource
28
- patient = bundle.entry.first.resource
32
+ FHIR::Model.client = client
29
33
  ```
30
34
 
31
- ### Fetching a Bundle
35
+ The FHIR models can now be used to directly interact with a FHIR server.
36
+
32
37
  ```ruby
33
- reply = client.read_feed(FHIR::Patient) # fetch Bundle of Patients
34
- bundle = reply.resource
35
- bundle.entry.each do |entry|
36
- patient = entry.resource
37
- puts patient.name[0].text
38
- end
39
- puts reply.code # HTTP 200 (or whatever was returned)
40
- puts reply.body # Raw XML or JSON
38
+ # read an existing patient with an ID of 'example'
39
+ patient = FHIR::Patient.read('example')
40
+
41
+ # update a patient
42
+ patient.gender = 'female'
43
+ patient.update # saves the patient
44
+
45
+ # create a patient
46
+ patient = FHIR::Patient.create(name: {given: 'John', family: 'Doe'})
47
+
48
+ # search patients
49
+ results = FHIR::Patient.search(given: 'John', family: 'Doe')
50
+ results.count # results in an enumeration
51
+
52
+ # delete the recently created patient
53
+ patient.destroy
41
54
  ```
42
55
 
56
+ ## Advanced Usage
57
+
43
58
  ### CRUD Examples
44
59
  ```ruby
45
60
  # read an existing patient with id "example"
@@ -73,6 +88,25 @@ client.conditional_create(patient, ifNoneExist)
73
88
  client.destroy(FHIR::Patient, patient_id)
74
89
  ```
75
90
 
91
+ ### Searching
92
+ ```ruby
93
+ reply = client.search(FHIR::Patient, search: {parameters: {name: 'P'}})
94
+ bundle = reply.resource
95
+ patient = bundle.entry.first.resource
96
+ ```
97
+
98
+ ### Fetching a Bundle
99
+ ```ruby
100
+ reply = client.read_feed(FHIR::Patient) # fetch Bundle of Patients
101
+ bundle = reply.resource
102
+ bundle.entry.each do |entry|
103
+ patient = entry.resource
104
+ puts patient.name[0].text
105
+ end
106
+ puts reply.code # HTTP 200 (or whatever was returned)
107
+ puts reply.body # Raw XML or JSON
108
+ ```
109
+
76
110
  ### Transactions
77
111
  ```ruby
78
112
  # Create a patient
data/fhir_client.gemspec CHANGED
@@ -7,11 +7,11 @@ Gem::Specification.new do |s|
7
7
  s.email = "aquina@mitre.org"
8
8
  s.homepage = "https://github.com/hl7-fhir/fhir-svn"
9
9
  s.authors = ["Andre Quina", "Jason Walonoski", "Janoo Fernandes"]
10
- s.version = '1.0.2'
10
+ s.version = '1.6.0'
11
11
 
12
12
  s.files = s.files = `git ls-files`.split("\n")
13
13
 
14
- s.add_dependency 'fhir_models', '>= 0.3.1'
14
+ s.add_dependency 'fhir_models', '>= 1.6.0'
15
15
  s.add_dependency 'tilt', '>= 1.1'
16
16
  s.add_dependency 'rest-client', '~> 1.8'
17
17
  s.add_dependency 'oauth2', '~> 1.1'
@@ -0,0 +1,10 @@
1
+ class ClientException < Exception
2
+
3
+ attr_accessor :reply
4
+
5
+ def initialize(message, reply = nil)
6
+ super(message)
7
+ @reply = reply
8
+ end
9
+
10
+ end
@@ -196,25 +196,20 @@ module FHIR
196
196
 
197
197
  def fhir_headers(options={})
198
198
  FHIR::ResourceAddress.new.fhir_headers(options, @use_format_param)
199
- end
199
+ end
200
200
 
201
201
  def parse_reply(klass, format, response)
202
202
  $LOG.info "Parsing response with {klass: #{klass}, format: #{format}, code: #{response.code}}."
203
203
  return nil if ![200,201].include? response.code
204
204
  res = nil
205
205
  begin
206
- res = nil
207
- if(format.downcase.include?('xml'))
208
- res = FHIR::Xml.from_xml(response.body)
209
- else
210
- res = FHIR::Json.from_json(response.body)
211
- end
206
+ res = FHIR.from_contents(response.body)
207
+ res.client = self if !res.nil?
212
208
  $LOG.warn "Expected #{klass} but got #{res.class}" if res.class!=klass
213
209
  rescue Exception => e
214
210
  $LOG.error "Failed to parse #{format} as resource #{klass}: #{e.message} %n #{e.backtrace.join("\n")} #{response}"
215
211
  nil
216
212
  end
217
- res.client = self
218
213
  res
219
214
  end
220
215
 
@@ -226,7 +221,7 @@ module FHIR
226
221
  if [:get, :delete, :head].include?(request['method'])
227
222
  method(request['method']).call(request['url'], request['headers'])
228
223
  elsif [:post, :put].include?(request['method'])
229
- resource = request['headers']['resource'].constantize.from_xml(request['payload'])
224
+ resource = FHIR.from_contents(request['payload']) unless request['payload'].nil?
230
225
  method(request['method']).call(request['url'], resource, request['headers'])
231
226
  end
232
227
  end
@@ -295,7 +290,7 @@ module FHIR
295
290
 
296
291
  def get(path, headers)
297
292
  url = URI(build_url(path)).to_s
298
- puts "GETTING: #{url}"
293
+ $LOG.info "GETTING: #{url}"
299
294
  headers = clean_headers(headers)
300
295
  if @use_oauth2_auth
301
296
  # @client.refresh!
@@ -320,22 +315,28 @@ module FHIR
320
315
  @reply = FHIR::ClientReply.new(req, res)
321
316
  else
322
317
  headers.merge!(@security_headers) if @use_basic_auth
323
- @client.get(url, headers){ |response, request, result|
324
- $LOG.info "GET - Request: #{request.to_json}, Response: #{response.force_encoding("UTF-8")}"
325
- request.args[:path] = url.gsub(@baseServiceUrl,'')
326
- res = {
327
- :code => result.code,
328
- :headers => scrubbed_response_headers(result.each_key{}),
329
- :body => response
330
- }
331
- @reply = FHIR::ClientReply.new(request.args, res)
318
+ begin
319
+ response = @client.get(url, headers)
320
+ rescue Exception => e
321
+ response = e.response if e.response
322
+ end
323
+
324
+ $LOG.info "GET - Request: #{response.request.to_json}, Response: #{response.body.force_encoding("UTF-8")}"
325
+ response.request.args[:path] = response.request.args[:url].gsub(@baseServiceUrl,'')
326
+ headers = response.headers.inject({}){ |h,(k,v)| h[k.to_s.gsub('_','-')] = v.to_s; h}
327
+ res = {
328
+ :code => response.code,
329
+ :headers => scrubbed_response_headers(headers),
330
+ :body => response.body
332
331
  }
332
+
333
+ @reply = FHIR::ClientReply.new(response.request.args, res)
333
334
  end
334
335
  end
335
336
 
336
337
  def post(path, resource, headers)
337
338
  url = URI(build_url(path)).to_s
338
- puts "POSTING: #{url}"
339
+ $LOG.info "POSTING: #{url}"
339
340
  headers = clean_headers(headers)
340
341
  payload = request_payload(resource, headers) if resource
341
342
  if @use_oauth2_auth
@@ -376,7 +377,7 @@ module FHIR
376
377
 
377
378
  def put(path, resource, headers)
378
379
  url = URI(build_url(path)).to_s
379
- puts "PUTTING: #{url}"
380
+ $LOG.info "PUTTING: #{url}"
380
381
  headers = clean_headers(headers)
381
382
  payload = request_payload(resource, headers) if resource
382
383
  if @use_oauth2_auth
@@ -417,7 +418,7 @@ module FHIR
417
418
 
418
419
  def patch(path, patchset, headers)
419
420
  url = URI(build_url(path)).to_s
420
- puts "PATCHING: #{url}"
421
+ $LOG.info "PATCHING: #{url}"
421
422
  headers = clean_headers(headers)
422
423
  payload = request_patch_payload(patchset, headers['format'])
423
424
  if @use_oauth2_auth
@@ -459,7 +460,7 @@ module FHIR
459
460
 
460
461
  def delete(path, headers)
461
462
  url = URI(build_url(path)).to_s
462
- puts "DELETING: #{url}"
463
+ $LOG.info "DELETING: #{url}"
463
464
  headers = clean_headers(headers)
464
465
  if @use_oauth2_auth
465
466
  # @client.refresh!
@@ -500,7 +501,7 @@ module FHIR
500
501
  def head(path, headers)
501
502
  headers.merge!(@security_headers) unless @security_headers.blank?
502
503
  url = URI(build_url(path)).to_s
503
- puts "HEADING: #{url}"
504
+ $LOG.info "HEADING: #{url}"
504
505
  RestClient.head(url, headers){ |response, request, result|
505
506
  $LOG.info "HEAD - Request: #{request.to_json}, Response: #{response.force_encoding("UTF-8")}"
506
507
  request.args[:path] = url.gsub(@baseServiceUrl,'')
data/lib/ext/model.rb CHANGED
@@ -22,46 +22,85 @@ module FHIR
22
22
  end
23
23
 
24
24
  def self.read(id, client = self.client)
25
- client.read(self, id).resource
25
+ handle_response client.read(self, id)
26
26
  end
27
27
 
28
28
  def self.read_with_summary(id, summary, client = self.client)
29
- client.read(self, id, client.default_format, summary).resource
29
+ handle_response client.read(self, id, client.default_format, summary)
30
+ end
31
+
32
+ def self.vread(id, version_id, client = self.client)
33
+ handle_response client.vread(self, id, version_id)
34
+ end
35
+
36
+ def self.resource_history(client = self.client)
37
+ handle_response client.resource_history(self)
38
+ end
39
+
40
+ def self.resource_history_as_of(last_update)
41
+ handle_response client.resource_history_as_of(self, last_update)
42
+ end
43
+
44
+ def self.resource_instance_history(id, client = self.client)
45
+ handle_response client.resource_instance_history(self, id)
46
+ end
47
+
48
+ def self.resource_instance_history_as_of(id, last_update, client = self.client)
49
+ handle_response client.resource_instance_history_as_of(self, id, last_update)
30
50
  end
31
51
 
32
52
  def self.search(params = {}, client = self.client)
33
- client.search(self, search: { parameters: params }).resource
53
+ handle_response client.search(self, search: { parameters: params })
34
54
  end
35
55
 
36
56
  def self.create(model, client = self.client)
37
57
  model = new(model) unless model.is_a?(self)
38
- client.create(model).resource
58
+ handle_response client.create(model)
39
59
  end
40
60
 
41
61
  def self.conditional_create(model, params, client = self.client)
42
62
  model = new(model) unless model.is_a?(self)
43
- client.conditional_create(model, params)
63
+ handle_response client.conditional_create(model, params)
64
+ end
65
+
66
+ def self.all
67
+ handle_response client.read_feed(self)
68
+ end
69
+
70
+ def vread(version_id)
71
+ self.class.vread(id, version_id, client)
44
72
  end
45
73
 
46
74
  def create
47
- client.create(self).resource
75
+ handle_response client.create(self)
48
76
  end
49
77
 
50
78
  def conditional_create(params)
51
- client.conditional_create(self, params)
79
+ handle_response client.conditional_create(self, params)
52
80
  end
53
81
 
54
82
  def update
55
- client.update(self, id).resource
83
+ handle_response client.update(self, id)
56
84
  end
57
85
 
58
86
  def conditional_update(params)
59
- client.conditional_update(self, self.id, params).resource
87
+ handle_response client.conditional_update(self, self.id, params)
60
88
  end
61
89
 
62
90
  def destroy
63
- client.destroy(self.class, id) unless id.nil?
91
+ handle_response client.destroy(self.class, id) unless id.nil?
64
92
  nil
65
93
  end
94
+
95
+ private
96
+
97
+ def self.handle_response(response)
98
+ raise ClientException.new "Server returned #{response.code}.", response if response.code.between?(400,599)
99
+ response.resource
100
+ end
101
+
102
+ def handle_response(response)
103
+ self.class.handle_response(response)
104
+ end
66
105
  end
67
106
  end
data/lib/ext/reference.rb CHANGED
@@ -5,7 +5,7 @@ module FHIR
5
5
  type, id = reference.to_s.split("/")
6
6
  return unless [type, id].all?(&:present?)
7
7
  klass = "FHIR::#{type}".constantize
8
- klass.read(client, id)
8
+ klass.read(id, client)
9
9
  end
10
10
  end
11
11
  end
data/lib/fhir_client.rb CHANGED
@@ -28,4 +28,4 @@ require_relative File.join('.','feed_format.rb')
28
28
  require_relative File.join('.','patch_format.rb')
29
29
  require_relative File.join('.','model','client_reply.rb')
30
30
  require_relative File.join('.','model','tag.rb')
31
-
31
+ require_relative File.join('.','client_exception.rb')
@@ -70,6 +70,8 @@ module FHIR
70
70
  url += "/$lookup"
71
71
  elsif (opr && opr[:name]== :concept_map_translate)
72
72
  url += "/$translate"
73
+ elsif (opr && opr[:name]== :closure_table_maintenance)
74
+ url += "/$closure"
73
75
  end
74
76
  end
75
77
 
@@ -77,13 +77,20 @@ module FHIR
77
77
  terminology_operation(options, format)
78
78
  end
79
79
 
80
- #
80
+ # ConceptMap Translation
81
81
  def concept_map_translate(params={}, format=@default_format)
82
82
  options = { resource: FHIR::ConceptMap, operation: { name: :concept_map_translate } }
83
83
  options.deep_merge!(params)
84
84
  terminology_operation(options, format)
85
85
  end
86
86
 
87
+ # ConceptMap Closure Table Maintenance
88
+ def closure_table_maintenance(params={}, format=@default_format)
89
+ options = { operation: { name: :closure_table_maintenance } }
90
+ options.deep_merge!(params)
91
+ terminology_operation(options, format)
92
+ end
93
+
87
94
  def terminology_operation(params={}, format=@default_format)
88
95
  options = { format: format }
89
96
  # params = [id, code, system, version, display, coding, codeableConcept, date, abstract]
data/lib/tasks/tasks.rake CHANGED
@@ -36,12 +36,15 @@ namespace :fhir do
36
36
  end
37
37
 
38
38
  desc 'count all resources for a given server'
39
- task :count, [:url] do |t, args|
39
+ task :count, [:url,:display_zero] do |t, args|
40
40
  client = FHIR::Client.new(args.url)
41
+ display_zero = (args.display_zero == 'true')
41
42
  counts = {}
42
- fhir_resources.map do | klass |
43
+ fhir_resources.each do | klass |
43
44
  reply = client.read_feed(klass)
44
- counts["#{klass.name.demodulize}"] = reply.resource.total unless reply.resource.nil?
45
+ if !reply.resource.nil? && (reply.resource.total > 0 || display_zero)
46
+ counts["#{klass.name.demodulize}"] = reply.resource.total
47
+ end
45
48
  end
46
49
  printf " %-30s %5s\n", 'Resource', 'Count'
47
50
  printf " %-30s %5s\n", '--------', '-----'
@@ -54,7 +57,7 @@ namespace :fhir do
54
57
  desc 'delete all resources for a given server'
55
58
  task :clean, [:url] do |t, args|
56
59
  client = FHIR::Client.new(args.url)
57
- fhir_resources.map do | klass |
60
+ fhir_resources.each do | klass |
58
61
  reply = client.read_feed(klass)
59
62
  while !reply.nil? && !reply.resource.nil? && reply.resource.total > 0
60
63
  reply.resource.entry.each do |entry|
@@ -67,7 +70,7 @@ namespace :fhir do
67
70
  end
68
71
 
69
72
  def fhir_resources
70
- Mongoid.models.select {|c| c.name.include?('FHIR') && !c.included_modules.find_index(FHIR::Resource).nil?}
73
+ FHIR::RESOURCES.map {|r| Object::const_get("FHIR::#{r}")}
71
74
  end
72
75
 
73
76
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fhir_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andre Quina
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-06-10 00:00:00.000000000 Z
13
+ date: 2016-08-12 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: fhir_models
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.3.1
21
+ version: 1.6.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - '>='
27
27
  - !ruby/object:Gem::Version
28
- version: 0.3.1
28
+ version: 1.6.0
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: tilt
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -124,6 +124,7 @@ files:
124
124
  - README.md
125
125
  - Rakefile
126
126
  - fhir_client.gemspec
127
+ - lib/client_exception.rb
127
128
  - lib/client_interface.rb
128
129
  - lib/ext/bundle.rb
129
130
  - lib/ext/model.rb
@@ -172,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
173
  version: '0'
173
174
  requirements: []
174
175
  rubyforge_project:
175
- rubygems_version: 2.4.6
176
+ rubygems_version: 2.0.14.1
176
177
  signing_key:
177
178
  specification_version: 4
178
179
  summary: A Gem for handling FHIR client requests in ruby