opentox-client 0.0.1pre → 0.0.2pre
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.
- data/README.markdown +5 -0
- data/lib/authorization.rb +55 -79
- data/lib/dataset.rb +17 -306
- data/lib/error.rb +23 -12
- data/lib/opentox-client.rb +5 -2
- data/lib/opentox.rb +27 -15
- data/lib/overwrite.rb +10 -22
- data/lib/policy.rb +204 -127
- data/lib/rest-client-wrapper.rb +14 -7
- data/lib/task.rb +22 -31
- data/opentox-client.gemspec +5 -1
- data/test/authorization.rb +107 -0
- data/test/dataset.rb +60 -14
- data/test/feature.rb +2 -2
- data/test/policy.rb +120 -0
- data/test/task.rb +5 -5
- metadata +19 -15
data/README.markdown
CHANGED
data/lib/authorization.rb
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
module OpenTox
|
2
|
-
|
2
|
+
AA = $aa[:uri] if defined? $aa
|
3
|
+
AA ||= "https://opensso.in-silico.ch" #if not set in .opentox/conf/[application]/[test].rb
|
3
4
|
#Module for Authorization and Authentication
|
4
5
|
#@example Authentication
|
5
6
|
# require "opentox-client"
|
6
|
-
# OpenTox::Authorization::
|
7
|
-
# token = OpenTox::Authorization.authenticate("
|
7
|
+
# OpenTox::Authorization::AA = "https://opensso.in-silico.ch" #if not set in .opentox/conf/[environment].yaml
|
8
|
+
# token = OpenTox::Authorization.authenticate("username", "password")
|
8
9
|
#@see http://www.opentox.org/dev/apis/api-1.2/AA OpenTox A&A API 1.2 specification
|
9
10
|
|
10
11
|
module Authorization
|
11
12
|
|
12
|
-
#Helper Class
|
13
|
+
#Helper Class to create and send default policies out of xml templates
|
13
14
|
#@example Creating a default policy to a URI
|
14
15
|
# aa=OpenTox::Authorization::AA.new(tok)
|
15
16
|
# xml=aa.get_xml('http://uri....')
|
16
17
|
# OpenTox::Authorization.create_policy(xml,tok)
|
17
18
|
|
18
|
-
class
|
19
|
+
class Helper
|
19
20
|
attr_accessor :user, :subjectid, :policy
|
20
21
|
|
21
22
|
#Generates AA object - requires subjectid
|
@@ -41,27 +42,27 @@ module OpenTox
|
|
41
42
|
xml = get_xml(uri)
|
42
43
|
ret = false
|
43
44
|
ret = Authorization.create_policy(xml, @subjectid)
|
44
|
-
|
45
|
-
|
45
|
+
$logger.warn "Create policy on openSSO failed for URI: #{uri} subjectid: #{@subjectid}. Will try again." if !ret
|
46
|
+
ret = Authorization.create_policy(xml, @subjectid) if !ret
|
47
|
+
$logger.debug "Policy send with subjectid: #{@subjectid}"
|
48
|
+
$logger.error "Not created Policy is: #{xml}" if !ret
|
46
49
|
ret
|
47
50
|
end
|
48
|
-
|
49
51
|
end
|
50
52
|
|
51
53
|
#Returns the open-sso server set in the config file .opentox/config/[environment].yaml
|
52
54
|
# @return [String, nil] the openSSO server URI or nil
|
53
55
|
def self.server
|
54
|
-
return
|
56
|
+
return AA
|
55
57
|
end
|
56
58
|
|
57
59
|
#Authentication against OpenSSO. Returns token. Requires Username and Password.
|
58
60
|
# @param [String, String]Username,Password
|
59
61
|
# @return [String, nil] gives subjectid or nil
|
60
62
|
def self.authenticate(user, pw)
|
61
|
-
return nil if !
|
63
|
+
return nil if !AA
|
62
64
|
begin
|
63
|
-
|
64
|
-
out = resource.post(:username=>user, :password => pw).sub("token.id=","").sub("\n","")
|
65
|
+
out = RestClientWrapper.post("#{AA}/auth/authenticate",{:username=>user, :password => pw}).sub("token.id=","").sub("\n","")
|
65
66
|
return out
|
66
67
|
rescue
|
67
68
|
return nil
|
@@ -73,22 +74,21 @@ module OpenTox
|
|
73
74
|
# @return [Boolean] true if logout is OK
|
74
75
|
def self.logout(subjectid)
|
75
76
|
begin
|
76
|
-
|
77
|
-
|
78
|
-
return true
|
77
|
+
out = RestClientWrapper.post("#{AA}/auth/logout",:subjectid => subjectid)
|
78
|
+
return true unless is_token_valid(subjectid)
|
79
79
|
rescue
|
80
80
|
return false
|
81
81
|
end
|
82
|
+
return false
|
82
83
|
end
|
83
84
|
|
84
85
|
#Authorization against OpenSSO for a URI with request-method (action) [GET/POST/PUT/DELETE]
|
85
86
|
# @param [String,String,String]uri,action,subjectid
|
86
87
|
# @return [Boolean, nil] returns true, false or nil (if authorization-request fails).
|
87
88
|
def self.authorize(uri, action, subjectid)
|
88
|
-
return true if !
|
89
|
+
return true if !AA
|
89
90
|
begin
|
90
|
-
|
91
|
-
return true if resource.post(:uri => uri, :action => action, :subjectid => subjectid) == "boolean=true\n"
|
91
|
+
return true if RestClientWrapper.post("#{AA}/auth/authorize",{:uri => uri, :action => action, :subjectid => subjectid})== "boolean=true\n"
|
92
92
|
rescue
|
93
93
|
return nil
|
94
94
|
end
|
@@ -98,13 +98,13 @@ module OpenTox
|
|
98
98
|
# @param [String]subjectid subjectid from openSSO session
|
99
99
|
# @return [Boolean] subjectid is valid or not.
|
100
100
|
def self.is_token_valid(subjectid)
|
101
|
-
return true if !
|
101
|
+
return true if !AA
|
102
102
|
begin
|
103
|
-
|
104
|
-
return true if resource.post(:tokenid => subjectid) == "boolean=true\n"
|
103
|
+
return true if RestClientWrapper.post("#{AA}/auth/isTokenValid",:tokenid => subjectid) == "boolean=true\n"
|
105
104
|
rescue
|
106
105
|
return false
|
107
106
|
end
|
107
|
+
return false
|
108
108
|
end
|
109
109
|
|
110
110
|
#Returns array with all policies of the token owner
|
@@ -112,11 +112,8 @@ module OpenTox
|
|
112
112
|
# @return [Array, nil] returns an Array of policy names or nil if request fails
|
113
113
|
def self.list_policies(subjectid)
|
114
114
|
begin
|
115
|
-
|
116
|
-
out = resource.get(:subjectid => subjectid)
|
115
|
+
out = RestClientWrapper.get("#{AA}/pol",nil,:subjectid => subjectid)
|
117
116
|
return out.split("\n")
|
118
|
-
rescue RestClient::InternalServerError => e
|
119
|
-
raise e.response
|
120
117
|
rescue
|
121
118
|
return nil
|
122
119
|
end
|
@@ -127,8 +124,7 @@ module OpenTox
|
|
127
124
|
# @return [String] XML of the policy
|
128
125
|
def self.list_policy(policy, subjectid)
|
129
126
|
begin
|
130
|
-
|
131
|
-
return resource.get(:subjectid => subjectid,:id => policy)
|
127
|
+
return RestClientWrapper.get("#{AA}/pol",nil,{:subjectid => subjectid,:id => policy})
|
132
128
|
rescue
|
133
129
|
return nil
|
134
130
|
end
|
@@ -160,8 +156,7 @@ module OpenTox
|
|
160
156
|
# return [String, nil]owner,nil returns owner of the URI
|
161
157
|
def self.get_uri_owner(uri, subjectid)
|
162
158
|
begin
|
163
|
-
|
164
|
-
return resource.get(:uri => uri, :subjectid => subjectid).sub("\n","")
|
159
|
+
return RestClientWrapper.get("#{AA}/pol",nil,{:subjectid => subjectid, :uri => uri}).sub("\n","")
|
165
160
|
rescue
|
166
161
|
return nil
|
167
162
|
end
|
@@ -181,8 +176,7 @@ module OpenTox
|
|
181
176
|
# return [Array, nil] returns an Array of policy names or nil if request fails
|
182
177
|
def self.list_uri_policies(uri, subjectid)
|
183
178
|
begin
|
184
|
-
|
185
|
-
out = resource.get(:uri => uri, :polnames => true, :subjectid => subjectid)
|
179
|
+
out = RestClientWrapper.get("#{AA}/pol",nil,{:uri => uri, :polnames => true, :subjectid => subjectid})
|
186
180
|
policies = []; notfirstline = false
|
187
181
|
out.split("\n").each do |line|
|
188
182
|
policies << line if notfirstline
|
@@ -199,9 +193,8 @@ module OpenTox
|
|
199
193
|
# return [Boolean] returns true if policy is created
|
200
194
|
def self.create_policy(policy, subjectid)
|
201
195
|
begin
|
202
|
-
|
203
|
-
|
204
|
-
return true if resource.post(policy, :subjectid => subjectid, :content_type => "application/xml")
|
196
|
+
$logger.debug "OpenTox::Authorization.create_policy policy: #{policy[168,43]} with token:" + subjectid.to_s + " length: " + subjectid.length.to_s
|
197
|
+
return true if RestClientWrapper.post("#{AA}/Pol/opensso-pol",policy, {:subjectid => subjectid, :content_type => "application/xml"})
|
205
198
|
rescue
|
206
199
|
return false
|
207
200
|
end
|
@@ -212,36 +205,19 @@ module OpenTox
|
|
212
205
|
# @return [Boolean,nil]
|
213
206
|
def self.delete_policy(policy, subjectid)
|
214
207
|
begin
|
215
|
-
|
216
|
-
|
217
|
-
return true if resource.delete(:subjectid => subjectid, :id => policy)
|
208
|
+
$logger.debug "OpenTox::Authorization.delete_policy policy: #{policy} with token: #{subjectid}"
|
209
|
+
return true if RestClientWrapper.delete("#{AA}/pol",nil, {:subjectid => subjectid, :id => policy})
|
218
210
|
rescue
|
219
211
|
return nil
|
220
212
|
end
|
221
213
|
end
|
222
214
|
|
223
|
-
#Returns array of all possible LDAP-Groups
|
224
|
-
# @param [String]subjectid
|
225
|
-
# @return [Array]
|
226
|
-
def self.list_groups(subjectid)
|
227
|
-
begin
|
228
|
-
resource = RestClient::Resource.new("#{AA_SERVER}/opensso/identity/search")
|
229
|
-
grps = resource.post(:admin => subjectid, :attributes_names => "objecttype", :attributes_values_objecttype => "group")
|
230
|
-
grps = grps.split("\n").collect{|x| x.sub("string=","")}
|
231
|
-
grps.delete_if{|g|g=="MemberManagement"||g=="Webmasters"}
|
232
|
-
grps
|
233
|
-
rescue
|
234
|
-
[]
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
215
|
#Returns array of the LDAP-Groups of an user
|
239
216
|
# @param [String]subjectid
|
240
217
|
# @return [Array] gives array of LDAP groups of a user
|
241
218
|
def self.list_user_groups(user, subjectid)
|
242
219
|
begin
|
243
|
-
|
244
|
-
out = resource.post(:name => user, :admin => subjectid, :attributes_names => "group")
|
220
|
+
out = RestClientWrapper.post("#{AA}/opensso/identity/read", {:name => user, :admin => subjectid, :attributes_names => "group"})
|
245
221
|
grps = []
|
246
222
|
out.split("\n").each do |line|
|
247
223
|
grps << line.sub("identitydetails.group=","") if line.include?("identitydetails.group=")
|
@@ -257,8 +233,7 @@ module OpenTox
|
|
257
233
|
# @return [String]user
|
258
234
|
def self.get_user(subjectid)
|
259
235
|
begin
|
260
|
-
|
261
|
-
out = resource.post(:subjectid => subjectid, :attributes_names => "uid")
|
236
|
+
out = RestClientWrapper.post("#{AA}/opensso/identity/attributes", {:subjectid => subjectid, :attributes_names => "uid"})
|
262
237
|
user = ""; check = false
|
263
238
|
out.split("\n").each do |line|
|
264
239
|
if check
|
@@ -273,13 +248,13 @@ module OpenTox
|
|
273
248
|
end
|
274
249
|
end
|
275
250
|
|
276
|
-
#Send default policy with Authorization::
|
251
|
+
#Send default policy with Authorization::Helper class
|
277
252
|
# @param [String, String]URI,subjectid
|
278
253
|
def self.send_policy(uri, subjectid)
|
279
|
-
return true if !
|
280
|
-
aa = Authorization::
|
254
|
+
return true if !AA
|
255
|
+
aa = Authorization::Helper.new(subjectid)
|
281
256
|
ret = aa.send(uri)
|
282
|
-
|
257
|
+
$logger.debug "OpenTox::Authorization send policy for URI: #{uri} | subjectid: #{subjectid} - policy created: #{ret}"
|
283
258
|
ret
|
284
259
|
end
|
285
260
|
|
@@ -291,7 +266,7 @@ module OpenTox
|
|
291
266
|
if policies
|
292
267
|
policies.each do |policy|
|
293
268
|
ret = delete_policy(policy, subjectid)
|
294
|
-
|
269
|
+
$logger.debug "OpenTox::Authorization delete policy: #{policy} - with result: #{ret}"
|
295
270
|
end
|
296
271
|
end
|
297
272
|
return true
|
@@ -300,15 +275,15 @@ module OpenTox
|
|
300
275
|
# Checks (if subjectid is valid) if a policy exist and create default policy if not
|
301
276
|
# @param [String] uri
|
302
277
|
# @param [String] subjectid
|
303
|
-
# @return [Boolean] true if policy checked/created successfully (or no uri/subjectid given), false else
|
278
|
+
# @return [Boolean] true if policy checked/created successfully (or no uri/subjectid given), false else
|
304
279
|
def self.check_policy(uri, subjectid)
|
305
280
|
return true unless uri and subjectid
|
306
281
|
token_valid = OpenTox::Authorization.is_token_valid(subjectid)
|
307
|
-
|
282
|
+
$logger.debug "OpenTox::Authorization.check_policy with uri: #{uri}, subjectid: #{subjectid} is valid: #{token_valid}"
|
308
283
|
# check if subjectid is valid
|
309
284
|
unless token_valid
|
310
285
|
# abort if invalid
|
311
|
-
|
286
|
+
$logger.error "OpenTox::Authorization.check_policy, subjectid NOT valid: #{subjectid}"
|
312
287
|
return false
|
313
288
|
end
|
314
289
|
|
@@ -320,7 +295,7 @@ module OpenTox
|
|
320
295
|
if authorize(uri, "POST", subjectid)
|
321
296
|
true
|
322
297
|
else
|
323
|
-
|
298
|
+
$logger.error "OpenTox::Authorization.check_policy, already exists, but no POST-authorization with subjectid: #{subjectid}"
|
324
299
|
false
|
325
300
|
end
|
326
301
|
end
|
@@ -337,35 +312,36 @@ module OpenTox
|
|
337
312
|
# @param [String] subjectid
|
338
313
|
# @return [Boolean] true if access granted, else otherwise
|
339
314
|
def self.authorized?(uri, request_method, subjectid)
|
340
|
-
if
|
341
|
-
|
315
|
+
request_method = request_method.to_sym if request_method
|
316
|
+
if $aa[:free_request].include?(request_method)
|
317
|
+
#$logger.debug "authorized? >>true<< (request is free), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
|
342
318
|
true
|
343
319
|
elsif OpenTox::Authorization.free_uri?(uri, request_method)
|
344
|
-
|
320
|
+
#$logger.debug "authorized? >>true<< (uris is free_uri), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
|
345
321
|
true
|
346
|
-
elsif
|
322
|
+
elsif $aa[:authenticate_request].include?(request_method)
|
347
323
|
ret = OpenTox::Authorization.is_token_valid(subjectid)
|
348
|
-
|
324
|
+
$logger.debug "authorized? >>#{ret}<< (token is in/valid), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}" unless ret
|
349
325
|
ret
|
350
326
|
elsif OpenTox::Authorization.authorize_exception?(uri, request_method)
|
351
327
|
ret = OpenTox::Authorization.is_token_valid(subjectid)
|
352
|
-
|
328
|
+
$logger.debug "authorized? >>#{ret}<< (uris is authorize exception, token is in/valid), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}" unless ret
|
353
329
|
ret
|
354
|
-
elsif
|
330
|
+
elsif $aa[:authorize_request].include?(request_method)
|
355
331
|
ret = OpenTox::Authorization.authorize(uri, request_method, subjectid)
|
356
|
-
|
332
|
+
$logger.debug "authorized? >>#{ret}<< (uri (not) authorized), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}" unless ret
|
357
333
|
ret
|
358
334
|
else
|
359
|
-
|
335
|
+
$logger.error "invalid request/uri method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
|
360
336
|
false
|
361
337
|
end
|
362
338
|
end
|
363
339
|
|
364
340
|
private
|
365
341
|
def self.free_uri?(uri, request_method)
|
366
|
-
if
|
367
|
-
|
368
|
-
if request_methods and uris and request_methods.include?(request_method.
|
342
|
+
if $aa[:free_uris]
|
343
|
+
$aa[:free_uris].each do |request_methods,uris|
|
344
|
+
if request_methods and uris and request_methods.include?(request_method.to_s)
|
369
345
|
uris.each do |u|
|
370
346
|
return true if u.match uri
|
371
347
|
end
|
@@ -376,8 +352,8 @@ module OpenTox
|
|
376
352
|
end
|
377
353
|
|
378
354
|
def self.authorize_exception?(uri, request_method)
|
379
|
-
if
|
380
|
-
|
355
|
+
if $aa[:authorize_exceptions]
|
356
|
+
$aa[:authorize_exceptions].each do |request_methods,uris|
|
381
357
|
if request_methods and uris and request_methods.include?(request_method.to_sym)
|
382
358
|
uris.each do |u|
|
383
359
|
return true if u.match uri
|
data/lib/dataset.rb
CHANGED
@@ -1,318 +1,29 @@
|
|
1
1
|
module OpenTox
|
2
|
-
|
2
|
+
|
3
3
|
# Ruby wrapper for OpenTox Dataset Webservices (http://opentox.org/dev/apis/api-1.2/dataset).
|
4
|
-
# TODO: fix API Doc
|
5
4
|
class Dataset
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
# @return [OpenTox::Dataset] Dataset object
|
18
|
-
def initialize(uri=nil,subjectid=nil)
|
19
|
-
super uri, subjectid
|
20
|
-
@features = {}
|
21
|
-
@compounds = []
|
22
|
-
@data_entries = {}
|
23
|
-
end
|
24
|
-
|
25
|
-
=begin
|
26
|
-
# Load YAML representation into the dataset
|
27
|
-
# @param [String] yaml YAML representation of the dataset
|
28
|
-
# @return [OpenTox::Dataset] Dataset object with YAML data
|
29
|
-
def self.from_yaml service_uri, yaml, subjectid=nil
|
30
|
-
Dataset.create(service_uri, subjectid).post yaml, :content_type => "application/x-yaml"
|
31
|
-
end
|
32
|
-
|
33
|
-
# Load RDF/XML representation from a file
|
34
|
-
# @param [String] file File with RDF/XML representation of the dataset
|
35
|
-
# @return [OpenTox::Dataset] Dataset object with RDF/XML data
|
36
|
-
def self.from_rdfxml service_uri, rdfxml, subjectid=nil
|
37
|
-
Dataset.create(service_uri, subjectid).post rdfxml, :content_type => "application/rdf+xml"
|
38
|
-
end
|
39
|
-
|
40
|
-
# Load CSV string (format specification: http://toxcreate.org/help)
|
41
|
-
# - loads data_entries, compounds, features
|
42
|
-
# - sets metadata (warnings) for parser errors
|
43
|
-
# - you will have to set remaining metadata manually
|
44
|
-
# @param [String] csv CSV representation of the dataset
|
45
|
-
# @return [OpenTox::Dataset] Dataset object with CSV data
|
46
|
-
def self.from_csv service_uri, csv, subjectid=nil
|
47
|
-
Dataset.from_file(service_uri, csv, subjectid)
|
48
|
-
end
|
49
|
-
|
50
|
-
# Load Spreadsheet book (created with roo gem http://roo.rubyforge.org/, excel format specification: http://toxcreate.org/help)
|
51
|
-
# - loads data_entries, compounds, features
|
52
|
-
# - sets metadata (warnings) for parser errors
|
53
|
-
# - you will have to set remaining metadata manually
|
54
|
-
# @param [Excel] book Excel workbook object (created with roo gem)
|
55
|
-
# @return [OpenTox::Dataset] Dataset object with Excel data
|
56
|
-
def self.from_xls service_uri, xls, subjectid=nil
|
57
|
-
Dataset.create(service_uri, subjectid).post xls, :content_type => "application/vnd.ms-excel"
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.from_sdf service_uri, sdf, subjectid=nil
|
61
|
-
Dataset.create(service_uri, subjectid).post sdf, :content_type => 'chemical/x-mdl-sdfile'
|
62
|
-
end
|
63
|
-
=end
|
64
|
-
|
65
|
-
# Load all data (metadata, data_entries, compounds and features) from URI
|
66
|
-
# TODO: move to opentox-server
|
67
|
-
def data_entries reload=true
|
68
|
-
if reload
|
69
|
-
file = Tempfile.new("ot-rdfxml")
|
70
|
-
file.puts get :accept => "application/rdf+xml"
|
71
|
-
file.close
|
72
|
-
to_delete = file.path
|
73
|
-
|
74
|
-
data = {}
|
75
|
-
feature_values = {}
|
76
|
-
feature = {}
|
77
|
-
feature_accept_values = {}
|
78
|
-
other_statements = {}
|
79
|
-
`rapper -i rdfxml -o ntriples #{file.path} 2>/dev/null`.each_line do |line|
|
80
|
-
triple = line.chomp.split(' ',3)
|
81
|
-
triple = triple[0..2].collect{|i| i.sub(/\s+.$/,'').gsub(/[<>"]/,'')}
|
82
|
-
case triple[1]
|
83
|
-
when /#{RDF::OT.values}|#{RDF::OT1.values}/i
|
84
|
-
data[triple[0]] = {:compound => "", :values => []} unless data[triple[0]]
|
85
|
-
data[triple[0]][:values] << triple[2]
|
86
|
-
when /#{RDF::OT.value}|#{RDF::OT1.value}/i
|
87
|
-
feature_values[triple[0]] = triple[2]
|
88
|
-
when /#{RDF::OT.compound}|#{RDF::OT1.compound}/i
|
89
|
-
data[triple[0]] = {:compound => "", :values => []} unless data[triple[0]]
|
90
|
-
data[triple[0]][:compound] = triple[2]
|
91
|
-
when /#{RDF::OT.feature}|#{RDF::OT1.feature}/i
|
92
|
-
feature[triple[0]] = triple[2]
|
93
|
-
when /#{RDF.type}/i
|
94
|
-
if triple[2]=~/#{RDF::OT.Compound}|#{RDF::OT1.Compound}/i and !data[triple[0]]
|
95
|
-
data[triple[0]] = {:compound => triple[0], :values => []}
|
96
|
-
end
|
97
|
-
when /#{RDF::OT.acceptValue}|#{RDF::OT1.acceptValue}/i # acceptValue in ambit datasets is only provided in dataset/<id> no in dataset/<id>/features
|
98
|
-
feature_accept_values[triple[0]] = [] unless feature_accept_values[triple[0]]
|
99
|
-
feature_accept_values[triple[0]] << triple[2]
|
100
|
-
else
|
101
|
-
end
|
102
|
-
end
|
103
|
-
File.delete(to_delete) if to_delete
|
104
|
-
data.each do |id,entry|
|
105
|
-
if entry[:values].size==0
|
106
|
-
# no feature values add plain compounds
|
107
|
-
@compounds << entry[:compound] unless @compounds.include? entry[:compound]
|
108
|
-
else
|
109
|
-
entry[:values].each do |value_id|
|
110
|
-
if feature_values[value_id]
|
111
|
-
split = feature_values[value_id].split(/\^\^/)
|
112
|
-
case split[-1]
|
113
|
-
when RDF::XSD.double, RDF::XSD.float
|
114
|
-
value = split.first.to_f
|
115
|
-
when RDF::XSD.boolean
|
116
|
-
value = split.first=~/(?i)true/ ? true : false
|
117
|
-
else
|
118
|
-
value = split.first
|
119
|
-
end
|
120
|
-
end
|
121
|
-
@compounds << entry[:compound] unless @compounds.include? entry[:compound]
|
122
|
-
@features[feature[value_id][value_id]] = {} unless @features[feature[value_id]]
|
123
|
-
@data_entries[entry[:compound].to_s] = {} unless @data_entries[entry[:compound].to_s]
|
124
|
-
@data_entries[entry[:compound].to_s][feature[value_id]] = [] unless @data_entries[entry[:compound]][feature[value_id]]
|
125
|
-
@data_entries[entry[:compound].to_s][feature[value_id]] << value if value!=nil
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
features subjectid
|
130
|
-
#feature_accept_values.each do |feature, values|
|
131
|
-
#self.features[feature][OT.acceptValue] = values
|
132
|
-
#end
|
133
|
-
self.metadata = metadata(subjectid)
|
134
|
-
end
|
135
|
-
@data_entries
|
136
|
-
end
|
137
|
-
|
138
|
-
# Load and return only compound URIs from the dataset service
|
139
|
-
# @return [Array] Compound URIs in the dataset
|
140
|
-
def compounds reload=true
|
141
|
-
reload ? @compounds = Compound.all(File.join(@uri,"compounds")) : @compounds
|
142
|
-
end
|
143
|
-
|
144
|
-
# Load and return only features from the dataset service
|
145
|
-
# @return [Hash] Features of the dataset
|
146
|
-
def features reload=true
|
147
|
-
reload ? @features = Feature.all(File.join(@uri,"features")) : @features
|
148
|
-
end
|
149
|
-
|
150
|
-
=begin
|
151
|
-
# returns the accept_values of a feature, i.e. the classification domain / all possible feature values
|
152
|
-
# @param [String] feature the URI of the feature
|
153
|
-
# @return [Array] return array with strings, nil if value is not set (e.g. when feature is numeric)
|
154
|
-
def accept_values(feature)
|
155
|
-
load_features
|
156
|
-
accept_values = features[feature][OT.acceptValue]
|
157
|
-
accept_values.sort if accept_values
|
158
|
-
accept_values
|
159
|
-
end
|
160
|
-
|
161
|
-
# Detect feature type(s) in the dataset
|
162
|
-
# @return [String] `classification", "regression", "mixed" or unknown`
|
163
|
-
def feature_type
|
164
|
-
load_features
|
165
|
-
feature_types = @features.collect{|f,metadata| metadata[RDF.type]}.flatten.uniq
|
166
|
-
if feature_types.include?(OT.NominalFeature)
|
167
|
-
"classification"
|
168
|
-
elsif feature_types.include?(OT.NumericFeature)
|
169
|
-
"regression"
|
170
|
-
else
|
171
|
-
"unknown"
|
172
|
-
end
|
6
|
+
def data_entries
|
7
|
+
# TODO fix for api 1.2
|
8
|
+
data_entries = []
|
9
|
+
pull
|
10
|
+
@reload = false
|
11
|
+
metadata[RDF::OT1.dataEntry].collect{|data_entry|
|
12
|
+
data_entries << @rdf.to_hash[data_entry]
|
13
|
+
}
|
14
|
+
@reload = true
|
15
|
+
data_entries
|
173
16
|
end
|
174
|
-
=end
|
175
17
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
get :accept => "application/vnd.ms-excel"
|
18
|
+
def compounds
|
19
|
+
uri = File.join(@uri,"compounds")
|
20
|
+
RestClientWrapper.get(uri,{},{:accept => "text/uri-list", :subjectid => @subjectid}).split("\n").collect{|uri| OpenTox::Compound.new uri}
|
180
21
|
end
|
181
22
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
get :accept => "text/csv"
|
23
|
+
def features
|
24
|
+
uri = File.join(@uri,"features")
|
25
|
+
RestClientWrapper.get(uri,{},{:accept => "text/uri-list", :subjectid => @subjectid}).split("\n").collect{|uri| OpenTox::Feature.new uri}
|
186
26
|
end
|
187
27
|
|
188
|
-
def to_sdf
|
189
|
-
get :accept => 'chemical/x-mdl-sdfile'
|
190
|
-
end
|
191
|
-
|
192
|
-
|
193
|
-
# Get OWL-DL in ntriples format
|
194
|
-
# @return [String] N-Triples representation
|
195
|
-
def to_ntriples
|
196
|
-
get :accept => "application/rdf+xml"
|
197
|
-
end
|
198
|
-
|
199
|
-
# Get OWL-DL in RDF/XML format
|
200
|
-
# @return [String] RDF/XML representation
|
201
|
-
def to_rdfxml
|
202
|
-
get :accept => "application/rdf+xml"
|
203
|
-
end
|
204
|
-
|
205
|
-
# Get name (DC.title) of a feature
|
206
|
-
# @param [String] feature Feature URI
|
207
|
-
# @return [String] Feture title
|
208
|
-
def feature_name(feature)
|
209
|
-
features[feature][DC.title]
|
210
|
-
end
|
211
|
-
|
212
|
-
def title
|
213
|
-
metadata[DC.title]
|
214
|
-
end
|
215
|
-
|
216
|
-
# Insert a statement (compound_uri,feature_uri,value)
|
217
|
-
# @example Insert a statement (compound_uri,feature_uri,value)
|
218
|
-
# dataset.add "http://webservices.in-silico.ch/compound/InChI=1S/C6Cl6/c7-1-2(8)4(10)6(12)5(11)3(1)9", "http://webservices.in-silico.ch/dataset/1/feature/hamster_carcinogenicity", true
|
219
|
-
# @param [String] compound Compound URI
|
220
|
-
# @param [String] feature Compound URI
|
221
|
-
# @param [Boolean,Float] value Feature value
|
222
|
-
def add (compound,feature,value)
|
223
|
-
@compounds << compound unless @compounds.include? compound
|
224
|
-
@features[feature] = {} unless @features[feature]
|
225
|
-
@data_entries[compound] = {} unless @data_entries[compound]
|
226
|
-
@data_entries[compound][feature] = [] unless @data_entries[compound][feature]
|
227
|
-
@data_entries[compound][feature] << value if value!=nil
|
228
|
-
end
|
229
|
-
|
230
|
-
# Add a feature
|
231
|
-
# @param [String] feature Feature URI
|
232
|
-
# @param [Hash] metadata Hash with feature metadata
|
233
|
-
def add_feature(feature,metadata={})
|
234
|
-
@features[feature] = metadata
|
235
|
-
end
|
236
|
-
|
237
|
-
# Add/modify metadata for a feature
|
238
|
-
# @param [String] feature Feature URI
|
239
|
-
# @param [Hash] metadata Hash with feature metadata
|
240
|
-
def add_feature_metadata(feature,metadata)
|
241
|
-
metadata.each { |k,v| @features[feature][k] = v }
|
242
|
-
end
|
243
|
-
|
244
|
-
# Add a new compound
|
245
|
-
# @param [String] compound Compound URI
|
246
|
-
def add_compound (compound)
|
247
|
-
@compounds << compound unless @compounds.include? compound
|
248
|
-
end
|
249
|
-
|
250
|
-
# Creates a new dataset, by splitting the current dataset, i.e. using only a subset of compounds and features
|
251
|
-
# @param [Array] compounds List of compound URIs
|
252
|
-
# @param [Array] features List of feature URIs
|
253
|
-
# @param [Hash] metadata Hash containing the metadata for the new dataset
|
254
|
-
# @param [String] subjectid
|
255
|
-
# @return [OpenTox::Dataset] newly created dataset, already saved
|
256
|
-
def split( compounds, features, metadata)
|
257
|
-
LOGGER.debug "split dataset using "+compounds.size.to_s+"/"+@compounds.size.to_s+" compounds"
|
258
|
-
raise "no new compounds selected" unless compounds and compounds.size>0
|
259
|
-
dataset = OpenTox::Dataset.create(CONFIG[:services]["opentox-dataset"],@subjectid)
|
260
|
-
if features.size==0
|
261
|
-
compounds.each{ |c| dataset.add_compound(c) }
|
262
|
-
else
|
263
|
-
compounds.each do |c|
|
264
|
-
features.each do |f|
|
265
|
-
if @data_entries[c]==nil or @data_entries[c][f]==nil
|
266
|
-
dataset.add(c,f,nil)
|
267
|
-
else
|
268
|
-
@data_entries[c][f].each do |v|
|
269
|
-
dataset.add(c,f,v)
|
270
|
-
end
|
271
|
-
end
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
# set feature metadata in new dataset accordingly (including accept values)
|
276
|
-
features.each do |f|
|
277
|
-
self.features[f].each do |k,v|
|
278
|
-
dataset.features[f][k] = v
|
279
|
-
end
|
280
|
-
end
|
281
|
-
dataset.add_metadata(metadata)
|
282
|
-
dataset.save
|
283
|
-
dataset
|
284
|
-
end
|
285
|
-
|
286
|
-
# Save dataset at the dataset service
|
287
|
-
# - creates a new dataset if uri is not set
|
288
|
-
# - overwrites dataset if uri exists
|
289
|
-
# @return [String] Dataset URI
|
290
|
-
def save
|
291
|
-
@compounds.uniq!
|
292
|
-
# create dataset if uri is empty
|
293
|
-
self.uri = RestClientWrapper.post(CONFIG[:services]["opentox-dataset"],{:subjectid => @subjectid}).to_s.chomp unless @uri
|
294
|
-
if (CONFIG[:yaml_hosts].include?(URI.parse(@uri).host))
|
295
|
-
RestClientWrapper.post(@uri,self.to_yaml,{:content_type => "application/x-yaml", :subjectid => @subjectid})
|
296
|
-
else
|
297
|
-
s = Serializer::Owl.new
|
298
|
-
s.add_dataset(self)
|
299
|
-
RestClientWrapper.post(@uri, s.to_rdfxml,{:content_type => "application/rdf+xml" , :subjectid => @subjectid})
|
300
|
-
end
|
301
|
-
@uri
|
302
|
-
end
|
303
|
-
|
304
|
-
private
|
305
|
-
# Copy a dataset (rewrites URI)
|
306
|
-
def copy(dataset)
|
307
|
-
@metadata = dataset.metadata
|
308
|
-
@data_entries = dataset.data_entries
|
309
|
-
@compounds = dataset.compounds
|
310
|
-
@features = dataset.features
|
311
|
-
if @uri
|
312
|
-
self.uri = @uri
|
313
|
-
else
|
314
|
-
@uri = dataset.metadata[XSD.anyURI]
|
315
|
-
end
|
316
|
-
end
|
317
28
|
end
|
318
29
|
end
|