bio-basespace-sdk 0.1.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bio-basespace-sdk might be problematic. Click here for more details.

Files changed (65) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +11 -0
  4. data/Gemfile +16 -0
  5. data/License.txt +275 -0
  6. data/README.md +671 -0
  7. data/Rakefile +54 -0
  8. data/VERSION +1 -0
  9. data/examples/0_app_triggering.rb +135 -0
  10. data/examples/1_authentication.rb +156 -0
  11. data/examples/2_browsing.rb +84 -0
  12. data/examples/3_accessing_files.rb +129 -0
  13. data/examples/4_app_result_upload.rb +102 -0
  14. data/examples/5_purchasing.rb +119 -0
  15. data/lib/basespace.rb +126 -0
  16. data/lib/basespace/api/api_client.rb +313 -0
  17. data/lib/basespace/api/base_api.rb +242 -0
  18. data/lib/basespace/api/basespace_api.rb +789 -0
  19. data/lib/basespace/api/basespace_error.rb +80 -0
  20. data/lib/basespace/api/billing_api.rb +115 -0
  21. data/lib/basespace/model.rb +78 -0
  22. data/lib/basespace/model/app_result.rb +158 -0
  23. data/lib/basespace/model/app_result_response.rb +40 -0
  24. data/lib/basespace/model/app_session.rb +99 -0
  25. data/lib/basespace/model/app_session_compact.rb +43 -0
  26. data/lib/basespace/model/app_session_launch_object.rb +58 -0
  27. data/lib/basespace/model/app_session_response.rb +41 -0
  28. data/lib/basespace/model/application.rb +47 -0
  29. data/lib/basespace/model/application_compact.rb +44 -0
  30. data/lib/basespace/model/basespace_model.rb +60 -0
  31. data/lib/basespace/model/coverage.rb +48 -0
  32. data/lib/basespace/model/coverage_meta_response.rb +40 -0
  33. data/lib/basespace/model/coverage_metadata.rb +43 -0
  34. data/lib/basespace/model/coverage_response.rb +40 -0
  35. data/lib/basespace/model/file.rb +172 -0
  36. data/lib/basespace/model/file_response.rb +40 -0
  37. data/lib/basespace/model/genome_response.rb +40 -0
  38. data/lib/basespace/model/genome_v1.rb +56 -0
  39. data/lib/basespace/model/list_response.rb +53 -0
  40. data/lib/basespace/model/multipart_upload.rb +288 -0
  41. data/lib/basespace/model/product.rb +50 -0
  42. data/lib/basespace/model/project.rb +103 -0
  43. data/lib/basespace/model/project_response.rb +40 -0
  44. data/lib/basespace/model/purchase.rb +89 -0
  45. data/lib/basespace/model/purchase_response.rb +39 -0
  46. data/lib/basespace/model/purchased_product.rb +56 -0
  47. data/lib/basespace/model/query_parameters.rb +86 -0
  48. data/lib/basespace/model/query_parameters_purchased_product.rb +67 -0
  49. data/lib/basespace/model/refund_purchase_response.rb +40 -0
  50. data/lib/basespace/model/resource_list.rb +48 -0
  51. data/lib/basespace/model/response_status.rb +42 -0
  52. data/lib/basespace/model/run_compact.rb +55 -0
  53. data/lib/basespace/model/sample.rb +127 -0
  54. data/lib/basespace/model/sample_response.rb +40 -0
  55. data/lib/basespace/model/user.rb +80 -0
  56. data/lib/basespace/model/user_compact.rb +45 -0
  57. data/lib/basespace/model/user_response.rb +40 -0
  58. data/lib/basespace/model/variant.rb +57 -0
  59. data/lib/basespace/model/variant_header.rb +44 -0
  60. data/lib/basespace/model/variant_info.rb +48 -0
  61. data/lib/basespace/model/variants_header_response.rb +40 -0
  62. data/spec/basespaceapi_spec.rb +26 -0
  63. data/spec/basespaceerror_spec.rb +87 -0
  64. data/spec/basespacemodel_spec.rb +57 -0
  65. metadata +239 -0
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2013 Toshiaki Katayama, Joachim Baran
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ # Creating an AppResult and uploading files
17
+ # https://developer.basespace.illumina.com/docs/content/documentation/sdk-samples/python-sdk-overview#Creating_an_AppResult_and_uploading_files
18
+
19
+ require 'basespace'
20
+
21
+ include Bio::BaseSpace
22
+
23
+ # This script demonstrates how to create a new AppResults object, change its state
24
+ # and upload result files to it and download files from it.
25
+
26
+ opts = {
27
+ # FILL IN WITH YOUR APP VALUES HERE!
28
+ 'client_id' => '<your client key>',
29
+ 'client_secret' => '<your client secret>',
30
+ 'access_token' => '<your access token>',
31
+ 'app_session_id' => '<app session id>',
32
+ 'basespace_url' => 'https://api.basespace.illumina.com/',
33
+ 'api_version' => 'v1pre3',
34
+ }
35
+
36
+ # Test if client variables have been set.
37
+ unless opts.select{|k,v| v[/^<.*>$/]}.empty?
38
+ opts = Bio::BaseSpace.load_credentials
39
+ exit 1 unless opts
40
+ end
41
+
42
+ # First, create a client for making calls for this user session.
43
+ bs_api = BaseSpaceAPI.new(opts['client_id'], opts['client_secret'], opts['basespace_url'], opts['api_version'], opts['app_session_id'], opts['access_token'])
44
+
45
+ # Now we'll do some work of our own. First get a project to work on.
46
+ # We need write permission for the project we are working on,
47
+ # meaning we will need get a new token and instantiate a new BaseSpaceAPI.
48
+ prj = bs_api.get_project_by_id('89') # [TODO] Original ID '89' was not accessible. Writable project is needed.
49
+
50
+ # Assuming we have write access to the project
51
+ # we list the current App Results for the project.
52
+ statuses = ['Running']
53
+ app_res = prj.get_app_results(bs_api, {}, statuses) # [TODO] should introduce hash options / keyword arguments (in Ruby 2.0)
54
+ puts "The current running AppResults are #{app_res}"
55
+ puts
56
+
57
+ #
58
+ # Retrieving results and setting status
59
+ #
60
+
61
+ # To create an appResults for a project, simply give the name and description.
62
+ app_results = prj.create_app_result(bs_api, "testing", "this is my results")
63
+ puts "Some info about our new app results"
64
+ puts app_results
65
+ puts app_results.id
66
+ puts
67
+ puts "The app results also comes with a reference to our AppSession"
68
+ my_app_session = app_results.app_session
69
+ puts my_app_session
70
+ puts
71
+
72
+ # We can change the status of our AppSession and add a status-summary as follows.
73
+ my_app_session.set_status(bs_api, 'needsattention', "We worked hard, but encountered some trouble.")
74
+ puts "After a change of status of the app sessions we get #{my_app_session}"
75
+ puts
76
+ # We set our appSession back to running so we can do some more work.
77
+ my_app_session.set_status(bs_api, 'running', "Back on track")
78
+
79
+
80
+ # Let's list all AppResults again and see if our new object shows up.
81
+ app_res = prj.get_app_results(bs_api, {}, ['Running'])
82
+ puts "The updated app results are #{app_res}"
83
+ app_result2 = bs_api.get_app_result_by_id(app_results.id)
84
+ puts app_result2
85
+ puts
86
+
87
+ # Now we will make another AppResult and try to upload a file to it
88
+ app_results2 = prj.create_app_result(bs_api, "My second AppResult", "This one I will upload to")
89
+ app_results2.upload_file(bs_api, '/home/mkallberg/Desktop/testFile2.txt', 'BaseSpaceTestFile.txt', '/mydir/', 'text/plain')
90
+ puts "My AppResult number 2 #{app_results2}"
91
+ puts
92
+
93
+ # Let's see if our new file made it.
94
+ app_result_files = app_results2.get_files(bs_api)
95
+ puts "These are the files in the appResult"
96
+ puts app_result_files
97
+ f = app_result_files.last
98
+
99
+ # We can even download our newly uploaded file.
100
+ f = bs_api.get_file_by_id(f.id)
101
+ f.download_file(bs_api, '/home/mkallberg/Desktop/')
102
+
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2013 Toshiaki Katayama, Joachim Baran
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'basespace'
17
+
18
+ include Bio::BaseSpace
19
+
20
+ # This example demonstrates the billing methods of BaseSpace.
21
+ #
22
+ # Below a purchase is created, requiring the user to click 'Purchase' in a web
23
+ # browser. The purchase is then refunded, and the purchase is again retrieved
24
+ # via the API using the purchase id and tags, which are used by developers
25
+ # to help clarify exactly what was purchased.
26
+ #
27
+ # NOTE You will need to fill client values for your app below!
28
+
29
+ opts = {
30
+ # FILL IN WITH YOUR APP VALUES HERE!
31
+ 'client_id' => '<your client key>', # from dev portal app Credentials tab
32
+ 'client_secret' => '<your client secret>', # from dev portal app Credentials tab
33
+ 'access_token' => '<your access token>', # from oauth2
34
+ 'app_session_id' => '<app session id>', # from launching an app
35
+ 'basespace_url' => 'https://api.basespace.illumina.com/',
36
+ 'api_version' => 'v1pre3',
37
+ 'basespace_store_url' => 'https://hoth-store.basespace.illumina.com/',
38
+ 'product_id' => '', # from dev portal Pricing tab
39
+ }
40
+
41
+ # Test if client variables have been set.
42
+ unless opts.select{|k,v| v[/^<.*>$/]}.empty?
43
+ opts = Bio::BaseSpace.load_credentials
44
+ exit 1 unless opts
45
+ end
46
+
47
+ unless opts['client_id'] or opts['product_id']
48
+ raise "Please fill in client values (in the script) before running the script"
49
+ end
50
+
51
+ # First, create a client for making calls for this user session.
52
+ bill_api = BillingAPI.new(opts['basespace_store_url'], opts['api_version'], opts['app_session_id'], opts['access_token'])
53
+
54
+ # Create a non-consumable purchase.
55
+ #purch = bill_api.create_purchase([{'id':product_id,'quantity':4 }])
56
+
57
+ # Create a consumable purchase, and associated it with an AppSession
58
+ # also add tags to provide (fake) details about the purchase.
59
+ puts "Creating purchase"
60
+ # purch = billAPI.createPurchase({'id':product_id,'quantity':4, 'tags':["test","test_tag"] }, AppSessionId)
61
+ products = {
62
+ 'id' => opts['product_id'],
63
+ 'quantity' => 4,
64
+ 'tags' => ["test", "test_tag"],
65
+ }
66
+ purch = bill_api.create_purchase(products, opts['app_session_id'])
67
+
68
+ # Record the purchase Id and RefundSecret for refunding later.
69
+ purchase_id = purch.id
70
+ refund_secret = purch.refund_secret
71
+
72
+ puts "Now complete the purchase in your web browser"
73
+ puts "CLOSE the browser window/tab after you click 'Purchase' (and don't proceed into the app)"
74
+ time.sleep(3)
75
+ ## PAUSE HERE
76
+ link = purch.href_purchase_dialog
77
+ puts "Opening: #{link}"
78
+ host = RbConfig::CONFIG['host_os']
79
+ case host
80
+ when /mswin|mingw|cygwin/
81
+ system("start #{link}")
82
+ when /darwin/
83
+ system("open #{link}")
84
+ when /linux/
85
+ system("xdg-open #{link}")
86
+ end
87
+ puts "Waiting 30 seconds..."
88
+ time.sleep(30)
89
+ ## PAUSE HERE
90
+
91
+ puts "Confirm the purchase"
92
+ post_purch = bill_api.get_purchase_by_id(purchase_id)
93
+ puts "The status of the purchase is now: " + post_purch.status
94
+ puts
95
+
96
+ puts "Refunding the Purchase"
97
+ puts
98
+ # NOTE We must use the same access token that was provided used for the purchase.
99
+ refunded_purchase = bill_api.refund_purchase(purchase_id, refund_secret, 'the product did not function well as a frisbee')
100
+
101
+ puts "Getting all purchases for the current user with the tags we used for the purchase above"
102
+ puts
103
+ #purch_prods = bill_api.get_user_products
104
+ purch_prods = bill_api.get_user_products('current', {'Tags' => 'test,test_tag'})
105
+ if purch_prods.nil? or purch_prods.empty?
106
+ puts "Hmmm, didn't find any purchases with these tags. Did everything go OK above?"
107
+ else
108
+ puts "For the first of these purchases:"
109
+ puts "Purchase Name: #{purch_prods[0].name}"
110
+ puts "Purchase Price: #{purch_prods[0].price}"
111
+ puts "Purchase Quantity: #{purch_prods[0].quantity}"
112
+ puts "Tags: #{purch_prods[0].tags}"
113
+ # Get the refund status of the purchase
114
+ puts "Getting the (refunded) Purchase we just made"
115
+ get_purch = bill_api.get_purchase_by_id(purch_prods[0].purchase_id)
116
+ puts "Refund Status: #{get_purch.refund_status}"
117
+ end
118
+
119
+
@@ -0,0 +1,126 @@
1
+ # Copyright 2012-2013 Joachim Baran, Raoul Bonnal, Toshiaki Katayama, Francesco Strozzi
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+
14
+ # Still need to check [TODO] sections
15
+
16
+ require 'basespace/api/api_client'
17
+ require 'basespace/api/base_api'
18
+ require 'basespace/api/billing_api'
19
+ require 'basespace/api/basespace_api'
20
+ require 'basespace/api/basespace_error'
21
+
22
+ require 'basespace/model'
23
+ require 'basespace/model/app_result'
24
+ require 'basespace/model/app_result_response'
25
+ require 'basespace/model/app_session'
26
+ require 'basespace/model/app_session_compact'
27
+ require 'basespace/model/app_session_launch_object'
28
+ require 'basespace/model/app_session_response'
29
+ require 'basespace/model/application'
30
+ require 'basespace/model/application_compact'
31
+ require 'basespace/model/basespace_model'
32
+ require 'basespace/model/coverage'
33
+ require 'basespace/model/coverage_meta_response'
34
+ require 'basespace/model/coverage_metadata'
35
+ require 'basespace/model/coverage_response'
36
+ require 'basespace/model/file'
37
+ require 'basespace/model/file_response'
38
+ require 'basespace/model/genome_response'
39
+ require 'basespace/model/genome_v1'
40
+ require 'basespace/model/list_response'
41
+ #require 'basespace/model/multipart_upload'
42
+ require 'basespace/model/product'
43
+ require 'basespace/model/project'
44
+ require 'basespace/model/project_response'
45
+ require 'basespace/model/purchase'
46
+ require 'basespace/model/purchase_response'
47
+ require 'basespace/model/purchased_product'
48
+ require 'basespace/model/query_parameters'
49
+ require 'basespace/model/query_parameters_purchased_product'
50
+ require 'basespace/model/refund_purchase_response'
51
+ require 'basespace/model/resource_list'
52
+ require 'basespace/model/response_status'
53
+ require 'basespace/model/run_compact'
54
+ require 'basespace/model/sample'
55
+ require 'basespace/model/sample_response'
56
+ require 'basespace/model/user'
57
+ require 'basespace/model/user_compact'
58
+ require 'basespace/model/user_response'
59
+ require 'basespace/model/variant'
60
+ require 'basespace/model/variant_header'
61
+ require 'basespace/model/variant_info'
62
+ require 'basespace/model/variants_header_response'
63
+
64
+ require 'json'
65
+
66
+ module Bio
67
+
68
+ # BaseSpace Ruby SDK is to be used in the development of Apps and scripts
69
+ # for working with Illumina's BaseSpace cloud-computing solution for next-gen
70
+ # sequencing data analysis.
71
+ module BaseSpace
72
+
73
+ # Loads login and authentication credentials from a JSON file.
74
+ #
75
+ # If the environment variable "BASESPACE_CREDENTIALS" is set, then the
76
+ # path to the JSON files is taken from there. Otherwise, the current
77
+ # directory is searched for the file "credentials.json".
78
+ #
79
+ # On success, returns a hash with the values for
80
+ # * client_id
81
+ # * client_secret
82
+ # * access_token
83
+ # * app_session_id
84
+ # * basespace_url
85
+ # * api_version
86
+ #
87
+ # On failure, returns nil.
88
+ def self.load_credentials
89
+ filename = "credentials.json"
90
+ if ENV['BASESPACE_CREDENTIALS']
91
+ jsonfile = ENV['BASESPACE_CREDENTIALS']
92
+ else
93
+ jsonfile = ::File.join('.', filename)
94
+ end
95
+ if ::File.exists?(jsonfile)
96
+ hash = JSON.parse(::File.read(jsonfile))
97
+ if $DEBUG
98
+ $stderr.puts " # ----- Bio::BaseSpace.load_credientials ----- "
99
+ $stderr.puts " # Loaded credentials from #{jsonfile}"
100
+ $stderr.puts " # "
101
+ end
102
+ else
103
+ hash = nil
104
+ $stderr.puts " # ----- Bio::BaseSpace.load_credientials ----- "
105
+ $stderr.puts " # You can put your credentials for the BaseSpace in the"
106
+ $stderr.puts " # #{jsonfile}"
107
+ $stderr.puts " # file or point to the file with an environmental variable"
108
+ $stderr.puts " # export BASESPACE_CREDENTIALS=/path/to/your/#{filename}"
109
+ $stderr.puts " # in the following format:"
110
+ data = {
111
+ 'client_id' => '<your client id>',
112
+ 'client_secret' => '<your client secret>',
113
+ 'access_token' => '<your access token>',
114
+ 'app_session_id' => '<app session id>',
115
+ 'basespace_url' => 'https://api.basespace.illumina.com/',
116
+ 'api_version' => 'v1pre3',
117
+ }
118
+ $stderr.puts JSON.pretty_generate(JSON.parse(data.to_json))
119
+ end
120
+ return hash
121
+ end
122
+
123
+ end # BaseSpace
124
+ end # Bio
125
+
126
+
@@ -0,0 +1,313 @@
1
+ # Copyright 2012-2013 Joachim Baran, Toshiaki Katayama
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+
14
+ require 'basespace/api/basespace_error'
15
+
16
+ require 'net/https'
17
+ require 'uri'
18
+ require 'json'
19
+ require 'date'
20
+
21
+ Net::HTTP.version_1_2
22
+
23
+ module Bio
24
+ module BaseSpace
25
+
26
+ # This class provides wrapper methods to the BaseSpace API RESTful interface. It also
27
+ # handles serialization and deserialization of objects (Ruby to/from JSON). It is primarily
28
+ # used as a helper class for BaseSpaceAPI.
29
+ class APIClient
30
+ attr_accessor :api_key, :api_server, :timeout
31
+
32
+ # Create a new instance that will carry out REST calls.
33
+ #
34
+ # +access_token+:: Access token that is provided by App triggering.
35
+ # +api_server+:: URI of the BaseSpace API server.
36
+ # +timeout+:: Timeout for REST calls.
37
+ def initialize(access_token = nil, api_server = nil, timeout = 10)
38
+ if $DEBUG
39
+ $stderr.puts " # ----- BaseAPI#initialize ----- "
40
+ $stderr.puts " # caller: #{caller}"
41
+ $stderr.puts " # access_token: #{access_token}"
42
+ $stderr.puts " # api_server: #{api_server}"
43
+ $stderr.puts " # timeout: #{timeout}"
44
+ $stderr.puts " # "
45
+ end
46
+ raise UndefinedParameterError.new('AccessToken') unless access_token
47
+ @api_key = access_token
48
+ @api_server = api_server
49
+ @timeout = timeout
50
+ end
51
+
52
+ # POST data to a provided URI.
53
+ #
54
+ # +resource_path+:: URI to which the data should be POSTed.
55
+ # +post_data+:: Hash that contains the data.
56
+ # +headers+:: Header of the POST call.
57
+ # +data+:: (unused; TODO)
58
+ def force_post_call(resource_path, post_data, headers, data = nil)
59
+ # [TODO] Confirm whether we can expect those two parameters are Hash objects:
60
+ # headers = { "key" => "value" }
61
+ # post_data = { "key" => "value" }
62
+ uri = URI.parse(resource_path)
63
+ # If headers are not needed, the following line should be enough:
64
+ # return Net::HTTP.post_form(uri, post_data).body
65
+ http_opts = {}
66
+ if uri.scheme == "https"
67
+ http_opts[:use_ssl] = true
68
+ end
69
+ res = Net::HTTP.start(uri.host, uri.port, http_opts) { |http|
70
+ encoded_data = hash2urlencode(post_data)
71
+ http.post(uri.path, encoded_data, headers)
72
+ }
73
+ return res.body
74
+ end
75
+
76
+ # URL encode a Hash of data values.
77
+ #
78
+ # +hash+:: data encoded in a Hash.
79
+ def hash2urlencode(hash)
80
+ # URI.escape (alias URI.encode) is obsolete since Ruby 1.9.2.
81
+ #return hash.map{|k,v| URI.encode(k.to_s) + "=" + URI.encode(v.to_s)}.join("&")
82
+ return hash.map{|k,v| URI.encode_www_form_component(k.to_s) + "=" + URI.encode_www_form_component(v.to_s)}.join("&")
83
+ end
84
+
85
+ # Makes a PUT call to a given URI for depositing file contents.
86
+ #
87
+ # +resource_path+:: URI to which the data should be transferred.
88
+ # +post_data+:: (unused; TODO)
89
+ # +headers+:: Header of the PUT call.
90
+ # +trans_file+:: Path to the file that should be transferred.
91
+ def put_call(resource_path, post_data, headers, trans_file)
92
+ return %x(curl -H "x-access-token:#{@api_key}" -H "Content-MD5:#{headers['Content-MD5'].strip}" -T "#{trans_file}" -X PUT #{resource_path})
93
+ end
94
+
95
+ # Deserialize a boolean value to a Ruby object.
96
+ #
97
+ # +value+:: serialized representation of the boolean value.
98
+ def bool(value)
99
+ case value
100
+ when nil, false, 0, 'nil', 'false', '0', 'None'
101
+ result = false
102
+ else
103
+ result = true
104
+ end
105
+ return result
106
+ end
107
+
108
+ # Carries out a RESTful operation on the BaseSpace API.
109
+ #
110
+ # TODO Need check. Logic in this method is rather complicated...
111
+ #
112
+ # +resource_path+:: URI that should be used for the API call.
113
+ # +method+:: HTTP method for the rest call (GET, POST, DELETE, etc.)
114
+ # +query_params+:: query parameters that should be sent along to the API.
115
+ # +post_data+:: Hash that contains data to be transferred.
116
+ # +header_params+:: Additional settings that should be transferred in the HTTP header.
117
+ # +force_post+:: Truth value that indicates whether a POST should be forced.
118
+ def call_api(resource_path, method, query_params, post_data, header_params = nil, force_post = false)
119
+ url = @api_server + resource_path
120
+
121
+ headers = header_params.dup
122
+ headers['Content-Type'] = 'application/json' if not headers.has_key?('Content-Type') and not method == 'PUT'
123
+ # include access token in header
124
+ headers['Authorization'] = "Bearer #{@api_key}"
125
+
126
+ uri = request = response = data = cgi_params = nil
127
+
128
+ if query_params
129
+ # Need to remove None (in Python, nil in Ruby) values, these should not be sent
130
+ sent_query_params = {}
131
+ query_params.each do |param, value|
132
+ sent_query_params[param] = value if bool(value)
133
+ end
134
+ cgi_params = hash2urlencode(sent_query_params)
135
+ end
136
+
137
+ if $DEBUG
138
+ $stderr.puts " # ----- APIClient#call_api ----- "
139
+ $stderr.puts " # caller: #{caller}"
140
+ $stderr.puts " # url: #{url}"
141
+ $stderr.puts " # method: #{method}"
142
+ $stderr.puts " # headers: #{headers}"
143
+ $stderr.puts " # cgi_params: #{cgi_params}"
144
+ $stderr.puts " # post_data: #{post_data}"
145
+ $stderr.puts " # "
146
+ end
147
+
148
+ case method
149
+ when 'GET'
150
+ if cgi_params
151
+ url += "?#{cgi_params}"
152
+ end
153
+ # [TODO] confirm this works or not
154
+ #request = urllib2.Request(url, headers)
155
+ uri = URI.parse(url)
156
+ request = Net::HTTP::Get.new(uri.path, headers)
157
+ when 'POST', 'PUT', 'DELETE'
158
+ if cgi_params
159
+ force_post_url = url
160
+ url += "?#{cgi_params}"
161
+ end
162
+ if post_data
163
+ # [TODO] Do we need to skip String, Integer, Float and bool in Ruby?
164
+ data = post_data.to_json # if not [str, int, float, bool].include?(type(post_data))
165
+ end
166
+ if force_post
167
+ response = force_post_call(force_post_url, sent_query_params, headers)
168
+ else
169
+ data = '\n' if data and data.empty? # temp fix, in case is no data in the file, to prevent post request from failing
170
+ # [TODO] confirm this works or not
171
+ #request = urllib2.Request(url, headers, data)#, @timeout)
172
+ uri = URI.parse(url)
173
+ request = Net::HTTP::Post.new(uri.path, headers)
174
+ end
175
+ if ['PUT', 'DELETE'].include?(method) # urllib doesnt do put and delete, default to pycurl here
176
+ response = put_call(url, query_params, headers, data)
177
+ response = response.split.last
178
+ end
179
+ else
180
+ raise "Method #{method} is not recognized."
181
+ end
182
+
183
+ # Make the request, request may raise 403 forbidden, or 404 non-response
184
+ if not force_post and not ['PUT', 'DELETE'].include?(method) # the normal case
185
+ # puts url
186
+ # puts request
187
+ # puts "request with timeout=#{@timeout}"
188
+ # [TODO] confirm this works or not
189
+ #response = urllib2.urlopen(request, @timeout).read()
190
+ http_opts = {}
191
+ if uri.scheme == "https"
192
+ http_opts[:use_ssl] = true
193
+ end
194
+ response = Net::HTTP.start(uri.host, uri.port, http_opts) { |http|
195
+ http.request(request)
196
+ }
197
+ end
198
+
199
+ begin
200
+ data = JSON.parse(response.body)
201
+ rescue => err
202
+ $stderr.puts " # ----- APIClient#call_api ----- "
203
+ $stderr.puts " # Error: #{err}"
204
+ $stderr.puts " # "
205
+ data = nil
206
+ end
207
+ return data
208
+ end
209
+
210
+ # Serialize a list to a CSV string, if necessary.
211
+ #
212
+ # +obj+:: Data object to be serialized.
213
+ def to_path_value(obj)
214
+ if obj.kind_of?(Array)
215
+ return obj.join(',')
216
+ else
217
+ return obj
218
+ end
219
+ end
220
+
221
+ # Deserialize a JSON string into an object.
222
+ #
223
+ # +obj+:: String or object to be deserialized.
224
+ # +obj_class+:: Class literal for deserialzied object, or string of class name.
225
+ def deserialize(obj, obj_class)
226
+ case obj_class.downcase
227
+ when 'str'
228
+ return obj.to_s
229
+ when 'int'
230
+ return obj.to_i
231
+ when 'float'
232
+ return obj.to_f
233
+ when 'bool'
234
+ return bool(obj)
235
+ when 'file'
236
+ # Bio::BaseSpace::File
237
+ instance = File.new
238
+ else
239
+ # models in BaseSpace
240
+ klass = Object.const_get(obj_class)
241
+ instance = klass.new
242
+ end
243
+
244
+ if $DEBUG
245
+ $stderr.puts " # ----- APIClient#deserialize ----- "
246
+ $stderr.puts " # caller: #{caller}"
247
+ $stderr.puts " # obj_class: #{obj_class}"
248
+ $stderr.puts " # obj: #{obj}" # JSON.pretty_generate(obj)
249
+ $stderr.puts " # "
250
+ end
251
+
252
+ instance.swagger_types.each do |attr, attr_type|
253
+ if obj.has_key?(attr) or obj.has_key?(attr.to_s)
254
+ if $DEBUG
255
+ $stderr.puts " # # ----- APIClient#deserialize/swagger_types ----- "
256
+ $stderr.puts " # # attr: #{attr}"
257
+ $stderr.puts " # # attr_type: #{attr_type}"
258
+ $stderr.puts " # # value: #{obj[attr]}"
259
+ $stderr.puts " # # "
260
+ end
261
+ value = obj[attr]
262
+ case attr_type.downcase
263
+ when 'str'
264
+ instance.set_attr(attr, value.to_s)
265
+ when 'int'
266
+ instance.set_attr(attr, value.to_i)
267
+ when 'float'
268
+ instance.set_attr(attr, value.to_f)
269
+ when 'datetime'
270
+ instance.set_attr(attr, DateTime.parse(value))
271
+ when 'bool'
272
+ instance.set_attr(attr, bool(value))
273
+ when /list</
274
+ sub_class = attr_type[/list<(.*)>/, 1]
275
+ sub_values = []
276
+ value.each do |sub_value|
277
+ sub_values << deserialize(sub_value, sub_class)
278
+ end
279
+ instance.set_attr(attr, sub_values)
280
+ when 'dict' # support for parsing dictionary
281
+ if $DEBUG
282
+ $stderr.puts " # # # ----- APIClient#deserialize/swagger_types/dict ----- "
283
+ $stderr.puts " # # # dict: #{value}"
284
+ $stderr.puts " # # # "
285
+ end
286
+ # [TODO] May need to convert value -> Hash (check in what format the value is passed)
287
+ instance.set_attr(attr, value)
288
+ else
289
+ if $DEBUG
290
+ # print "recursive call w/ " + attrType
291
+ $stderr.puts " # # # ----- APIClient#deserialize/swagger_types/recursive call ----- "
292
+ $stderr.puts " # # # attr: #{attr}"
293
+ $stderr.puts " # # # attr_type: #{attr_type}"
294
+ $stderr.puts " # # # value: #{value}"
295
+ $stderr.puts " # # # "
296
+ end
297
+ instance.set_attr(attr, deserialize(value, attr_type))
298
+ end
299
+ end
300
+ end
301
+ if $DEBUG
302
+ $stderr.puts " # # ----- APIClient#deserialize/instance ----- "
303
+ $stderr.puts " # # instance: #{instance.attributes.inspect}"
304
+ $stderr.puts " # # "
305
+ end
306
+ return instance
307
+ end
308
+
309
+ end
310
+
311
+ end # module BaseSpace
312
+ end # module Bio
313
+