diff options
author | Martin Gütlein <martin.guetlein@gmail.com> | 2010-04-23 14:20:40 +0200 |
---|---|---|
committer | Martin Gütlein <martin.guetlein@gmail.com> | 2010-04-23 14:20:40 +0200 |
commit | ad974c419a2efe4c0ceaa1f3e2346906b5783e52 (patch) | |
tree | 5c98d81de01a79f39ff9b01d991e9f6041802004 /lib | |
parent | 1926e43b9e2716e7f7248fe183a4d43da1209a1b (diff) |
adjusted task to api, new owl
Diffstat (limited to 'lib')
-rw-r--r-- | lib/model.rb | 27 | ||||
-rw-r--r-- | lib/owl.rb | 251 | ||||
-rw-r--r-- | lib/rest_client_wrapper.rb | 109 | ||||
-rw-r--r-- | lib/task.rb | 144 |
4 files changed, 294 insertions, 237 deletions
diff --git a/lib/model.rb b/lib/model.rb index 3aae652..8b275ed 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -3,7 +3,7 @@ module OpenTox class Generic - attr_accessor :uri, :title, :source, :identifier, :predicted_variables, :independent_variables, :dependent_variables, :activity_dataset_uri, :feature_dataset_uri, :effects, :activities, :p_values, :fingerprints, :features, :algorithm + attr_accessor :uri, :title, :creator, :date, :format, :identifier, :predictedVariables, :independentVariables, :dependentVariables, :trainingDataset, :feature_dataset_uri, :effects, :activities, :p_values, :fingerprints, :features, :algorithm def self.find(uri) owl = OpenTox::Owl.from_uri(uri) @@ -12,23 +12,16 @@ module OpenTox protected def initialize(owl) - @title = owl.title - @source = owl.source - @identifier = owl.identifier.sub(/^\[/,'').sub(/\]$/,'') - @uri = owl.uri.to_s #@identifier - @algorithm = owl.algorithm - @dependent_variables = owl.dependentVariables - @independent_variables = owl.independentVariables - @predicted_variables = owl.predictedVariables - - raise "invalid model:\n"+self.to_yaml+"\n" unless Utils.is_uri?(@uri) && - #@dependent_variables.to_s.size>0 && - #@independent_variables.to_s.size>0 && - @predicted_variables.to_s.size>0 if ENV['RACK_ENV'] =~ /test|debug/ + [:uri, :date, :creator, :title, :format, :identifier, :algorithm, + :dependentVariables, :independentVariables, :predictedVariables, :trainingDataset].each do |a| + self.send("#{a.to_s}=".to_sym, owl.get(a.to_s)) + end + RestClientWrapper.raise_uri_error "invalid model:\n"+ + self.to_yaml+"\n",@uri.to_s unless (Utils.is_uri?(@uri) and + @dependentVariables and @independentVariables and @predictedVariables) if ENV['RACK_ENV'] =~ /test|debug/ end end - class PredictionModel < Generic def self.build( algorithm_uri, algorithm_params ) @@ -41,7 +34,7 @@ module OpenTox LOGGER.debug "Build model, algorithm_uri:"+algorithm_uri.to_s+", algorithm_parms: "+algorithm_params.inspect.to_s uri = OpenTox::RestClientWrapper.post(algorithm_uri,algorithm_params).to_s - RestClientWrapper.illegal_result("Invalid build model result: "+uri.to_s, algorithm_uri, algorithm_params ) unless Utils.model_uri?(uri) + RestClientWrapper.raise_uri_error("Invalid build model result: "+uri.to_s, algorithm_uri, algorithm_params ) unless Utils.model_uri?(uri) return PredictionModel.find(uri) end @@ -49,7 +42,7 @@ module OpenTox LOGGER.debug "Predict dataset: "+dataset_uri.to_s+" with model "+@uri.to_s uri = RestClientWrapper.post(@uri, {:dataset_uri=>dataset_uri}) - RestClientWrapper.illegal_result("Prediciton result no dataset uri: "+uri.to_s, @uri, {:dataset_uri=>dataset_uri} ) unless Utils.dataset_uri?(uri) + RestClientWrapper.raise_uri_error("Prediciton result no dataset uri: "+uri.to_s, @uri, {:dataset_uri=>dataset_uri} ) unless Utils.dataset_uri?(uri) uri end @@ -1,5 +1,9 @@ class Redland::Literal + def self.create(value, datatype) + Redland::Literal.new(value,nil,Redland::Uri.new(datatype)) + end + # the literal node of the ruby swig api provdides the 'value' of a literal but not the 'datatype' # found solution in mailing list def datatype() @@ -12,33 +16,61 @@ end module OpenTox class Owl - - attr_accessor :uri, :ot_class, :model + + # ot_class is the class of the object, e.g. "Model","Dataset", ... + # root_node is the root-object node in the rdf + # identifier is the uri of the object + attr_accessor :ot_class, :root_node, :identifier, :model def initialize @model = Redland::Model.new Redland::MemoryStore.new end - def self.create(ot_class,uri) + def self.create( ot_class, uri ) owl = OpenTox::Owl.new - owl.ot_class = ot_class - owl.uri = Redland::Uri.new(uri.chomp) - owl.model.add owl.uri, RDF['type'], OT[owl.ot_class] - owl.model.add owl.uri, DC['identifier'], owl.uri + owl.ot_class = ot_class + owl.root_node = Redland::Resource.new(uri.chomp+"XYZ") + owl.identifier = uri.chomp + owl.set("type",owl.ot_class) + owl.set('identifier', owl.identifier, "xsd:anyURI") owl end - def self.from_data(data,uri) + def self.from_data(data,base_uri) owl = OpenTox::Owl.new parser = Redland::Parser.new + begin - parser.parse_string_into_model(owl.model, data, uri) + parser.parse_string_into_model(owl.model, data, base_uri) + + # getting object-(root)-node and identifier via identifier property + # PENDING easier solution? + owl.identifier = nil + owl.model.find(nil, owl.node('identifier'), nil) do |s,p,o| + #LOGGER.debug "ID Statements "+s.to_s+" . "+p.to_s+" -> "+o.to_s + root_id = true + owl.model.find(nil, nil, s) do |ss,pp,oo| + root_id = false + break + end + if root_id + if o.is_a?(Redland::Literal) + raise "cannot derieve object uri from rdf, more than one identifier" if owl.identifier + owl.root_node = s + owl.identifier = o.value + else + raise "illegal identifier, not a literal: "+o.to_s + end + end + end + raise "Illegal RDF: root identifier missing" unless owl.identifier + owl.ot_class = owl.get("type") + LOGGER.debug "RDF loaded, uri/identifier:"+owl.identifier+", ot-class: "+owl.ot_class.to_s+", root-node:"+owl.root_node.to_s + owl rescue => e - raise "Error parsing #{uri}: "+e.message + RestClientWrapper.raise_uri_error(e.message, base_uri) end - owl.uri = Redland::Uri.new(uri.chomp) - owl end def self.from_uri(uri) @@ -47,53 +79,49 @@ module OpenTox def rdf @model.to_string - end - - def method_missing(name, *args) - methods = ['title', 'source', 'identifier', 'algorithm', 'independentVariables', 'dependentVariables', 'predictedVariables', 'date','trainingDataset', 'hasStatus', "percentageCompleted" ] - if methods.include? name.to_s.sub(/=/,'') - if /=/ =~ name.to_s # setter - name = name.to_s.sub(/=/,'') - begin # delete existing entry - t = @model.object(@uri, DC[name]) - @model.delete @uri, DC[name], t - rescue - end - @model.add @uri, DC[name], args.first - else # getter - #HACK for reading Panteli's models - if @uri.to_s =~ /194.141.0.136.*model|ambit2.*model|ntua.*model|tu-muenchen.*model/ and !["title", "source", "identifier"].include?(name.to_s) - begin - me = @model.subject(RDF['type'],OT['Model']) - return @model.object(me, OT[name.to_s]).uri.to_s - rescue - LOGGER.warn "cannot get "+name.to_s+" from model" - return nil - end - elsif @uri.to_s =~ /ambit.*task/ and ["hasStatus", "percentageCompleted"].include?(name.to_s) - me = @model.subject(RDF['type'],OT['Task']) - return @model.object(me, OT[name.to_s]).literal.value.to_s - end - #raise "stop there "+name.to_s - val = @model.object(@uri, DC[name.to_s]) - if val.is_a?(Redland::Literal) - return val.value - else - return val.to_s - end - end - else - raise "Method '#{name.to_s}' not found." - end - end + end + + def uri + @identifier + end + + def get(name) + property_node = node(name.to_s) + raise "Method '#{name.to_s}' not found." unless property_node + val = @model.object(@root_node, property_node) + return nil unless val + if val.is_a?(Redland::Literal) + return val.value + else + return val.uri.to_s + end + end + + def set(name, value, datatype=nil) + property_node = node(name.to_s) + raise "Method '#{name.to_s}' not found." unless property_node + begin # delete existing entry + t = @model.object(@root_node, property_node) + @model.delete @root_node, property_node, t + rescue + end + if value.first.is_a?(Redland::Node) + raise "not nil datatype not allowed when setting redland node as value" if datatype + @model.add @root_node, property_node, value + elsif datatype + @model.add @root_node, property_node, Redland::Literal.create(value, datatype) + else + @model.add @root_node, property_node, value + end + end def parameters=(params) params.each do |name, settings| parameter = @model.create_resource - @model.add parameter, RDF['type'], OT['Parameter'] - @model.add parameter, DC['title'], name - @model.add parameter, OT['paramScope'], settings[:scope] - @model.add parameter, OT['paramValue'], settings[:value] + @model.add parameter, node('type'), node('Parameter') + @model.add parameter, node('title'), name + @model.add parameter, node('paramScope'), settings[:scope] + @model.add parameter, node('paramValue'), settings[:value] end end @@ -102,8 +130,8 @@ module OpenTox compound = @model.subject(DC["identifier"], compound_uri) if compound.nil? compound = @model.create_resource(compound_uri) - @model.add compound, RDF['type'], OT["Compound"] - @model.add compound, DC["identifier"], compound_uri + @model.add compound, node('type'), node("Compound") + @model.add compound, node("identifier"), compound_uri end features.each do |f| f.each do |feature_uri,value| @@ -112,51 +140,51 @@ module OpenTox if value.class.to_s == 'Hash' # create tuple tuple = @model.create_resource - @model.add tuple, RDF['type'], OT["Tuple"] - @model.add tuple, OT['feature'], feature + @model.add tuple, node('type'), node("Tuple") + @model.add tuple, node('feature'), feature value.each do |uri,v| f = find_or_create_feature uri complex_value = @model.create_resource - @model.add tuple, OT['complexValue'], complex_value - @model.add complex_value, RDF['type'], OT["FeatureValue"] - @model.add complex_value, OT['feature'], f - @model.add complex_value, OT['value'], v.to_s + @model.add tuple, node('complexValue'), complex_value + @model.add complex_value, node('type'), node("FeatureValue") + @model.add complex_value, node('feature'), f + @model.add complex_value, node('value'), v.to_s end # add data entry - data_entry = @model.subject OT['compound'], compound + data_entry = @model.subject node('compound'), compound if data_entry.nil? data_entry = @model.create_resource - @model.add @uri, OT['dataEntry'], data_entry - @model.add data_entry, RDF['type'], OT["DataEntry"] - @model.add data_entry, OT['compound'], compound + @model.add @root_node, node('dataEntry'), data_entry + @model.add data_entry, node('type'), node("DataEntry") + @model.add data_entry, node('compound'), compound end - @model.add data_entry, OT['values'], tuple + @model.add data_entry, node('values'), tuple else - data_entry = @model.subject OT['compound'], compound + data_entry = @model.subject node('compound'), compound if data_entry.nil? data_entry = @model.create_resource - @model.add @uri, OT['dataEntry'], data_entry - @model.add data_entry, RDF['type'], OT["DataEntry"] - @model.add data_entry, OT['compound'], compound + @model.add @root_node, node('dataEntry'), data_entry + @model.add data_entry,node('type'), node("DataEntry") + @model.add data_entry, node('compound'), compound end values = @model.create_resource - @model.add data_entry, OT['values'], values - @model.add values, RDF['type'], OT['FeatureValue'] - @model.add values, OT['feature'], feature - @model.add values, OT['value'], value.to_s + @model.add data_entry, node('values'), values + @model.add values, node('type'), node('FeatureValue') + @model.add values, node('feature'), feature + @model.add values, node('value'), value.to_s end end end end def find_or_create_feature(feature_uri) - feature = @model.subject(DC["identifier"], feature_uri) + feature = @model.subject(node("identifier"), feature_uri) if feature.nil? feature = @model.create_resource(feature_uri) - @model.add feature, RDF['type'], OT["Feature"] - @model.add feature, DC["identifier"], feature_uri - @model.add feature, DC["title"], File.basename(feature_uri).split(/#/)[1] - @model.add feature, DC['source'], feature_uri + @model.add feature, node('type'), node("Feature") + @model.add feature, node("identifier"), feature_uri + @model.add feature, node("title"), File.basename(feature_uri).split(/#/)[1] + @model.add feature, node('creator'), feature_uri end feature end @@ -164,15 +192,13 @@ module OpenTox # feature values are not loaded for performance reasons # loading compounds and features into arrays that are given as params def load_dataset( compounds, features ) - ot_compound = OT['compound'] - dc_identifier = DC['identifier'] - @model.subjects(RDF['type'], OT['DataEntry']).each do |data_entry| - compound_node = @model.object(data_entry, ot_compound) - compound_uri = @model.object(compound_node, dc_identifier).to_s + @model.subjects(node('type'), node('DataEntry')).each do |data_entry| + compound_node = @model.object(data_entry, node('compound')) + compound_uri = @model.object(compound_node, node('identifier')).to_s compounds << compound_uri end - @model.subjects(RDF['type'], OT['Feature']).each do |feature| - feature_literal = @model.object(feature, dc_identifier) + @model.subjects(node('type'), node('Feature')).each do |feature| + feature_literal = @model.object(feature, node('identifier')) raise "feature is no literal" unless feature_literal.is_a?(Redland::Literal) # PENDING: to be able to recreate literal nodes for features, the datatype is stored @@feature_datatype = feature_literal.datatype @@ -194,24 +220,16 @@ module OpenTox # values are stored in the data-hash, hash has a key for each compound compounds.each{|c| data[c] = [] unless data[c]} - ot_values = OT['values'] - ot_feature = OT['feature'] - ot_compound = OT['compound'] - dc_identifier = DC['identifier'] - ot_value = OT['value'] - rdf_type = RDF['type'] - ot_feature_value = OT['FeatureValue'] - load_all_features = feature_uri==nil feature_node = nil # create feature node for feature uri if specified unless load_all_features feature_literal = Redland::Literal.new(feature_uri,nil,Redland::Uri.new(@@feature_datatype)) - feature_node = @model.subject(dc_identifier, feature_literal) + feature_node = @model.subject(node('identifier'), feature_literal) # remark: solution without creating the literal node: #@model.subjects(RDF['type'], OT['Feature']).each do |feature| - # f_uri = @model.object(feature, dc_identifier).value + # f_uri = @model.object(feature, node('identifier')).value # if feature_uri==f_uri # feature_node = feature # break @@ -230,14 +248,14 @@ module OpenTox # feature_node is either nil, i.e. a wildcard or specified @model.find(nil, ot_feature, feature_node) do |feature_value_node,p,o| - # get compound_uri by "backtracking" to values node (property is 'ot_values'), then get compound_node via 'ot_compound' - value_nodes = @model.subjects(ot_values,feature_value_node) + # get compound_uri by "backtracking" to values node (property is 'values'), then get compound_node via 'compound' + value_nodes = @model.subjects(node('values'),feature_value_node) raise "more than one value node "+value_nodes.size.to_s unless value_nodes.size==1 value_node = value_nodes[0] - compound_node = @model.object(value_node, ot_compound) + compound_node = @model.object(value_node, node('compound')) compound_uri = compound_uri_store[compound_node.to_s] unless compound_uri - compound_uri = @model.object(compound_node, dc_identifier).to_s + compound_uri = @model.object(compound_node, node('identifier')).to_s compound_uri_store[compound_node.to_s] = compound_uri end @@ -245,16 +263,16 @@ module OpenTox # if load all features, feautre_uri is not specified, derieve from feature_node feature_uri = feature_uri_store[o.to_s] unless feature_uri - feature_literal = @model.object(o, dc_identifier) + feature_literal = @model.object(o, node('identifier')) raise "feature is no literal" unless feature_literal.is_a?(Redland::Literal) feature_uri = feature_literal.value feature_uri_store[o.to_s] = feature_uri end end - value_node_type = @model.object(feature_value_node, rdf_type) - if (value_node_type == ot_feature_value) - value_literal = @model.object( feature_value_node, ot_value) + value_node_type = @model.object(feature_value_node, node('type')) + if (value_node_type == node('FeatureValue')) + value_literal = @model.object( feature_value_node, node('value')) raise "feature value no literal" unless value_literal.is_a?(Redland::Literal) case value_literal.datatype @@ -273,7 +291,27 @@ module OpenTox end LOGGER.debug "loaded "+count.to_s+" feature values" + end + + @@property_nodes = { "type" => RDF["type"], + "title" => DC["title"], + "creator" => DC["creator"], + "uri" => DC["identifier"], + "identifier" => DC["identifier"], + "date" => DC["date"], + "format" => DC["format"]} + + # this method has to purposes: + # * distinguishing ot-properties from dc- and rdf- properties + # * caching nodes, as creating nodes is costly + def node(name) + n = @@property_nodes[name] + unless n + n = OT[name] + @@property_nodes[name] = n end + return n + end =begin def data @@ -341,3 +379,4 @@ module OpenTox end end + diff --git a/lib/rest_client_wrapper.rb b/lib/rest_client_wrapper.rb index eaf6616..5a6362b 100644 --- a/lib/rest_client_wrapper.rb +++ b/lib/rest_client_wrapper.rb @@ -1,3 +1,5 @@ + + module OpenTox #PENDING: implement ot error api, move to own file @@ -28,7 +30,11 @@ module OpenTox end - module RestClientWrapper + class WrapperResult < String + attr_accessor :content_type + end + + class RestClientWrapper # PENDING: remove as soon as redirect tasks are remove from partner webservices def self.redirect_task( uri ) @@ -53,77 +59,88 @@ module OpenTox return uri end - def self.get(uri, headers=nil, curl_hack=false) - execute( "get", uri, headers, nil, curl_hack ) + def self.get(uri, headers=nil) + execute( "get", uri, headers) end - def self.post(uri, headers, payload=nil, curl_hack=false) - raise "payload and headers switched" if payload.is_a?(Hash) and headers==nil - raise "illegal headers" unless headers==nil || headers.is_a?(Hash) - execute( "post", uri, headers, payload, curl_hack ) + def self.post(uri, headers, payload=nil, wait=true) + execute( "post", uri, headers, payload, wait ) + end + + def self.put(uri, headers, payload=nil ) + execute( "put", uri, headers, payload ) end - def self.delete(uri, headers=nil, curl_hack=false) - execute( "delete", uri, headers, nil, curl_hack ) + def self.delete(uri, headers=nil) + execute( "delete", uri, headers, nil) end - def self.illegal_result(error_msg, uri, headers, payload=nil) + def self.raise_uri_error(error_msg, uri, headers=nil, payload=nil) do_halt( "-", error_msg, uri, headers, payload ) end private - def self.execute( rest_call, uri, headers, payload=nil, curl_hack=false ) + def self.execute( rest_call, uri, headers, payload=nil, wait=true ) do_halt 400,"uri is null",uri,headers,payload unless uri - do_halt 400,"not an uri",uri,headers,payload unless Utils.is_uri?(uri) + do_halt 400,"not a uri",uri,headers,payload unless Utils.is_uri?(uri) do_halt 400,"headers are no hash",uri,headers,payload unless headers==nil or headers.is_a?(Hash) headers.each{ |k,v| headers.delete(k) if v==nil } if headers #remove keys with empty values, as this can cause problems begin - unless curl_hack - - #LOGGER.debug "RestCall: "+rest_call.to_s+" "+uri.to_s+" "+headers.inspect - resource = RestClient::Resource.new(uri, :timeout => 60) - if payload - result = resource.send(rest_call, payload, headers).to_s - #result = RestClient.send(rest_call, uri, payload, headers).to_s - elsif headers - #result = RestClient.send(rest_call, uri, headers).to_s - result = resource.send(rest_call, headers).to_s - else - result = resource.send(rest_call).to_s - end + #LOGGER.debug "RestCall: "+rest_call.to_s+" "+uri.to_s+" "+headers.inspect + resource = RestClient::Resource.new(uri,{:timeout => 60, :user => @@users[:users].keys[0], :password => @@users[:users].values[0]}) + if payload + result = resource.send(rest_call, payload, headers) + elsif headers + result = resource.send(rest_call, headers) else - result = "" - cmd = " curl -v -X "+rest_call.upcase+" "+payload.collect{|k,v| "-d "+k.to_s+"='"+v.to_s+"' "}.join("")+" "+uri.to_s - LOGGER.debug "CURL HACK: "+cmd - IO.popen(cmd+" 2> /dev/null") do |f| - while line = f.gets - result += line - end + result = resource.send(rest_call) + end + + # result is a string, with the additional filed content_type + res = WrapperResult.new(result.to_s) + res.content_type = result.headers[:content_type] + + # get result cannot be a task + return res if rest_call=="get" or !wait + return res if res.strip.size==0 + + # try to load task from result (maybe task-uri, or task-object) + task = nil + case res.content_type + when /application\/rdf\+xml|text\/x-yaml/ + task = OpenTox::Task.from_data(res, res.content_type, uri) + when /text\// + return res if res.content_type=~/text\/uri-list/ and + res.split("\n").size > 1 #if uri list contains more then one uri, its not a task + # HACK for redirect tasks + if res =~ /ambit.*task|tu-muenchen.*task/ + res = WrapperResult.new(redirect_task(res)) + res.content_type = "text/uri-list" + return res end - result.chomp!("\n") - LOGGER.debug "CURL -> "+result.to_s - raise "curl call failed "+result if $?!=0 - #raise "STOP "+result + task = OpenTox::Task.find(res) if Utils.task_uri?(res) + else + raise "unknown content-type when checking for task: "+res.content_type+" content: "+res[0..200] end - - if result.to_s =~ /ambit.*task|tu-muenchen.*task/ - result = redirect_task(result) - elsif Utils.task_uri?(result) - task = OpenTox::Task.find(result) + + # task could be loaded, wait for task to finish + if task + LOGGER.debug "result is a task "+task.uri.to_s+", wait for completion" task.wait_for_completion - raise task.description if task.failed? - result = task.resource + raise task.description if task.error? + res = WrapperResult.new(task.resultURI) + res.content_type = "text/uri-list" end - return result + return res rescue RestClient::RequestFailed => ex do_halt ex.http_code,ex.http_body,uri,headers,payload rescue RestClient::RequestTimeout => ex do_halt 408,ex.message,uri,headers,payload rescue => ex - #raise ex + #raise ex.message+" uri: "+uri.to_s begin code = ex.http_code msg = ex.http_body @@ -145,7 +162,7 @@ module OpenTox error = [Error.new(code, body, uri, payload, headers)] end -# debug utility: write error to file + ##debug utility: write error to file #error_dir = "/tmp/ot_errors" #FileUtils.mkdir(error_dir) unless File.exist?(error_dir) #raise "could not create error dir" unless File.exist?(error_dir) and File.directory?(error_dir) diff --git a/lib/task.rb b/lib/task.rb index 29fb4fe..dee8a86 100644 --- a/lib/task.rb +++ b/lib/task.rb @@ -4,96 +4,105 @@ module OpenTox class Task - attr_accessor :uri + TASK_ATTRIBS = [ :uri, :date, :title, :creator, :title, :description, :hasStatus, :percentageCompleted, :resultURI ] + TASK_ATTRIBS.each{ |a| attr_accessor(a) } - def initialize(uri) - @uri = uri.chomp - end - - def self.create - resource = RestClient::Resource.new(@@config[:services]["opentox-task"], :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) - uri = resource.post({}).chomp - Task.new(uri.chomp) + private + def initialize(uri) + @uri = uri + end + + public + def self.create + task_uri = RestClientWrapper.post(@@config[:services]["opentox-task"], nil, nil, false).to_s + Task.find(task_uri.chomp) end def self.find(uri) - Task.new(uri) - end - - def self.base_uri - @@config[:services]["opentox-task"] - end - - def self.all - task_uris = RestClient.get(@@config[:services]["opentox-task"]).chomp.split(/\n/) - task_uris.collect{|uri| Task.new(uri)} - end - - def created_at - RestClient.get File.join(@uri, 'created_at') - end - - def finished_at - RestClient.get File.join(@uri, 'finished_at') - end - - def description - RestClient.get File.join(@uri, 'description') + task = Task.new(uri) + task.reload + return task end - def status - RestClient.get File.join(@uri, 'status') - end - - def resource - RestClient.get File.join(@uri, 'resource') - end - - def started - LOGGER.info File.join(@uri,'started') - resource = RestClient::Resource.new(File.join(@uri,'started'), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) - resource.put({}) - end + def self.from_data(data, content_type, base_uri) + begin + task = Task.new(nil) + task.reload_from_data(data, content_type, base_uri) + return task + rescue + return nil + end + end + + def reload + result = RestClientWrapper.get(uri) + reload_from_data(result, result.content_type) + end + + def reload_from_data( data=nil, content_type=nil, base_uri=nil ) + case content_type + when /text\/x-yaml/ + task = YAML.load data + raise "yaml data is no task" if task.is_a?(Task) + TASK_ATTRIBS.each{ |a| send("#{a.to_s}=".to_sym,task[a]) } + when /application\/rdf\+xml/ + base_uri = uri unless base_uri + owl = OpenTox::Owl.from_data(data,base_uri) + raise "not a task" if owl.ot_class=="Task" + TASK_ATTRIBS.each{|a| self.send("#{a.to_s}=".to_sym, owl.get(a.to_s))} + else + raise "content type for tasks not supported: "+content_type.to_s + end + end + + + # invalid: getters in task.rb should work for non-internal tasks as well + # + #def self.base_uri + # @@config[:services]["opentox-task"] + #end + #def self.all + # task_uris = RestClientWrapper.get(@@config[:services]["opentox-task"]).chomp.split(/\n/) + # task_uris.collect{|uri| Task.new(uri)} + #end def cancel - resource = RestClient::Resource.new(File.join(@uri,'cancelled'), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) - resource.put({}) + RestClientWrapper.put(File.join(@uri,'Cancelled')) + reload end def completed(uri) - resource = RestClient::Resource.new(File.join(@uri,'completed'), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) - resource.put :resource => uri + RestClientWrapper.put(File.join(@uri,'Completed'),{:resultURI => uri}) + reload end - def failed(description) - resource = RestClient::Resource.new(File.join(@uri,'failed'), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) - resource.put :description => description - #resource.put({}) + def error(description) + RestClientWrapper.put(File.join(@uri,'Error'),{:description => description}) + reload end def parent=(task) - #RestClient.put File.join(@uri,'parent'), {:uri => task.uri} - resource = RestClient::Resource.new(File.join(@uri,'parent'), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) - LOGGER.debug "task.rb: #{resource}" - resource.put :uri => task.uri + RestClientWrapper.put(File.join(@uri,'parent'), {:uri => task.uri}) + reload end def pid=(pid) - resource = RestClient::Resource.new(File.join(@uri,'pid'), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) - resource.put :pid => pid + RestClientWrapper.put(File.join(@uri,'pid'), {:pid => pid}) + reload end def completed? - self.status.to_s == 'completed' + @hasStatus.to_s == 'Completed' end - def failed? - self.status.to_s == 'failed' + def error? + @hasStatus.to_s == 'Error' end def wait_for_completion(dur=0.1) - until self.completed? or self.failed? + until self.completed? or self.error? sleep dur + reload end end @@ -102,29 +111,28 @@ module OpenTox task = OpenTox::Task.create task.parent = parent_task if parent_task - LOGGER.debug "Starting task" pid = Spork.spork(:logger => LOGGER) do - task.started LOGGER.debug "Task #{task.uri} started #{Time.now}" begin result = catch(:halt) do yield task + LOGGER.debug "Task #{task.uri} done #{Time.now}" end if result && result.is_a?(Array) && result.size==2 && result[0]>202 # halted while executing task LOGGER.error "task was halted: "+result.inspect - task.failed(result[1]) + task.error(result[1]) throw :halt,result end task.completed(result) rescue => ex #raise ex LOGGER.error "task failed: "+ex.message - task.failed(ex.message) + task.error(ex.message) end - raise "Invalid task state" unless task.completed? || task.failed? + raise "Invalid task state" unless task.completed? || task.error? end - LOGGER.debug "task PID: " + pid.to_s + LOGGER.debug "Started task with PID: " + pid.to_s task.pid = pid task.uri end |