opentox-ruby 0.0.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +41 -0
- data/Rakefile +4 -0
- data/VERSION +1 -1
- data/lib/algorithm.rb +15 -2
- data/lib/authorization.rb +381 -0
- data/lib/compound.rb +6 -0
- data/lib/config/config_ru.rb +1 -0
- data/lib/dataset.rb +98 -43
- data/lib/environment.rb +9 -18
- data/lib/error.rb +99 -0
- data/lib/feature.rb +30 -2
- data/lib/helper.rb +90 -17
- data/lib/model.rb +81 -34
- data/lib/ontology_service.rb +43 -0
- data/lib/opentox-ruby.rb +3 -2
- data/lib/opentox.rb +9 -4
- data/lib/overwrite.rb +87 -28
- data/lib/parser.rb +117 -22
- data/lib/policy.rb +261 -0
- data/lib/rest_client_wrapper.rb +110 -99
- data/lib/serializer.rb +130 -1
- data/lib/task.rb +179 -42
- data/lib/templates/config.yaml +45 -0
- data/lib/templates/default_guest_policy.xml +53 -0
- data/lib/templates/default_policy.xml +53 -0
- data/lib/to-html.rb +112 -0
- data/lib/validation.rb +183 -57
- metadata +31 -94
- data/README.rdoc +0 -23
data/lib/helper.rb
CHANGED
@@ -1,26 +1,99 @@
|
|
1
1
|
helpers do
|
2
2
|
|
3
|
-
|
4
|
-
def protected!
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
# Authentification
|
4
|
+
def protected!(subjectid)
|
5
|
+
if env["session"]
|
6
|
+
unless authorized?(subjectid)
|
7
|
+
flash[:notice] = "You don't have access to this section: "
|
8
|
+
redirect back
|
9
|
+
end
|
10
|
+
elsif !env["session"] && subjectid
|
11
|
+
unless authorized?(subjectid)
|
12
|
+
LOGGER.debug "URI not authorized: clean: " + clean_uri("#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}").to_s + " full: #{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']} with request: #{request.env['REQUEST_METHOD']}"
|
13
|
+
raise OpenTox::NotAuthorizedError.new "Not authorized"
|
14
|
+
end
|
15
|
+
else
|
16
|
+
raise OpenTox::NotAuthorizedError.new "Not authorized" unless authorized?(subjectid)
|
17
|
+
end
|
8
18
|
end
|
9
19
|
|
10
|
-
|
11
|
-
|
12
|
-
|
20
|
+
#Check Authorization for URI with method and subjectid.
|
21
|
+
def authorized?(subjectid)
|
22
|
+
request_method = request.env['REQUEST_METHOD']
|
23
|
+
uri = clean_uri("#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}")
|
24
|
+
request_method = "GET" if request_method == "POST" && uri =~ /\/model\/\d+\/?$/
|
25
|
+
return OpenTox::Authorization.authorized?(uri, request_method, subjectid)
|
13
26
|
end
|
14
27
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
=
|
28
|
+
#cleans URI from querystring and file-extension. Sets port 80 to emptystring
|
29
|
+
# @param [String] uri
|
30
|
+
def clean_uri(uri)
|
31
|
+
uri = uri.sub(" ", "%20") #dirty hacks => to fix
|
32
|
+
uri = uri[0,uri.index("InChI=")] if uri.index("InChI=")
|
33
|
+
|
34
|
+
out = URI.parse(uri)
|
35
|
+
out.path = out.path[0, out.path.length - (out.path.reverse.rindex(/\/{1}\d+\/{1}/))] if out.path.index(/\/{1}\d+\/{1}/) #cuts after /id/ for a&a
|
36
|
+
port = (out.scheme=="http" && out.port==80)||(out.scheme=="https" && out.port==443) ? "" : ":#{out.port.to_s}"
|
37
|
+
"#{out.scheme}://#{out.host}#{port}#{out.path.chomp("/")}" #"
|
38
|
+
end
|
39
|
+
|
40
|
+
#unprotected uri for login
|
41
|
+
def login_requests
|
42
|
+
return env['REQUEST_URI'] =~ /\/login$/
|
43
|
+
end
|
44
|
+
|
45
|
+
def uri_available?(urlStr)
|
46
|
+
url = URI.parse(urlStr)
|
47
|
+
unless @subjectid
|
48
|
+
Net::HTTP.start(url.host, url.port) do |http|
|
49
|
+
return http.head(url.request_uri).code == "200"
|
50
|
+
end
|
51
|
+
else
|
52
|
+
Net::HTTP.start(url.host, url.port) do |http|
|
53
|
+
return http.post(url.request_uri, "subjectid=#{@subjectid}").code == "202"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
24
57
|
|
25
58
|
end
|
26
59
|
|
60
|
+
before do
|
61
|
+
unless !AA_SERVER or login_requests or CONFIG[:authorization][:free_request].include?(env['REQUEST_METHOD'])
|
62
|
+
begin
|
63
|
+
subjectid = nil
|
64
|
+
subjectid = session[:subjectid] if session[:subjectid]
|
65
|
+
subjectid = params[:subjectid] if params[:subjectid] and !subjectid
|
66
|
+
subjectid = request.env['HTTP_SUBJECTID'] if request.env['HTTP_SUBJECTID'] and !subjectid
|
67
|
+
subjectid = request.cookies["subjectid"] unless subjectid
|
68
|
+
# see http://rack.rubyforge.org/doc/SPEC.html
|
69
|
+
subjectid = CGI.unescape(subjectid) if subjectid.include?("%23")
|
70
|
+
@subjectid = subjectid
|
71
|
+
rescue
|
72
|
+
#LOGGER.debug "OpenTox ruby api wrapper: helper before filter: NO subjectid for URI: #{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}"
|
73
|
+
subjectid = ""
|
74
|
+
end
|
75
|
+
@subjectid = subjectid
|
76
|
+
protected!(subjectid)
|
77
|
+
|
78
|
+
extension = File.extname(request.path_info) # params[:id] is not yet available
|
79
|
+
unless extension.empty?
|
80
|
+
#request.path_info.sub!(/\.#{extension}$/,'')
|
81
|
+
case extension
|
82
|
+
when "html"
|
83
|
+
@accept = 'text/html'
|
84
|
+
when "yaml"
|
85
|
+
@accept = 'application/x-yaml'
|
86
|
+
when "csv"
|
87
|
+
@accept = 'text/csv'
|
88
|
+
when "rdfxml"
|
89
|
+
@accept = 'application/rdf+xml'
|
90
|
+
when "xls"
|
91
|
+
@accept = 'application/ms-excel'
|
92
|
+
else
|
93
|
+
halt 404, "File format #{extension} not supported."
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
data/lib/model.rb
CHANGED
@@ -6,33 +6,71 @@ module OpenTox
|
|
6
6
|
|
7
7
|
# Run a model with parameters
|
8
8
|
# @param [Hash] params Parameters for OpenTox model
|
9
|
+
# @param [optional,OpenTox::Task] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
|
9
10
|
# @return [text/uri-list] Task or resource URI
|
10
|
-
def run(params)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
RestClientWrapper.post(@uri,{:accept => accept},params).to_s
|
18
|
-
rescue => e
|
19
|
-
LOGGER.error "Failed to run #{@uri} with #{params.inspect} (#{e.inspect})"
|
20
|
-
raise "Failed to run #{@uri} with #{params.inspect}"
|
11
|
+
def run( params, accept_header=nil, waiting_task=nil )
|
12
|
+
unless accept_header
|
13
|
+
if CONFIG[:yaml_hosts].include?(URI.parse(@uri).host)
|
14
|
+
accept_header = 'application/x-yaml'
|
15
|
+
else
|
16
|
+
accept_header = 'application/rdf+xml'
|
17
|
+
end
|
21
18
|
end
|
19
|
+
LOGGER.info "running model "+@uri.to_s+", params: "+params.inspect+", accept: "+accept_header.to_s
|
20
|
+
RestClientWrapper.post(@uri,params,{:accept => accept_header},waiting_task).to_s
|
22
21
|
end
|
23
22
|
|
24
23
|
# Generic OpenTox model class for all API compliant services
|
25
24
|
class Generic
|
26
25
|
include Model
|
26
|
+
|
27
|
+
# Find Generic Opentox Model via URI, and loads metadata, could raise NotFound/NotAuthorized error
|
28
|
+
# @param [String] uri Model URI
|
29
|
+
# @return [OpenTox::Model::Generic] Model instance
|
30
|
+
def self.find(uri,subjectid=nil)
|
31
|
+
return nil unless uri
|
32
|
+
model = Generic.new(uri)
|
33
|
+
model.load_metadata(subjectid)
|
34
|
+
raise "could not load model metadata '"+uri.to_s+"'" if model.metadata==nil or model.metadata.size==0
|
35
|
+
model
|
36
|
+
end
|
37
|
+
|
38
|
+
# provides feature type, possible types are "regression" or "classification"
|
39
|
+
# @return [String] feature type, "unknown" if type could not be estimated
|
40
|
+
def feature_type(subjectid=nil)
|
41
|
+
return @feature_type if @feature_type
|
42
|
+
|
43
|
+
# dynamically perform restcalls if necessary
|
44
|
+
load_metadata(subjectid) if @metadata==nil or @metadata.size==0 or (@metadata.size==1 && @metadata.values[0]==@uri)
|
45
|
+
algorithm = OpenTox::Algorithm::Generic.find(@metadata[OT.algorithm], subjectid)
|
46
|
+
algorithm_title = algorithm ? algorithm.metadata[DC.title] : nil
|
47
|
+
algorithm_type = algorithm ? algorithm.metadata[OT.isA] : nil
|
48
|
+
dependent_variable = OpenTox::Feature.find( @metadata[OT.dependentVariables],subjectid )
|
49
|
+
dependent_variable_type = dependent_variable ? dependent_variable.feature_type : nil
|
50
|
+
type_indicators = [dependent_variable_type, @metadata[OT.isA], @metadata[DC.title],
|
51
|
+
@uri, algorithm_type, algorithm_title]
|
52
|
+
type_indicators.each do |type|
|
53
|
+
case type
|
54
|
+
when /(?i)classification/
|
55
|
+
@feature_type = "classification"
|
56
|
+
break
|
57
|
+
when /(?i)regression/
|
58
|
+
@feature_type = "regression"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
raise "unknown model "+type_indicators.inspect unless @feature_type
|
62
|
+
@feature_type
|
63
|
+
end
|
64
|
+
|
27
65
|
end
|
28
|
-
|
66
|
+
|
29
67
|
# Lazy Structure Activity Relationship class
|
30
68
|
class Lazar
|
31
69
|
|
32
70
|
include Model
|
33
71
|
include Algorithm
|
34
72
|
|
35
|
-
attr_accessor :compound, :prediction_dataset, :features, :effects, :activities, :p_values, :fingerprints, :feature_calculation_algorithm, :similarity_algorithm, :prediction_algorithm, :min_sim
|
73
|
+
attr_accessor :compound, :prediction_dataset, :features, :effects, :activities, :p_values, :fingerprints, :feature_calculation_algorithm, :similarity_algorithm, :prediction_algorithm, :min_sim, :subjectid
|
36
74
|
|
37
75
|
def initialize(uri=nil)
|
38
76
|
|
@@ -60,15 +98,15 @@ module OpenTox
|
|
60
98
|
|
61
99
|
# Get URIs of all lazar models
|
62
100
|
# @return [Array] List of lazar model URIs
|
63
|
-
def self.all
|
64
|
-
RestClientWrapper.get(CONFIG[:services]["opentox-model"]).to_s.split("\n")
|
101
|
+
def self.all(subjectid=nil)
|
102
|
+
RestClientWrapper.get(CONFIG[:services]["opentox-model"], :subjectid => subjectid).to_s.split("\n")
|
65
103
|
end
|
66
104
|
|
67
105
|
# Find a lazar model
|
68
106
|
# @param [String] uri Model URI
|
69
107
|
# @return [OpenTox::Model::Lazar] lazar model
|
70
|
-
def self.find(uri)
|
71
|
-
YAML.load RestClientWrapper.get(uri
|
108
|
+
def self.find(uri, subjectid=nil)
|
109
|
+
YAML.load RestClientWrapper.get(uri,{:accept => 'application/x-yaml', :subjectid => subjectid})
|
72
110
|
end
|
73
111
|
|
74
112
|
# Create a new lazar model
|
@@ -77,7 +115,7 @@ module OpenTox
|
|
77
115
|
def self.create(params)
|
78
116
|
lazar_algorithm = OpenTox::Algorithm::Generic.new File.join( CONFIG[:services]["opentox-algorithm"],"lazar")
|
79
117
|
model_uri = lazar_algorithm.run(params)
|
80
|
-
OpenTox::Model::Lazar.find(model_uri)
|
118
|
+
OpenTox::Model::Lazar.find(model_uri, params[:subjectid])
|
81
119
|
end
|
82
120
|
|
83
121
|
# Get a parameter value
|
@@ -89,21 +127,30 @@ module OpenTox
|
|
89
127
|
|
90
128
|
# Predict a dataset
|
91
129
|
# @param [String] dataset_uri Dataset URI
|
130
|
+
# @param [optional,subjectid]
|
131
|
+
# @param [optional,OpenTox::Task] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
|
92
132
|
# @return [OpenTox::Dataset] Dataset with predictions
|
93
|
-
def predict_dataset(dataset_uri)
|
94
|
-
@prediction_dataset = Dataset.create
|
133
|
+
def predict_dataset(dataset_uri, subjectid=nil, waiting_task=nil)
|
134
|
+
@prediction_dataset = Dataset.create(CONFIG[:services]["opentox-dataset"], subjectid)
|
95
135
|
@prediction_dataset.add_metadata({
|
96
136
|
OT.hasSource => @uri,
|
97
137
|
DC.creator => @uri,
|
98
138
|
DC.title => URI.decode(File.basename( @metadata[OT.dependentVariables] )),
|
99
139
|
OT.parameters => [{DC.title => "dataset_uri", OT.paramValue => dataset_uri}]
|
100
140
|
})
|
101
|
-
d = Dataset.new(dataset_uri)
|
102
|
-
d.load_compounds
|
141
|
+
d = Dataset.new(dataset_uri,subjectid)
|
142
|
+
d.load_compounds(subjectid)
|
143
|
+
count = 0
|
103
144
|
d.compounds.each do |compound_uri|
|
104
|
-
|
145
|
+
begin
|
146
|
+
predict(compound_uri,false,subjectid)
|
147
|
+
count += 1
|
148
|
+
waiting_task.progress( count/d.compounds.size.to_f*100.0 ) if waiting_task
|
149
|
+
rescue => ex
|
150
|
+
LOGGER.warn "prediction for compound "+compound_uri.to_s+" failed: "+ex.message
|
151
|
+
end
|
105
152
|
end
|
106
|
-
@prediction_dataset.save
|
153
|
+
@prediction_dataset.save(subjectid)
|
107
154
|
@prediction_dataset
|
108
155
|
end
|
109
156
|
|
@@ -111,7 +158,7 @@ module OpenTox
|
|
111
158
|
# @param [String] compound_uri Compound URI
|
112
159
|
# @param [optinal,Boolean] verbose Verbose prediction (output includes neighbors and features)
|
113
160
|
# @return [OpenTox::Dataset] Dataset with prediction
|
114
|
-
def predict(compound_uri,verbose=false)
|
161
|
+
def predict(compound_uri,verbose=false,subjectid=nil)
|
115
162
|
|
116
163
|
@compound = Compound.new compound_uri
|
117
164
|
features = {}
|
@@ -119,7 +166,7 @@ module OpenTox
|
|
119
166
|
unless @prediction_dataset
|
120
167
|
#@prediction_dataset = cached_prediction
|
121
168
|
#return @prediction_dataset if cached_prediction
|
122
|
-
@prediction_dataset = Dataset.create
|
169
|
+
@prediction_dataset = Dataset.create(CONFIG[:services]["opentox-dataset"], subjectid)
|
123
170
|
@prediction_dataset.add_metadata( {
|
124
171
|
OT.hasSource => @uri,
|
125
172
|
DC.creator => @uri,
|
@@ -129,7 +176,7 @@ module OpenTox
|
|
129
176
|
} )
|
130
177
|
end
|
131
178
|
|
132
|
-
return @prediction_dataset if database_activity
|
179
|
+
return @prediction_dataset if database_activity(subjectid)
|
133
180
|
|
134
181
|
neighbors
|
135
182
|
prediction = eval("#{@prediction_algorithm}(@neighbors,{:similarity_algorithm => @similarity_algorithm, :p_values => @p_values})")
|
@@ -217,7 +264,7 @@ module OpenTox
|
|
217
264
|
end
|
218
265
|
end
|
219
266
|
|
220
|
-
@prediction_dataset.save
|
267
|
+
@prediction_dataset.save(subjectid)
|
221
268
|
@prediction_dataset
|
222
269
|
end
|
223
270
|
|
@@ -245,11 +292,11 @@ module OpenTox
|
|
245
292
|
|
246
293
|
# Find database activities and store them in @prediction_dataset
|
247
294
|
# @return [Boolean] true if compound has databasse activities, false if not
|
248
|
-
def database_activity
|
295
|
+
def database_activity(subjectid)
|
249
296
|
if @activities[@compound.uri]
|
250
297
|
@activities[@compound.uri].each { |act| @prediction_dataset.add @compound.uri, @metadata[OT.dependentVariables], act }
|
251
298
|
@prediction_dataset.add_metadata(OT.hasSource => @metadata[OT.trainingDataset])
|
252
|
-
@prediction_dataset.save
|
299
|
+
@prediction_dataset.save(subjectid)
|
253
300
|
true
|
254
301
|
else
|
255
302
|
false
|
@@ -257,13 +304,13 @@ module OpenTox
|
|
257
304
|
end
|
258
305
|
|
259
306
|
# Save model at model service
|
260
|
-
def save
|
261
|
-
self.uri = RestClientWrapper.post(@uri,{:content_type => "application/x-yaml"}
|
307
|
+
def save(subjectid)
|
308
|
+
self.uri = RestClientWrapper.post(@uri,self.to_yaml,{:content_type => "application/x-yaml", :subjectid => subjectid})
|
262
309
|
end
|
263
310
|
|
264
311
|
# Delete model at model service
|
265
|
-
def delete
|
266
|
-
RestClientWrapper.delete
|
312
|
+
def delete(subjectid)
|
313
|
+
RestClientWrapper.delete(@uri, :subjectid => subjectid) unless @uri == CONFIG[:services]["opentox-model"]
|
267
314
|
end
|
268
315
|
|
269
316
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module OpenTox
|
2
|
+
module OntologyService
|
3
|
+
module Endpoints
|
4
|
+
require 'sparql/client'
|
5
|
+
@sparql = SPARQL::Client.new("http://apps.ideaconsult.net:8080/ontology")
|
6
|
+
def self.qs(classname="Endpoints")
|
7
|
+
return "PREFIX ot:<http://www.opentox.org/api/1.1#>
|
8
|
+
PREFIX ota:<http://www.opentox.org/algorithms.owl#>
|
9
|
+
PREFIX owl:<http://www.w3.org/2002/07/owl#>
|
10
|
+
PREFIX dc:<http://purl.org/dc/elements/1.1/>
|
11
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
12
|
+
PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
13
|
+
PREFIX otee:<http://www.opentox.org/echaEndpoints.owl#>
|
14
|
+
PREFIX toxcast:<http://www.opentox.org/toxcast.owl#>
|
15
|
+
select ?Endpoints ?title ?id
|
16
|
+
where {?Endpoints rdfs:subClassOf otee:#{classname}.
|
17
|
+
OPTIONAL {?Endpoints dc:title ?title}.
|
18
|
+
OPTIONAL {?Endpoints dc:identifier ?id}.}
|
19
|
+
ORDER BY ?title"
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.make_option_list(endpoint="Endpoints", level=1)
|
23
|
+
out = ""
|
24
|
+
results = @sparql.query(qs(endpoint)) rescue results = []
|
25
|
+
results.each do |result|
|
26
|
+
endpointname = result.Endpoints.to_s.split('#').last
|
27
|
+
title = result.bound?(:title) ? result.title : endpointname
|
28
|
+
out += "<option value='#{title}' id='#{endpointname}' class='level_#{level}'>#{title}</option>\n"
|
29
|
+
out += make_option_list(endpointname, level + 1)
|
30
|
+
end
|
31
|
+
return out
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.get_endpoint_selectlist(include_blank=true)
|
35
|
+
out = "<select id='endpoint' name='endpoint'>\n"
|
36
|
+
out += "<option value='' id='please_select'>Please select</option>\n" if include_blank
|
37
|
+
out += make_option_list
|
38
|
+
out += "</select>\n"
|
39
|
+
return out
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/opentox-ruby.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
['rubygems', 'sinatra', 'sinatra/url_for', 'rest_client', 'yaml', 'cgi', 'spork', 'overwrite', 'environment'].each do |lib|
|
1
|
+
['rubygems', 'sinatra', 'sinatra/url_for', 'ohm', 'rest_client', 'yaml', 'cgi', 'spork', 'error', 'overwrite', 'environment'].each do |lib|
|
2
2
|
require lib
|
3
3
|
end
|
4
4
|
|
@@ -8,6 +8,7 @@ rescue LoadError
|
|
8
8
|
puts "Please install Openbabel with 'rake openbabel:install' in the compound component"
|
9
9
|
end
|
10
10
|
|
11
|
-
['opentox', 'compound','dataset', 'parser','serializer', 'algorithm','model','task','validation','feature',
|
11
|
+
['opentox', 'compound','dataset', 'parser','serializer', 'algorithm','model','task','validation','feature',
|
12
|
+
'rest_client_wrapper', 'authorization', 'policy', 'helper', 'to-html' ].each do |lib|
|
12
13
|
require lib
|
13
14
|
end
|
data/lib/opentox.rb
CHANGED
@@ -19,14 +19,14 @@ module OpenTox
|
|
19
19
|
|
20
20
|
# Get all objects from a service
|
21
21
|
# @return [Array] List of available URIs
|
22
|
-
def self.all(uri)
|
23
|
-
RestClientWrapper.get(uri,:accept => "text/uri-list").to_s.split(/\n/)
|
22
|
+
def self.all(uri, subjectid=nil)
|
23
|
+
RestClientWrapper.get(uri,:accept => "text/uri-list", :subjectid => subjectid).to_s.split(/\n/)
|
24
24
|
end
|
25
25
|
|
26
26
|
# Load (and return) metadata from object URI
|
27
27
|
# @return [Hash] Metadata
|
28
|
-
def load_metadata
|
29
|
-
@metadata = Parser::Owl::Generic.new(@uri).load_metadata
|
28
|
+
def load_metadata(subjectid=nil)
|
29
|
+
@metadata = Parser::Owl::Generic.new(@uri).load_metadata(subjectid)
|
30
30
|
@metadata
|
31
31
|
end
|
32
32
|
|
@@ -43,5 +43,10 @@ module OpenTox
|
|
43
43
|
s.to_rdfxml
|
44
44
|
end
|
45
45
|
|
46
|
+
# deletes the resource, deletion should have worked when no RestCallError raised
|
47
|
+
def delete(subjectid=nil)
|
48
|
+
RestClientWrapper.delete(uri,:subjectid => subjectid)
|
49
|
+
end
|
50
|
+
|
46
51
|
end
|
47
52
|
|
data/lib/overwrite.rb
CHANGED
@@ -1,38 +1,91 @@
|
|
1
1
|
# class overwrites aka monkey patches
|
2
|
-
# hack: store sinatra in global var to make url_for and halt methods accessible
|
3
|
-
before{
|
2
|
+
# hack: store sinatra instance in global var $url_provider to make url_for and halt methods accessible
|
3
|
+
before {
|
4
|
+
raise "should not happen, url provider already differently initialized "+
|
5
|
+
$url_provider.request.host.to_s+" != "+self.request.host.to_s if
|
6
|
+
$url_provider and $url_provider.request.host!=self.request.host and
|
7
|
+
$url_provider.request.script_name!=self.request.script_name
|
8
|
+
$url_provider = self
|
9
|
+
# stupid internet explorer does not ask for text/html, add this manually
|
10
|
+
request.env['HTTP_ACCEPT'] += ";text/html" if request.env["HTTP_USER_AGENT"]=~/MSIE/
|
11
|
+
}
|
12
|
+
|
13
|
+
# Error handling
|
14
|
+
# Errors are logged as error and formated according to acccept-header
|
15
|
+
# Non OpenTox::Errors (defined in error.rb) are handled as internal error (500), stacktrace is logged
|
16
|
+
# IMPT: set sinatra settings :show_exceptions + :raise_errors to false in config.ru, otherwise Rack::Showexceptions takes over
|
17
|
+
error Exception do
|
18
|
+
error = request.env['sinatra.error']
|
19
|
+
# log error message and backtrace to logfile
|
20
|
+
LOGGER.error error.class.to_s+": "+error.message
|
21
|
+
LOGGER.error ":\n"+error.backtrace.join("\n")
|
22
|
+
|
23
|
+
actor = "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}"
|
24
|
+
rep = OpenTox::ErrorReport.create(error, actor)
|
25
|
+
|
26
|
+
case request.env['HTTP_ACCEPT']
|
27
|
+
when /rdf/
|
28
|
+
content_type 'application/rdf+xml'
|
29
|
+
halt error.http_code,rep.to_rdfxml
|
30
|
+
when /html/
|
31
|
+
content_type 'text/html'
|
32
|
+
halt error.http_code,(OpenTox.text_to_html rep.to_yaml, @subjectid)
|
33
|
+
else
|
34
|
+
content_type 'application/x-yaml'
|
35
|
+
halt error.http_code,rep.to_yaml
|
36
|
+
end
|
37
|
+
end
|
4
38
|
|
5
39
|
class Sinatra::Base
|
6
|
-
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
40
|
+
|
41
|
+
def return_task( task )
|
42
|
+
code = task.running? ? 202 : 200
|
43
|
+
case request.env['HTTP_ACCEPT']
|
44
|
+
when /rdf/
|
45
|
+
response['Content-Type'] = "application/rdf+xml"
|
46
|
+
halt code,task.to_rdfxml
|
47
|
+
when /yaml/
|
48
|
+
response['Content-Type'] = "application/x-yaml"
|
49
|
+
halt code,task.to_yaml # PENDING differs from task-webservice
|
50
|
+
when /html/
|
51
|
+
response['Content-Type'] = "text/html"
|
52
|
+
halt code,OpenTox.text_to_html(task.to_yaml, @subjectid)
|
53
|
+
else # default /uri-list/
|
54
|
+
response['Content-Type'] = "text/uri-list"
|
55
|
+
halt code,task.uri+"\n"
|
56
|
+
end
|
12
57
|
end
|
13
58
|
end
|
14
59
|
|
15
60
|
class String
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
61
|
+
def task_uri?
|
62
|
+
self.uri? && !self.match(/task/).nil?
|
63
|
+
end
|
64
|
+
|
65
|
+
def dataset_uri?
|
66
|
+
self.uri? && !self.match(/dataset/).nil?
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.model_uri?
|
70
|
+
self.uri? && !self.match(/model/).nil?
|
71
|
+
end
|
27
72
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
73
|
+
def uri?
|
74
|
+
begin
|
75
|
+
u = URI::parse(self)
|
76
|
+
return (u.scheme!=nil and u.host!=nil)
|
77
|
+
rescue URI::InvalidURIError
|
78
|
+
return false
|
35
79
|
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def underscore
|
83
|
+
self.gsub(/::/, '/').
|
84
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
85
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
86
|
+
tr("-", "_").
|
87
|
+
downcase
|
88
|
+
end
|
36
89
|
end
|
37
90
|
|
38
91
|
require 'logger'
|
@@ -52,7 +105,7 @@ class OTLogger < Logger
|
|
52
105
|
n = 2
|
53
106
|
line = lines[n]
|
54
107
|
|
55
|
-
while (line =~ /spork.rb/ or line =~ /create/ or line =~ /
|
108
|
+
while (line =~ /spork.rb/ or line =~ /create/ or line =~ /overwrite.rb/)
|
56
109
|
n += 1
|
57
110
|
line = lines[n]
|
58
111
|
end
|
@@ -63,7 +116,7 @@ class OTLogger < Logger
|
|
63
116
|
end
|
64
117
|
|
65
118
|
def format(msg)
|
66
|
-
pwd.ljust(18)+" :: "+msg.to_s+" :: "+trace
|
119
|
+
pwd.ljust(18)+" :: "+msg.to_s+" :: "+trace
|
67
120
|
end
|
68
121
|
|
69
122
|
def debug(msg)
|
@@ -84,3 +137,9 @@ class OTLogger < Logger
|
|
84
137
|
|
85
138
|
end
|
86
139
|
|
140
|
+
# make migration from datamapper more straightforward
|
141
|
+
class Ohm::Model
|
142
|
+
def self.get(id)
|
143
|
+
self[id]
|
144
|
+
end
|
145
|
+
end
|