opentox-client 0.0.2pre → 1.0.0pre1
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/.gitignore +2 -1
- data/ChangeLog +2 -0
- data/README.markdown +16 -1
- data/Rakefile +0 -10
- data/VERSION +1 -0
- data/bin/opentox-client-install +46 -0
- data/lib/authorization.rb +9 -7
- data/lib/compound.rb +40 -20
- data/lib/dataset.rb +126 -16
- data/lib/error.rb +41 -83
- data/lib/model.rb +3 -2
- data/lib/opentox-client.rb +17 -12
- data/lib/opentox.rb +122 -96
- data/lib/overwrite.rb +20 -3
- data/lib/policy.rb +17 -2
- data/lib/rest-client-wrapper.rb +24 -5
- data/lib/task.rb +36 -18
- data/opentox-client.gemspec +2 -1
- metadata +60 -38
- data/test/authorization.rb +0 -107
- data/test/compound.rb +0 -52
- data/test/data/CPDBAS_v5c_1547_29Apr2008part.sdf +0 -13553
- data/test/data/EPAFHM.csv +0 -618
- data/test/data/EPAFHM.mini.csv +0 -21
- data/test/data/ISSCAN-multi.csv +0 -59
- data/test/data/cpdb_100.csv +0 -101
- data/test/data/hamster_carcinogenicity.csv +0 -86
- data/test/data/hamster_carcinogenicity.mini.csv +0 -11
- data/test/data/hamster_carcinogenicity.sdf +0 -2805
- data/test/data/hamster_carcinogenicity.xls +0 -0
- data/test/data/hamster_carcinogenicity.yaml +0 -352
- data/test/data/hamster_carcinogenicity_with_errors.csv +0 -88
- data/test/data/kazius.csv +0 -4069
- data/test/data/multi_cell_call.csv +0 -1067
- data/test/data/multicolumn.csv +0 -5
- data/test/dataset.rb +0 -99
- data/test/error.rb +0 -35
- data/test/feature.rb +0 -36
- data/test/policy.rb +0 -120
- data/test/task.rb +0 -85
data/.gitignore
CHANGED
data/ChangeLog
ADDED
data/README.markdown
CHANGED
@@ -1,8 +1,23 @@
|
|
1
|
-
opentox-
|
1
|
+
opentox-client
|
2
2
|
====================
|
3
3
|
|
4
4
|
Thin Ruby wrapper for the [OpenTox](http://www.opentox.org) REST API
|
5
5
|
|
6
|
+
Libraries:
|
7
|
+
|
8
|
+
* {OpenTox::Algorithm} Wrapper for OpenTox Algorithms
|
9
|
+
* {OpenTox::Authorization} Authorization and Authentication
|
10
|
+
* {OpenTox::Compound} Compound Library
|
11
|
+
* {OpenTox::Dataset} Dataset Library
|
12
|
+
* {OpenTox::Error} extends Exception class according the OpenTox API
|
13
|
+
* {OpenTox::Model} Model Library
|
14
|
+
* {OpenTox} OpenTox Library - general definition of OpenTox objects
|
15
|
+
* {OTLogger} OpenTox Logger Extensions
|
16
|
+
* {OpenTox::Policies} parse and serialize XML for the openSSO A&A server
|
17
|
+
* {OpenTox::RestClientWrapper} wrapper for the RestClient gem
|
18
|
+
* {OpenTox::Task} Task Library
|
19
|
+
|
20
|
+
|
6
21
|
Dependencies
|
7
22
|
------------
|
8
23
|
|
data/Rakefile
CHANGED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0pre1
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# Installs Opentox Webservice.
|
4
|
+
# Author: Christoph Helma, Andreas Maunz.
|
5
|
+
|
6
|
+
SELF=$(basename $0 -install)
|
7
|
+
[ "`id -u`" = "0" ] && echo "This script must be run as non-root." 1>&2 && exit 1
|
8
|
+
|
9
|
+
# Adjust ruby version here!
|
10
|
+
RUBY_NUM_VER="1.9.3-p194"
|
11
|
+
|
12
|
+
echo
|
13
|
+
echo "Welcome to service installation (<Return> to continue)."
|
14
|
+
read delete_me
|
15
|
+
|
16
|
+
|
17
|
+
# check wd is root of service
|
18
|
+
DIR=`pwd`
|
19
|
+
if echo $DIR | grep "$SELF/bin" >/dev/null 2>&1 ; then cd ..; fi
|
20
|
+
|
21
|
+
# # # Boot the script
|
22
|
+
|
23
|
+
# load base config, helper funs, environment
|
24
|
+
OT_CONFIG_DIR="$HOME/.opentox"
|
25
|
+
! [ -f "$OT_CONFIG_DIR/config/install/config.sh" ] && echo "config.sh not found." 1>&2 && exit 1 || . $OT_CONFIG_DIR/config/install/config.sh
|
26
|
+
! [ -f "$OT_PREFIX/install/utils.sh" ] && echo "utils.sh not found." 1>&2 && exit 1 || . $OT_PREFIX/install/utils.sh
|
27
|
+
[ -f $OT_CONFIG_DIR/opentox-ui.sh ] && . $OT_CONFIG_DIR/opentox-ui.sh # should have been done by user already
|
28
|
+
RUBY_DIR="$HOME/.rbenv/versions/$RUBY_NUM_VER"
|
29
|
+
|
30
|
+
|
31
|
+
# # # Install
|
32
|
+
|
33
|
+
check_utils "rbenv find"
|
34
|
+
check_log $SELF
|
35
|
+
|
36
|
+
# ruby
|
37
|
+
install_ruby
|
38
|
+
|
39
|
+
# self
|
40
|
+
echo
|
41
|
+
install_with_bundler
|
42
|
+
|
43
|
+
notify
|
44
|
+
|
45
|
+
# return to wd
|
46
|
+
cd "$DIR"
|
data/lib/authorization.rb
CHANGED
@@ -5,7 +5,7 @@ module OpenTox
|
|
5
5
|
#@example Authentication
|
6
6
|
# require "opentox-client"
|
7
7
|
# OpenTox::Authorization::AA = "https://opensso.in-silico.ch" #if not set in .opentox/conf/[environment].yaml
|
8
|
-
#
|
8
|
+
# subjectid = OpenTox::Authorization.authenticate("username", "password")
|
9
9
|
#@see http://www.opentox.org/dev/apis/api-1.2/AA OpenTox A&A API 1.2 specification
|
10
10
|
|
11
11
|
module Authorization
|
@@ -65,6 +65,7 @@ module OpenTox
|
|
65
65
|
out = RestClientWrapper.post("#{AA}/auth/authenticate",{:username=>user, :password => pw}).sub("token.id=","").sub("\n","")
|
66
66
|
return out
|
67
67
|
rescue
|
68
|
+
resource_not_found_error "#{out.inspect}"
|
68
69
|
return nil
|
69
70
|
end
|
70
71
|
end
|
@@ -87,11 +88,12 @@ module OpenTox
|
|
87
88
|
# @return [Boolean, nil] returns true, false or nil (if authorization-request fails).
|
88
89
|
def self.authorize(uri, action, subjectid)
|
89
90
|
return true if !AA
|
90
|
-
begin
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
91
|
+
#begin
|
92
|
+
return true if RestClientWrapper.post("#{AA}/auth/authorize",{:uri => uri, :action => action, :subjectid => subjectid})== "boolean=true\n"
|
93
|
+
return false
|
94
|
+
#rescue
|
95
|
+
# return nil
|
96
|
+
#end
|
95
97
|
end
|
96
98
|
|
97
99
|
#Checks if a token is a valid token
|
@@ -101,7 +103,7 @@ module OpenTox
|
|
101
103
|
return true if !AA
|
102
104
|
begin
|
103
105
|
return true if RestClientWrapper.post("#{AA}/auth/isTokenValid",:tokenid => subjectid) == "boolean=true\n"
|
104
|
-
rescue
|
106
|
+
rescue #do rescue because openSSO throws 401
|
105
107
|
return false
|
106
108
|
end
|
107
109
|
return false
|
data/lib/compound.rb
CHANGED
@@ -11,6 +11,7 @@ module OpenTox
|
|
11
11
|
# @param [String] smiles Smiles string
|
12
12
|
# @return [OpenTox::Compound] Compound
|
13
13
|
def self.from_smiles service_uri, smiles, subjectid=nil
|
14
|
+
@smiles = smiles
|
14
15
|
Compound.new RestClientWrapper.post(service_uri, smiles, {:content_type => 'chemical/x-daylight-smiles', :subjectid => subjectid})
|
15
16
|
end
|
16
17
|
|
@@ -18,6 +19,7 @@ module OpenTox
|
|
18
19
|
# @param [String] smiles InChI string
|
19
20
|
# @return [OpenTox::Compound] Compound
|
20
21
|
def self.from_inchi service_uri, inchi, subjectid=nil
|
22
|
+
@inchi = inchi
|
21
23
|
Compound.new RestClientWrapper.post(service_uri, inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid})
|
22
24
|
end
|
23
25
|
|
@@ -33,60 +35,78 @@ module OpenTox
|
|
33
35
|
# compound = OpenTox::Compound.from_name("Benzene")
|
34
36
|
# @param [String] name name can be also an InChI/InChiKey, CAS number, etc
|
35
37
|
# @return [OpenTox::Compound] Compound
|
38
|
+
#
|
36
39
|
def self.from_name service_uri, name, subjectid=nil
|
37
|
-
|
40
|
+
@inchi = RestClientWrapper.get File.join(CACTUS_URI,URI.escape(name),"stdinchi")
|
41
|
+
Compound.new RestClientWrapper.post(service_uri, @inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid})
|
38
42
|
end
|
39
43
|
|
40
44
|
# Get InChI
|
41
45
|
# @return [String] InChI string
|
42
|
-
def
|
43
|
-
get(:accept => 'chemical/x-inchi').
|
46
|
+
def inchi
|
47
|
+
@inchi ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-inchi'}).chomp
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get InChIKey
|
51
|
+
# @return [String] InChI string
|
52
|
+
def inchikey
|
53
|
+
@inchikey ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-inchikey'}).chomp
|
44
54
|
end
|
45
55
|
|
46
56
|
# Get (canonical) smiles
|
47
57
|
# @return [String] Smiles string
|
48
|
-
def
|
49
|
-
get(:accept => 'chemical/x-daylight-smiles').chomp
|
58
|
+
def smiles
|
59
|
+
@smiles ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-daylight-smiles'}).chomp
|
50
60
|
end
|
51
61
|
|
52
62
|
# Get sdf
|
53
63
|
# @return [String] SDF string
|
54
|
-
def
|
55
|
-
get(:accept => 'chemical/x-mdl-sdfile').chomp
|
64
|
+
def sdf
|
65
|
+
RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-mdl-sdfile'}).chomp
|
56
66
|
end
|
57
67
|
|
58
68
|
# Get gif image
|
59
69
|
# @return [image/gif] Image data
|
60
|
-
def
|
61
|
-
|
70
|
+
def gif
|
71
|
+
RestClientWrapper.get File.join(CACTUS_URI,inchi,"image")
|
62
72
|
end
|
63
73
|
|
64
74
|
# Get png image
|
65
75
|
# @example
|
66
|
-
# image = compound.
|
76
|
+
# image = compound.png
|
67
77
|
# @return [image/png] Image data
|
68
|
-
def
|
69
|
-
get(File.join @uri, "image")
|
78
|
+
def png
|
79
|
+
RestClientWrapper.get(File.join @uri, "image")
|
70
80
|
end
|
71
81
|
|
72
82
|
# Get URI of compound image
|
73
83
|
# @return [String] Compound image URI
|
74
|
-
def
|
84
|
+
def image_uri
|
75
85
|
File.join @uri, "image"
|
76
86
|
end
|
77
87
|
|
78
88
|
# Get all known compound names. Relies on an external service for name lookups.
|
79
89
|
# @example
|
80
|
-
# names = compound.
|
90
|
+
# names = compound.names
|
81
91
|
# @return [String] Compound names
|
82
|
-
def
|
83
|
-
|
84
|
-
get("#{CACTUS_URI}#{to_inchi}/names").split("\n")
|
85
|
-
rescue
|
86
|
-
"not available"
|
87
|
-
end
|
92
|
+
def names
|
93
|
+
RestClientWrapper.get("#{CACTUS_URI}#{inchi}/names").split("\n")
|
88
94
|
end
|
89
95
|
|
96
|
+
def cid
|
97
|
+
pug_uri = "http://pubchem.ncbi.nlm.nih.gov/rest/pug/"
|
98
|
+
@cid ||= RestClientWrapper.post(File.join(pug_uri, "compound", "inchi", "cids", "TXT"),{:inchi => inchi}).strip
|
99
|
+
end
|
100
|
+
|
101
|
+
def chebi
|
102
|
+
end
|
103
|
+
|
104
|
+
def chemblid
|
105
|
+
# https://www.ebi.ac.uk/chembldb/ws#individualCompoundByInChiKey
|
106
|
+
uri = "http://www.ebi.ac.uk/chemblws/compounds/smiles/#{smiles}.json"
|
107
|
+
@chemblid = JSON.parse(RestClientWrapper.get(uri))["compounds"].first["chemblId"]
|
108
|
+
end
|
109
|
+
|
90
110
|
=begin
|
91
111
|
# Match a smarts string
|
92
112
|
# @example
|
data/lib/dataset.rb
CHANGED
@@ -3,27 +3,137 @@ module OpenTox
|
|
3
3
|
# Ruby wrapper for OpenTox Dataset Webservices (http://opentox.org/dev/apis/api-1.2/dataset).
|
4
4
|
class Dataset
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
6
|
+
attr_accessor :features, :compounds, :data_entries
|
7
|
+
|
8
|
+
def initialize uri=nil, subjectid=nil
|
9
|
+
super uri, subjectid
|
10
|
+
@features = []
|
11
|
+
@compounds = []
|
12
|
+
@data_entries = []
|
13
|
+
append RDF.type, RDF::OT.OrderedDataset
|
14
|
+
end
|
15
|
+
|
16
|
+
def upload filename, wait=true
|
17
|
+
uri = RestClientWrapper.put(@uri, {:file => File.new(filename)}, {:subjectid => @subjectid})
|
18
|
+
OpenTox::Task.new(uri).wait if URI.task?(uri) and wait
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_csv
|
22
|
+
CSV.generate do |csv|
|
23
|
+
csv << ["SMILES"] + @features.collect{|f| f.title}
|
24
|
+
@compounds.each_with_index do |c,i|
|
25
|
+
csv << [c.smiles] + @data_entries[i]
|
26
|
+
end
|
27
|
+
end
|
16
28
|
end
|
17
29
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
30
|
+
def get
|
31
|
+
super
|
32
|
+
@features = []
|
33
|
+
@compounds = []
|
34
|
+
@data_entries = []
|
35
|
+
query = RDF::Query.new do
|
36
|
+
pattern [:uri, RDF.type, RDF::OT.OrderedDataset]
|
37
|
+
end
|
38
|
+
if query.execute(@rdf).first # ordered dataset
|
39
|
+
query = RDF::Query.new do
|
40
|
+
pattern [:uri, RDF.type, RDF::OT.Compound]
|
41
|
+
pattern [:uri, RDF::OLO.index, :idx]
|
42
|
+
end
|
43
|
+
@compounds = query.execute(@rdf).sort_by{|s| s.idx}.collect{|s| OpenTox::Compound.new s.uri.to_s}
|
44
|
+
query = RDF::Query.new do
|
45
|
+
pattern [:uri, RDF.type, RDF::OT.Feature]
|
46
|
+
pattern [:uri, RDF::OLO.index, :idx]
|
47
|
+
end
|
48
|
+
@features = query.execute(@rdf).sort_by{|s| s.idx}.collect{|s| OpenTox::Feature.new(s.uri.to_s)}
|
49
|
+
numeric_features = @features.collect{|f| f.get; f[RDF.type].include? RDF::OT.NumericFeature}
|
50
|
+
@compounds.each_with_index do |compound,i|
|
51
|
+
query = RDF::Query.new do
|
52
|
+
pattern [:data_entry, RDF::OLO.index, i]
|
53
|
+
pattern [:data_entry, RDF::OT.values, :values]
|
54
|
+
pattern [:values, RDF::OT.feature, :feature]
|
55
|
+
pattern [:feature, RDF::OLO.index, :feature_idx]
|
56
|
+
pattern [:values, RDF::OT.value, :value]
|
57
|
+
end
|
58
|
+
values = query.execute(@rdf).sort_by{|s| s.feature_idx}.collect do |s|
|
59
|
+
(numeric_features[s.feature_idx] and s.value.to_s != "") ? s.value.to_s.to_f : s.value.to_s
|
60
|
+
end
|
61
|
+
@data_entries << values.collect{|v| v == "" ? nil : v}
|
62
|
+
end
|
63
|
+
else
|
64
|
+
query = RDF::Query.new do
|
65
|
+
pattern [:uri, RDF.type, RDF::OT.Feature]
|
66
|
+
end
|
67
|
+
@features = query.execute(@rdf).collect{|s| OpenTox::Feature.new(s.uri.to_s)}
|
68
|
+
query = RDF::Query.new do
|
69
|
+
pattern [:data_entry, RDF::OT.compound, :compound]
|
70
|
+
end
|
71
|
+
@compounds = query.execute(@rdf).sort_by{|s| s.data_entry}.collect{|s| OpenTox::Compound.new s.compound.to_s}
|
72
|
+
numeric_features = @features.collect{|f| f.get; f[RDF.type].include? RDF::OT.NumericFeature}
|
73
|
+
@compounds.each do |compound|
|
74
|
+
values = []
|
75
|
+
@features.each_with_index do |feature,i|
|
76
|
+
query = RDF::Query.new do
|
77
|
+
pattern [:data_entry, RDF::OT.compound, RDF::URI.new(compound.uri)]
|
78
|
+
pattern [:data_entry, RDF::OT.values, :values]
|
79
|
+
pattern [:values, RDF::OT.feature, RDF::URI.new(feature.uri)]
|
80
|
+
pattern [:values, RDF::OT.value, :value]
|
81
|
+
end
|
82
|
+
value = query.execute(@rdf).first.value.to_s
|
83
|
+
value = value.to_f if numeric_features[i] and !value.nil?
|
84
|
+
values << value
|
85
|
+
end
|
86
|
+
@data_entries << values
|
87
|
+
end
|
88
|
+
end
|
21
89
|
end
|
22
90
|
|
23
|
-
def
|
24
|
-
uri = File.join(@uri,"
|
25
|
-
|
91
|
+
def get_metadata
|
92
|
+
uri = File.join(@uri,"metadata")
|
93
|
+
begin
|
94
|
+
parse_ntriples RestClientWrapper.get(uri,{},{:accept => "text/plain", :subjectid => @subjectid})
|
95
|
+
rescue # fall back to rdfxml
|
96
|
+
parse_rdfxml RestClientWrapper.get(uri,{},{:accept => "application/rdf+xml", :subjectid => @subjectid})
|
97
|
+
end
|
98
|
+
metadata
|
26
99
|
end
|
27
100
|
|
101
|
+
def << data_entry
|
102
|
+
compound = data_entry.shift
|
103
|
+
bad_request_error "Dataset features are empty." unless features
|
104
|
+
bad_request_error "data_entry size does not match features size." unless data_entry.size == features.size
|
105
|
+
bad_request_error "First data_entry is not a OpenTox::Compound" unless compound.class == OpenTox::Compound
|
106
|
+
@compounds << compound
|
107
|
+
@data_entries << data_entry
|
108
|
+
end
|
109
|
+
|
110
|
+
RDF_FORMATS.each do |format|
|
111
|
+
|
112
|
+
# redefine rdf serialization methods
|
113
|
+
send :define_method, "to_#{format}".to_sym do
|
114
|
+
# TODO: check, might affect appending to unordered datasets
|
115
|
+
features.each_with_index do |feature,i|
|
116
|
+
@rdf << [RDF::URI.new(feature.uri), RDF::URI.new(RDF.type), RDF::URI.new(RDF::OT.Feature)]
|
117
|
+
@rdf << [RDF::URI.new(feature.uri), RDF::URI.new(RDF::OLO.index), RDF::Literal.new(i)]
|
118
|
+
end
|
119
|
+
compounds.each_with_index do |compound,i|
|
120
|
+
@rdf << [RDF::URI.new(compound.uri), RDF::URI.new(RDF.type), RDF::URI.new(RDF::OT.Compound)]
|
121
|
+
@rdf << [RDF::URI.new(compound.uri), RDF::URI.new(RDF::OLO.index), RDF::Literal.new(i)]
|
122
|
+
data_entry_node = RDF::Node.new
|
123
|
+
@rdf << [RDF::URI.new(@uri), RDF::URI.new(RDF::OT.dataEntry), data_entry_node]
|
124
|
+
@rdf << [data_entry_node, RDF::URI.new(RDF.type), RDF::URI.new(RDF::OT.DataEntry)]
|
125
|
+
@rdf << [data_entry_node, RDF::URI.new(RDF::OLO.index), RDF::Literal.new(i)]
|
126
|
+
@rdf << [data_entry_node, RDF::URI.new(RDF::OT.compound), RDF::URI.new(compound.uri)]
|
127
|
+
data_entries[i].each_with_index do |value,j|
|
128
|
+
value_node = RDF::Node.new
|
129
|
+
@rdf << [data_entry_node, RDF::URI.new(RDF::OT.values), value_node]
|
130
|
+
@rdf << [value_node, RDF::URI.new(RDF::OT.feature), RDF::URI.new(@features[j].uri)]
|
131
|
+
@rdf << [value_node, RDF::URI.new(RDF::OT.value), RDF::Literal.new(value)]
|
132
|
+
end
|
133
|
+
end
|
134
|
+
super()
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
28
138
|
end
|
29
139
|
end
|
data/lib/error.rb
CHANGED
@@ -5,20 +5,51 @@ class RuntimeError
|
|
5
5
|
attr_accessor :http_code, :uri
|
6
6
|
def initialize message, uri=nil
|
7
7
|
super message
|
8
|
-
@uri = uri
|
8
|
+
@uri = uri.to_s.sub(%r{//.*:.*@},'//') # remove credentials from uri
|
9
9
|
@http_code ||= 500
|
10
|
-
|
10
|
+
@rdf = RDF::Graph.new
|
11
|
+
subject = RDF::Node.new
|
12
|
+
@rdf << [subject, RDF.type, RDF::OT.ErrorReport]
|
13
|
+
@rdf << [subject, RDF::OT.actor, @uri]
|
14
|
+
@rdf << [subject, RDF::OT.message, message.to_s]
|
15
|
+
@rdf << [subject, RDF::OT.statusCode, @http_code]
|
16
|
+
@rdf << [subject, RDF::OT.errorCode, self.class.to_s]
|
17
|
+
@rdf << [subject, RDF::OT.errorCause, short_backtrace]
|
18
|
+
$logger.error("\n"+self.to_turtle)
|
11
19
|
end
|
12
20
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
21
|
+
def short_backtrace
|
22
|
+
backtrace = caller.collect{|line| line unless line =~ /#{File.dirname(__FILE__)}/}.compact
|
23
|
+
cut_index = backtrace.find_index{|line| line.match /sinatra|minitest/}
|
24
|
+
cut_index ||= backtrace.size
|
25
|
+
cut_index -= 1
|
26
|
+
cut_index = backtrace.size-1 if cut_index < 0
|
27
|
+
backtrace[0..cut_index].join("\n")
|
16
28
|
end
|
29
|
+
|
30
|
+
RDF_FORMATS.each do |format|
|
31
|
+
# rdf serialization methods for all formats e.g. to_rdfxml
|
32
|
+
send :define_method, "to_#{format}".to_sym do
|
33
|
+
RDF::Writer.for(format).buffer do |writer|
|
34
|
+
@rdf.each{|statement| writer << statement}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_turtle # redefine to use prefixes (not supported by RDF::Writer)
|
40
|
+
prefixes = {:rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns#"}
|
41
|
+
['OT', 'DC', 'XSD', 'OLO'].each{|p| prefixes[p.downcase.to_sym] = eval("RDF::#{p}.to_s") }
|
42
|
+
RDF::N3::Writer.for(:turtle).buffer(:prefixes => prefixes) do |writer|
|
43
|
+
@rdf.each{|statement| writer << statement}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
17
47
|
end
|
18
48
|
|
19
49
|
module OpenTox
|
20
50
|
|
21
51
|
class Error < RuntimeError
|
52
|
+
|
22
53
|
def initialize code, message, uri=nil
|
23
54
|
@http_code = code
|
24
55
|
super message, uri
|
@@ -26,92 +57,19 @@ module OpenTox
|
|
26
57
|
end
|
27
58
|
|
28
59
|
# OpenTox errors
|
29
|
-
|
30
|
-
"BadRequestError" => 400,
|
31
|
-
"NotAuthorizedError" => 401,
|
32
|
-
"NotFoundError" => 404,
|
33
|
-
"LockedError" => 423,
|
34
|
-
"InternalServerError" => 500,
|
35
|
-
"NotImplementedError" => 501,
|
36
|
-
"ServiceUnavailableError" => 503,
|
37
|
-
"TimeOutError" => 504,
|
38
|
-
}.each do |klass,code|
|
60
|
+
RestClientWrapper.known_errors.each do |error|
|
39
61
|
# create error classes
|
40
62
|
c = Class.new Error do
|
41
63
|
define_method :initialize do |message, uri=nil|
|
42
|
-
super code, message, uri
|
64
|
+
super error[:code], message, uri
|
43
65
|
end
|
44
66
|
end
|
45
|
-
OpenTox.const_set
|
67
|
+
OpenTox.const_set error[:class],c
|
46
68
|
|
47
69
|
# define global methods for raising errors, eg. bad_request_error
|
48
|
-
Object.send(:define_method,
|
49
|
-
raise c
|
70
|
+
Object.send(:define_method, error[:method]) do |message,uri=nil|
|
71
|
+
raise c.new(message, uri)
|
50
72
|
end
|
51
73
|
end
|
52
74
|
|
53
|
-
# Errors received from RestClientWrapper calls
|
54
|
-
class RestCallError < Error
|
55
|
-
attr_accessor :request#, :response
|
56
|
-
def initialize message, request, uri
|
57
|
-
#def initialize request, response, message
|
58
|
-
@request = request
|
59
|
-
#@response = response
|
60
|
-
super 502, message, uri
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# TODO: create reports directly from errors, requires modified task service
|
65
|
-
class ErrorReport
|
66
|
-
def initialize http_code, error
|
67
|
-
@http_code = http_code
|
68
|
-
@report = {}
|
69
|
-
@report[RDF::OT.actor] = error.uri.to_s
|
70
|
-
@report[RDF::OT.message] = error.message.to_s
|
71
|
-
@report[RDF::OT.statusCode] = @http_code
|
72
|
-
@report[RDF::OT.errorCode] = error.class.to_s
|
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")
|
81
|
-
@report[RDF::OT.errorDetails] += "REST paramenters:\n#{error.request.args.inspect}" if defined? error.request
|
82
|
-
#@report[RDF::OT.message] += "\n" + error.response.body.to_s if defined? error.response
|
83
|
-
# TODO fix Error cause
|
84
|
-
# should point to another errorReport, but errorReports do not have URIs
|
85
|
-
# create a separate service?
|
86
|
-
#report[RDF::OT.errorCause] = @report if defined?(@report)
|
87
|
-
end
|
88
|
-
|
89
|
-
# define to_ and self.from_ methods for various rdf formats
|
90
|
-
RDF_FORMATS.each do |format|
|
91
|
-
|
92
|
-
send :define_method, "to_#{format}".to_sym do
|
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#')
|
98
|
-
subject = RDF::Node.new
|
99
|
-
@report.each do |predicate,object|
|
100
|
-
writer << [subject, predicate, object] if object
|
101
|
-
end
|
102
|
-
end
|
103
|
-
rdf
|
104
|
-
end
|
105
|
-
|
106
|
-
=begin
|
107
|
-
define_singleton_method "from_#{format}".to_sym do |rdf|
|
108
|
-
report = ErrorReport.new
|
109
|
-
RDF::Reader.for(format).new(rdf) do |reader|
|
110
|
-
reader.each_statement{ |statement| report.rdf << statement }
|
111
|
-
end
|
112
|
-
report
|
113
|
-
end
|
114
|
-
=end
|
115
|
-
end
|
116
|
-
end
|
117
75
|
end
|