opentox-client 0.0.1pre → 0.0.2pre
Sign up to get free protection for your applications and to get access to all the features.
- 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/lib/error.rb
CHANGED
@@ -45,20 +45,19 @@ module OpenTox
|
|
45
45
|
OpenTox.const_set klass,c
|
46
46
|
|
47
47
|
# define global methods for raising errors, eg. bad_request_error
|
48
|
-
Object.send(:define_method, klass.underscore.to_sym) do |message|
|
49
|
-
defined?(@uri) ? uri = @uri : uri=nil
|
50
|
-
# TODO: insert uri from sinatra
|
48
|
+
Object.send(:define_method, klass.underscore.to_sym) do |message,uri=nil|
|
51
49
|
raise c, message, uri
|
52
50
|
end
|
53
51
|
end
|
54
52
|
|
55
53
|
# Errors received from RestClientWrapper calls
|
56
54
|
class RestCallError < Error
|
57
|
-
attr_accessor :request
|
58
|
-
def initialize
|
55
|
+
attr_accessor :request#, :response
|
56
|
+
def initialize message, request, uri
|
57
|
+
#def initialize request, response, message
|
59
58
|
@request = request
|
60
|
-
|
61
|
-
super 502, message,
|
59
|
+
#@response = response
|
60
|
+
super 502, message, uri
|
62
61
|
end
|
63
62
|
end
|
64
63
|
|
@@ -66,16 +65,24 @@ module OpenTox
|
|
66
65
|
class ErrorReport
|
67
66
|
def initialize http_code, error
|
68
67
|
@http_code = http_code
|
69
|
-
#@report = report#.to_yaml
|
70
68
|
@report = {}
|
71
|
-
@report[RDF::OT.actor] = error.uri
|
72
|
-
@report[RDF::OT.message] = error.message
|
69
|
+
@report[RDF::OT.actor] = error.uri.to_s
|
70
|
+
@report[RDF::OT.message] = error.message.to_s
|
73
71
|
@report[RDF::OT.statusCode] = @http_code
|
74
72
|
@report[RDF::OT.errorCode] = error.class.to_s
|
75
|
-
|
73
|
+
|
74
|
+
# cut backtrace
|
75
|
+
backtrace = caller.collect{|line| line unless line =~ /#{File.dirname(__FILE__)}/}.compact
|
76
|
+
cut_index = backtrace.find_index{|line| line.match /sinatra|minitest/}
|
77
|
+
cut_index ||= backtrace.size
|
78
|
+
cut_index -= 1
|
79
|
+
cut_index = backtrace.size-1 if cut_index < 0
|
80
|
+
@report[RDF::OT.errorDetails] = backtrace[0..cut_index].join("\n")
|
76
81
|
@report[RDF::OT.errorDetails] += "REST paramenters:\n#{error.request.args.inspect}" if defined? error.request
|
77
|
-
|
82
|
+
#@report[RDF::OT.message] += "\n" + error.response.body.to_s if defined? error.response
|
78
83
|
# TODO fix Error cause
|
84
|
+
# should point to another errorReport, but errorReports do not have URIs
|
85
|
+
# create a separate service?
|
79
86
|
#report[RDF::OT.errorCause] = @report if defined?(@report)
|
80
87
|
end
|
81
88
|
|
@@ -84,6 +91,10 @@ module OpenTox
|
|
84
91
|
|
85
92
|
send :define_method, "to_#{format}".to_sym do
|
86
93
|
rdf = RDF::Writer.for(format).buffer do |writer|
|
94
|
+
# TODO: not used for turtle
|
95
|
+
# http://rdf.rubyforge.org/RDF/Writer.html#
|
96
|
+
writer.prefix :ot, RDF::URI('http://www.opentox.org/api/1.2#')
|
97
|
+
writer.prefix :ot1_1, RDF::URI('http://www.opentox.org/api/1.1#')
|
87
98
|
subject = RDF::Node.new
|
88
99
|
@report.each do |predicate,object|
|
89
100
|
writer << [subject, predicate, object] if object
|
data/lib/opentox-client.rb
CHANGED
@@ -5,6 +5,7 @@ require 'rdf/raptor'
|
|
5
5
|
require "rest-client"
|
6
6
|
require 'uri'
|
7
7
|
require 'yaml'
|
8
|
+
require 'json'
|
8
9
|
require 'logger'
|
9
10
|
|
10
11
|
# define constants and global variables
|
@@ -14,7 +15,7 @@ RDF::OT1 = RDF::Vocabulary.new 'http://www.opentox.org/api/1.1#'
|
|
14
15
|
RDF::OTA = RDF::Vocabulary.new 'http://www.opentox.org/algorithmTypes.owl#'
|
15
16
|
|
16
17
|
#CLASSES = ["Compound", "Feature", "Dataset", "Algorithm", "Model", "Validation", "Task", "ErrorReport", "Investigation"]
|
17
|
-
CLASSES = ["Compound", "Feature", "Dataset", "Algorithm", "Model", "Validation", "Task", "Investigation"]
|
18
|
+
CLASSES = ["Generic", "Compound", "Feature", "Dataset", "Algorithm", "Model", "Validation", "Task", "Investigation"]
|
18
19
|
RDF_FORMATS = [:rdfxml,:ntriples,:turtle]
|
19
20
|
$default_rdf = "application/rdf+xml"
|
20
21
|
|
@@ -25,8 +26,10 @@ FALSE_REGEXP = /^(false|inactive|0|0.0|low tox|deactivating|non-carcinogen|non-m
|
|
25
26
|
require File.join(File.dirname(__FILE__),"overwrite.rb")
|
26
27
|
require File.join(File.dirname(__FILE__),"error.rb")
|
27
28
|
require File.join(File.dirname(__FILE__),"rest-client-wrapper.rb")
|
29
|
+
require File.join(File.dirname(__FILE__),"authorization.rb")
|
30
|
+
require File.join(File.dirname(__FILE__),"policy.rb")
|
28
31
|
require File.join(File.dirname(__FILE__),"otlogger.rb") # avoid require conflicts with logger
|
29
32
|
require File.join(File.dirname(__FILE__),"opentox.rb")
|
30
33
|
require File.join(File.dirname(__FILE__),"task.rb")
|
31
34
|
require File.join(File.dirname(__FILE__),"compound.rb")
|
32
|
-
|
35
|
+
require File.join(File.dirname(__FILE__),"dataset.rb")
|
data/lib/opentox.rb
CHANGED
@@ -4,7 +4,7 @@ $logger.level = Logger::DEBUG
|
|
4
4
|
|
5
5
|
module OpenTox
|
6
6
|
|
7
|
-
attr_accessor :uri, :subjectid, :rdf, :response
|
7
|
+
attr_accessor :uri, :subjectid, :rdf, :response, :reload
|
8
8
|
|
9
9
|
# Ruby interface
|
10
10
|
|
@@ -15,34 +15,34 @@ module OpenTox
|
|
15
15
|
def initialize uri=nil, subjectid=nil
|
16
16
|
@uri = uri.to_s.chomp
|
17
17
|
@subjectid = subjectid
|
18
|
+
@reload = true
|
18
19
|
@rdf = RDF::Graph.new
|
19
20
|
end
|
20
21
|
|
21
22
|
# Load metadata from service
|
22
23
|
def pull
|
23
|
-
kind_of?(OpenTox::Dataset) ? uri = File.join(@uri,"metadata") : uri = @uri
|
24
24
|
# TODO generic method for all formats
|
25
|
-
parse_rdfxml RestClientWrapper.get(uri,{},{:accept => $default_rdf, :subjectid => @subjectid})
|
25
|
+
parse_rdfxml RestClientWrapper.get(@uri,{},{:accept => $default_rdf, :subjectid => @subjectid})
|
26
26
|
end
|
27
27
|
|
28
28
|
# Get object metadata
|
29
29
|
# @return [Hash] Metadata
|
30
30
|
def metadata
|
31
|
-
pull if @
|
32
|
-
|
33
|
-
@rdf.query([RDF::URI.new(@uri),nil,nil]).collect do |statement|
|
34
|
-
metadata[statement.predicate] ||= []
|
35
|
-
metadata[statement.predicate] << statement.object
|
36
|
-
end
|
37
|
-
metadata
|
31
|
+
pull if @reload # force update
|
32
|
+
@rdf.to_hash[RDF::URI.new(@uri)]
|
38
33
|
end
|
39
34
|
|
40
35
|
# Get metadata values
|
41
36
|
# @param [RDF] Key from RDF Vocabularies
|
42
37
|
# @return [Array] Values for supplied key
|
43
38
|
def [](key)
|
44
|
-
pull if @
|
45
|
-
@rdf.query([RDF::URI.new(@uri),key,nil]).collect{|statement| statement.object}
|
39
|
+
pull if @reload # force update
|
40
|
+
result = @rdf.query([RDF::URI.new(@uri),key,nil]).collect{|statement| statement.object}
|
41
|
+
# TODO: convert to OpenTox objects??
|
42
|
+
return nil if result and result.empty?
|
43
|
+
return result.first.to_s if result.size == 1
|
44
|
+
return result.collect{|r| r.to_s}
|
45
|
+
result
|
46
46
|
end
|
47
47
|
|
48
48
|
# Save object at service
|
@@ -70,6 +70,14 @@ module OpenTox
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
+
def to_yaml
|
74
|
+
@rdf.to_hash.to_yaml
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_json
|
78
|
+
to_hash.to_json
|
79
|
+
end
|
80
|
+
|
73
81
|
# REST API
|
74
82
|
def get headers={}
|
75
83
|
headers[:subjectid] ||= @subjectid
|
@@ -125,10 +133,14 @@ module OpenTox
|
|
125
133
|
|
126
134
|
# guess class from uri, this is potentially unsafe, but polling metadata from large uri lists is way too slow (and not all service provide RDF.type in their metadata)
|
127
135
|
result = CLASSES.collect{|s| s if uri =~ /#{s.downcase}/}.compact
|
128
|
-
|
129
|
-
|
136
|
+
if result.size == 1
|
137
|
+
klass = result.first
|
138
|
+
else
|
139
|
+
klass = OpenTox::Generic.new(uri)[RDF.type]
|
140
|
+
internal_server_error "Cannot determine class from URI '#{uri} (Candidate classes are #{result.inspect}) or matadata." unless klass
|
141
|
+
end
|
130
142
|
# initialize with/without subjectid
|
131
|
-
subjectid ? eval("#{self}.new(\"#{uri}\", #{subjectid})") : eval("#{self}.new(\"#{uri}\")")
|
143
|
+
subjectid ? eval("#{self}.new(\"#{uri}\", \"#{subjectid}\")") : eval("#{self}.new(\"#{uri}\")")
|
132
144
|
end
|
133
145
|
end
|
134
146
|
|
data/lib/overwrite.rb
CHANGED
@@ -21,18 +21,22 @@ module URI
|
|
21
21
|
def self.dataset? uri, subjectid=nil
|
22
22
|
uri =~ /dataset/ and URI.accessible? uri, subjectid=nil
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def self.model? uri, subjectid=nil
|
26
26
|
uri =~ /model/ and URI.accessible? uri, subjectid=nil
|
27
27
|
end
|
28
28
|
|
29
|
-
def self.
|
29
|
+
def self.ssl? uri, subjectid=nil
|
30
|
+
URI.parse(uri).instance_of? URI::HTTPS
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.accessible?(uri, subjectid=nil)
|
30
34
|
if URI.task? uri or URI.compound? uri
|
31
35
|
# just try to get a response, valid tasks may return codes > 400
|
32
36
|
Net::HTTP.get_response(URI.parse(uri))
|
33
37
|
true
|
34
38
|
else
|
35
|
-
Net::HTTP.get_response(URI.parse(uri)).code.to_i < 400
|
39
|
+
Net::HTTP.get_response(URI.parse(uri + (subjectid ? "?subjectid=#{CGI.escape subjectid}" : ""))).code.to_i < 400
|
36
40
|
end
|
37
41
|
rescue
|
38
42
|
false
|
@@ -64,27 +68,11 @@ module Kernel
|
|
64
68
|
stdout = stdout_stream.read
|
65
69
|
stderr = stderr_stream.read
|
66
70
|
end
|
67
|
-
|
71
|
+
internal_server_error "`" + cmd + "` failed.\n" + stdout + stderr if !status.success?
|
68
72
|
return stdout
|
69
|
-
rescue
|
70
|
-
internal_server_error
|
73
|
+
rescue
|
74
|
+
internal_server_error $!.message
|
71
75
|
end
|
72
76
|
|
73
|
-
alias_method :system!, :system
|
74
|
-
|
75
|
-
def system cmd
|
76
|
-
`#{cmd}`
|
77
|
-
return true
|
78
|
-
end
|
79
77
|
end
|
80
78
|
|
81
|
-
class Array
|
82
|
-
def short_backtrace
|
83
|
-
short = []
|
84
|
-
each do |c|
|
85
|
-
break if c =~ /sinatra\/base/
|
86
|
-
short << c
|
87
|
-
end
|
88
|
-
short.join("\n")
|
89
|
-
end
|
90
|
-
end
|