summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorch <ch@ch.in-silico.ch>2015-07-08 10:58:24 +0200
committerch <ch@ch.in-silico.ch>2015-07-08 10:58:24 +0200
commit723d731bc08d90a82f22474c9fafcc504eb424d3 (patch)
treecbc147e1dd7079c403e5c25e6a9917e568a41fdb /lib
parent1070a35db8aa6414cf53bcce92c1355986cbc53b (diff)
feature, error and task (almost) working
Diffstat (limited to 'lib')
-rw-r--r--lib/error.rb31
-rw-r--r--lib/opentox.rb95
-rw-r--r--lib/overwrite.rb4
-rw-r--r--lib/rest-client-wrapper.rb12
-rw-r--r--lib/task.rb48
5 files changed, 85 insertions, 105 deletions
diff --git a/lib/error.rb b/lib/error.rb
index 506c542..878ed28 100644
--- a/lib/error.rb
+++ b/lib/error.rb
@@ -8,27 +8,27 @@ module OpenToxError
@error_cause = cause ? OpenToxError::cut_backtrace(cause) : short_backtrace
super message
- #unless self.is_a? Errno::EAGAIN # avoid "Resource temporarily unavailable" errors
@uri = uri.to_s.sub(%r{//.*:.*@},'//') # remove credentials from uri
@http_code ||= 500
- @rdf = RDF::Graph.new
- subject = RDF::Node.new
- @rdf << [subject, RDF.type, RDF::OT.ErrorReport]
- @rdf << [subject, RDF::OT.actor, @uri]
- @rdf << [subject, RDF::OT.message, message.to_s]
- @rdf << [subject, RDF::OT.statusCode, @http_code]
- @rdf << [subject, RDF::OT.errorCode, self.class.to_s]
- @rdf << [subject, RDF::OT.errorCause, @error_cause]
- $logger.error("\n"+self.to_yaml)
- #end
+ @metadata = {
+ :type => "ErrorReport",
+ :actor => @uri,
+ :message => message.to_s,
+ :statusCode => @http_code,
+ :errorCode => self.class.to_s,
+ :errorCause => @error_cause,
+ }
+ $logger.error("\n"+JSON.pretty_generate(@metadata))
end
+=begin
# this method defines what is used for to_yaml (override to skip large @rdf graph)
def encode_with coder
@rdf.each do |statement|
coder[statement.predicate.fragment.to_s] = statement.object.to_s
end
end
+=end
def self.cut_backtrace(trace)
if trace.is_a?(Array)
@@ -36,7 +36,7 @@ module OpenToxError
cut_index ||= trace.size
cut_index -= 1
cut_index = trace.size-1 if cut_index < 0
- trace[0..cut_index].join("\n")
+ trace[0..cut_index]
else
trace
end
@@ -47,6 +47,7 @@ module OpenToxError
OpenToxError::cut_backtrace(backtrace)
end
+=begin
RDF_FORMATS.each do |format|
# rdf serialization methods for all formats e.g. to_rdfxml
send :define_method, "to_#{format}".to_sym do
@@ -63,11 +64,15 @@ module OpenToxError
@rdf.each{|statement| writer << statement} if @rdf
end
end
+=end
+
+ def to_json
+ @metadata.to_json
+ end
end
class RuntimeError
-#class StandardError
include OpenToxError
end
diff --git a/lib/opentox.rb b/lib/opentox.rb
index 9564e9c..850ef4b 100644
--- a/lib/opentox.rb
+++ b/lib/opentox.rb
@@ -3,7 +3,6 @@ $logger = OTLogger.new(STDERR)
$logger.level = Logger::DEBUG
module OpenTox
- #include RDF CH: leads to namespace clashes with URI class
attr_reader :uri
attr_writer :metadata, :parameters
@@ -14,20 +13,16 @@ module OpenTox
# @param uri [optional,String] URI
# @return [OpenTox] OpenTox object
def initialize uri=nil
- @rdf = RDF::Graph.new
@metadata = {}
- @parameters = []
+ @metadata[:type] = self.class.to_s.split(/::/).last
+ #@parameters = []
uri ? @uri = uri.to_s.chomp : @uri = File.join(service_uri, SecureRandom.uuid)
end
# Object metadata (lazy loading)
# @return [Hash] Object metadata
def metadata force_update=false
- if (@metadata.nil? or @metadata.empty? or force_update) and URI.accessible? @uri
- get if @rdf.nil? or @rdf.empty? or force_update
- # return values as plain strings instead of RDF objects
- @metadata = @rdf.to_hash[RDF::URI.new(@uri)].inject({}) { |h, (predicate, values)| h[predicate] = values.collect{|v| v.to_s}; h }
- end
+ get #if (@metadata.nil? or @metadata.empty? or force_update) and URI.accessible? @uri
@metadata
end
@@ -35,6 +30,7 @@ module OpenTox
# @param predicate [String] Predicate URI
# @return [Array, String] Predicate value(s)
def [](predicate)
+ predicate = predicate.to_s
return nil if metadata[predicate].nil?
metadata[predicate].size == 1 ? metadata[predicate].first : metadata[predicate]
end
@@ -43,15 +39,17 @@ module OpenTox
# @param predicate [String] Predicate URI
# @param values [Array, String] Predicate value(s)
def []=(predicate,values)
+ predicate = predicate.to_s
@metadata[predicate] = [values].flatten
end
+=begin
# Object parameters (lazy loading)
# {http://opentox.org/dev/apis/api-1.2/interfaces OpenTox API}
# @return [Hash] Object parameters
def parameters force_update=false
if (@parameters.empty? or force_update) and URI.accessible? @uri
- get if @rdf.empty? or force_update
+ get #if @rdf.empty? or force_update
params = {}
query = RDF::Query.new({
:parameter => {
@@ -74,20 +72,28 @@ module OpenTox
def parameter_value title
@parameters.collect{|p| p[RDF::OT.paramValue] if p[RDF::DC.title] == title}.compact.first
end
+=end
# Get object from webservice
# @param [String,optional] mime_type
- def get mime_type="text/plain"
- bad_request_error "Mime type #{mime_type} is not supported. Please use 'text/plain' (default) or 'application/rdf+xml'." unless mime_type == "text/plain" or mime_type == "application/rdf+xml"
+ def get mime_type="application/json"
+ bad_request_error "Mime type #{mime_type} is not supported. Please use 'application/json' (default), 'text/plain' (ntriples) or mime_type == 'application/rdf+xml'." unless mime_type == "application/json" or mime_type == "text/plain" or mime_type == "application/rdf+xml"
response = RestClientWrapper.get(@uri,{},{:accept => mime_type})
if URI.task?(response)
uri = wait_for_task response
response = RestClientWrapper.get(uri,{},{:accept => mime_type})
end
- parse_ntriples response if mime_type == "text/plain"
- parse_rdfxml response if mime_type == "application/rdf+xml"
+ case mime_type
+ when 'application/json'
+ @metadata = JSON.parse(response)
+ when "text/plain"
+ parse_ntriples response
+ when "application/rdf+xml"
+ parse_rdfxml response
+ end
end
+=begin
# Post object to webservice (append to object), rarely useful and deprecated
# @deprecated
def post wait=true, mime_type="text/plain"
@@ -102,17 +108,20 @@ module OpenTox
uri = RestClientWrapper.post @uri.to_s, body, { :content_type => mime_type}
wait ? wait_for_task(uri) : uri
end
+=end
# Save object at webservice (replace or create object)
- def put wait=true, mime_type="text/plain"
- bad_request_error "Mime type #{mime_type} is not supported. Please use 'text/plain' (default) or 'application/rdf+xml'." unless mime_type == "text/plain" or mime_type == "application/rdf+xml"
- @metadata[RDF::OT.created_at] = DateTime.now unless URI.accessible? @uri
+ def put wait=true, mime_type="application/json"
+ bad_request_error "Mime type #{mime_type} is not supported. Please use 'application/json' (default)." unless mime_type == "application/json" or mime_type == "text/plain" or mime_type == "application/rdf+xml"
+ @metadata[:created_at] = DateTime.now unless URI.accessible? @uri
#@metadata[RDF::DC.modified] = DateTime.now
case mime_type
when 'text/plain'
body = self.to_ntriples
when 'application/rdf+xml'
body = self.to_rdfxml
+ when 'application/json'
+ body = self.to_json
end
uri = RestClientWrapper.put @uri, body, { :content_type => mime_type}
wait ? wait_for_task(uri) : uri
@@ -157,8 +166,11 @@ module OpenTox
RDF::Reader.for(format).new(rdf) do |reader|
reader.each_statement{ |statement| @rdf << statement }
end
+ # return values as plain strings instead of RDF objects
+ @metadata = @rdf.to_hash[RDF::URI.new(@uri)].inject({}) { |h, (predicate, values)| h[predicate] = values.collect{|v| v.to_s}; h }
end
+=begin
# rdf serialization methods for all formats e.g. to_rdfxml
send :define_method, "to_#{format}".to_sym do
create_rdf
@@ -170,6 +182,7 @@ module OpenTox
end
end
end
+=end
end
# @return [String] converts object to turtle-string
@@ -182,20 +195,28 @@ module OpenTox
end
end
+ def to_json
+ @metadata[:uri] = @uri
+ @metadata.to_json
+ end
+
# @return [String] converts OpenTox object into html document (by first converting it to a string)
def to_html
to_turtle.to_html
end
+=begin
# short access for metadata keys title, description and type
- { :title => RDF::DC.title, :description => RDF::DC.description, :type => RDF.type }.each do |method,predicate|
+ #{ :title => RDF::DC.title, :description => RDF::DC.description, :type => RDF.type }.each do |method,predicate|
+ [ :title , :description, :type ].each do |method|
send :define_method, method do
- self.[](predicate)
+ self.[](method)
end
send :define_method, "#{method}=" do |value|
- self.[]=(predicate,value)
+ self.[]=(method,value)
end
end
+=end
# define class methods within module
def self.included(base)
@@ -242,40 +263,8 @@ module OpenTox
end
def self.find_or_create metadata
- t = Time.now
- sparql = "SELECT DISTINCT ?s WHERE { "
- # flatten 3.level arrays in objects
- metadata.each{|p,o| o.flatten! if o.is_a? Array}
- metadata.each do |predicate,objects|
- unless [RDF::DC.date,RDF::DC.modified,RDF::DC.description].include? predicate # remove dates and description (strange characters in description may lead to SPARQL errors)
- if objects.is_a? String
- #URI.valid?(objects) ? o = "<#{objects}>" : o = "'''#{objects}'''" #DG: do not understand this quotation
- URI.valid?(objects) ? o = "<#{objects}>" : o = "\"#{objects}\""
- sparql << "?s <#{predicate}> #{o}. "
- elsif objects.is_a? Array
- objects.each do |object|
- #URI.valid?(object) ? o = "<#{object}>" : o = "'#{object}'" #DG: do not understand this quotation
- URI.valid?(object) ? o = "<#{object}>" : o = "\"#{object}\""
- sparql << "?s <#{predicate}> #{o}. "
- end
- end
- end
- end
- sparql << "}"
- puts "Create SPARQL: #{Time.now-t}"
- t = Time.new
- uris = RestClientWrapper.get(service_uri,{:query => sparql},{:accept => "text/uri-list"}).split("\n")
- puts "Query: #{Time.now-t}"
- t = Time.new
- if uris.empty?
- f=self.create metadata
- puts "Create: #{Time.now-t}"
- f
- else
- f=self.new uris.first
- puts "Found: #{Time.now-t}"
- f
- end
+ uris = RestClientWrapper.get(service_uri,{:query => metadata},{:accept => "text/uri-list"}).split("\n")
+ uris.empty? ? self.create(metadata) : self.new(uris.first)
end
end
OpenTox.const_set klass,c
diff --git a/lib/overwrite.rb b/lib/overwrite.rb
index c96c2d8..692e239 100644
--- a/lib/overwrite.rb
+++ b/lib/overwrite.rb
@@ -158,8 +158,8 @@ module Kernel
error = OpenTox::RestClientWrapper.known_errors.select{|error| error[:code] == t.code}.first
error_method = error ? error[:method] : :internal_server_error
report = t.error_report
- error_message = report ? report[RDF::OT.message] : $!.message
- error_cause = report ? report[RDF::OT.errorCause] : nil
+ error_message = report ? report[:message] : $!.message
+ error_cause = report ? report[:errorCause] : nil
Object.send(error_method,error_message,t.uri,error_cause)
end
uri = t.resultURI
diff --git a/lib/rest-client-wrapper.rb b/lib/rest-client-wrapper.rb
index 7011eca..de1b74f 100644
--- a/lib/rest-client-wrapper.rb
+++ b/lib/rest-client-wrapper.rb
@@ -62,13 +62,11 @@ module OpenTox
#parameters[:url] = parameters[:url].gsub(/(http|https|)\:\/\/[a-zA-Z0-9\-]+\:[a-zA-Z0-9]+\@/, "REMOVED@") if parameters[:url]
#message += "\nREST parameters:\n#{parameters.inspect}"
error = known_errors.collect{|e| e if e[:code] == response.code}.compact.first
- begin # errors are returned as error reports in turtle, try to parse
- content = {}
- RDF::Reader.for(:turtle).new(response) do |reader|
- reader.each_triple{|triple| content[triple[1]] = triple[2]}
- end
- msg = content[RDF::OT.message].to_s
- cause = content[RDF::OT.errorCause].to_s
+ begin # errors are returned as error reports in json, try to parse
+ # TODO: may be the reason for failure of task.rb -n test_11_wait_for_error_task
+ content = JSON.parse(response)
+ msg = content["message"].to_s
+ cause = content["errorCause"].to_s
raise if msg.size==0 && cause.size==0 # parsing failed
rescue # parsing error failed, use complete content as message
msg = "Could not parse error response from rest call '#{method}' to '#{uri}':\n#{response}"
diff --git a/lib/task.rb b/lib/task.rb
index a64e668..7f4d39a 100644
--- a/lib/task.rb
+++ b/lib/task.rb
@@ -17,11 +17,11 @@ module OpenTox
def self.run(description, creator=nil, uri=nil)
task = Task.new uri
- task[RDF::OT.created_at] = DateTime.now
- task[RDF::OT.hasStatus] = "Running"
- task[RDF::DC.description] = description.to_s
- task[RDF::DC.creator] = creator.to_s
- task[RDF::OT.percentageCompleted] = "0"
+ task[:created_at] = DateTime.now
+ task[:hasStatus] = "Running"
+ task[:description] = description.to_s
+ task[:creator] = creator.to_s
+ task[:percentageCompleted] = "0"
task.put
pid = fork do
begin
@@ -30,7 +30,7 @@ module OpenTox
# wrap non-opentox-errors first
e = OpenTox::Error.new(500,e.message,nil,e.backtrace) unless e.is_a?(OpenTox::Error)
$logger.error "error in task #{task.uri} created by #{creator}" # creator is not logged because error is logged when thrown
- RestClientWrapper.put(File.join(task.uri,'Error'),{:errorReport => e.to_ntriples},{:content_type => 'text/plain'})
+ RestClientWrapper.put(File.join(task.uri,'Error'),{:errorReport => e.to_json},{:content_type => 'application/json'})
task.kill
end
end
@@ -59,25 +59,25 @@ module OpenTox
end
def description
- self.[](RDF::DC.description)
+ self.[](:description)
end
def creator
- self.[](RDF::DC.creator)
+ self.[](:creator)
end
def cancel
kill
- self.[]=(RDF::OT.hasStatus, "Cancelled")
- self.[]=(RDF::OT.finished_at, DateTime.now)
+ self.[]=(:hasStatus, "Cancelled")
+ self.[]=(:finished_at, DateTime.now.to_s)
put
end
def completed(uri)
- self.[]=(RDF::OT.resultURI, uri)
- self.[]=(RDF::OT.hasStatus, "Completed")
- self.[]=(RDF::OT.finished_at, DateTime.now)
- self.[]=(RDF::OT.percentageCompleted, "100")
+ self.[]=(:resultURI, uri)
+ self.[]=(:hasStatus, "Completed")
+ self.[]=(:finished_at, DateTime.now.to_s)
+ self.[]=(:percentageCompleted, "100")
put
end
@@ -118,31 +118,19 @@ module OpenTox
[:hasStatus, :resultURI, :created_at, :finished_at, :percentageCompleted].each do |method|
define_method method do
- response = self.[](RDF::OT[method])
- response = self.[](RDF::OT1[method]) unless response # API 1.1 compatibility
- response
+ self.[](method)
end
end
# Check status of a task
# @return [String] Status
def status
- self[RDF::OT.hasStatus]
+ self[:hasStatus]
end
def error_report
- get
- report = {}
- query = RDF::Query.new({
- :report => {
- RDF.type => RDF::OT.ErrorReport,
- :property => :value,
- }
- })
- query.execute(@rdf).each do |solution|
- report[solution.property] = solution.value.to_s
- end
- report
+ #get
+ self[:errorReport]
end
#TODO: subtasks (only for progress in validation)