bio-basespace-sdk 0.1.2

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.

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
+