From 63fcd8f8feed58af4b1e1ff0e5fdaa09791c9596 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 8 Mar 2012 15:23:43 +0000 Subject: improved integration of error reports, call stack added as errorDetails --- lib/opentox.rb | 118 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 40 deletions(-) (limited to 'lib/opentox.rb') diff --git a/lib/opentox.rb b/lib/opentox.rb index 9ba64bd..342b04e 100644 --- a/lib/opentox.rb +++ b/lib/opentox.rb @@ -1,52 +1,73 @@ -#TODO: switch services to 1.2 -RDF::OT = RDF::Vocabulary.new 'http://www.opentox.org/api/1.2#' -RDF::OT1 = RDF::Vocabulary.new 'http://www.opentox.org/api/1.1#' -RDF::OTA = RDF::Vocabulary.new 'http://www.opentox.org/algorithmTypes.owl#' - -SERVICES = ["Compound", "Feature", "Dataset", "Algorithm", "Model", "Validation", "Task", "Investigation"] - -# Regular expressions for parsing classification data -TRUE_REGEXP = /^(true|active|1|1.0|tox|activating|carcinogen|mutagenic)$/i -FALSE_REGEXP = /^(false|inactive|0|0.0|low tox|deactivating|non-carcinogen|non-mutagenic)$/i - # defaults to stderr, may be changed to file output (e.g in opentox-service) $logger = OTLogger.new(STDERR) $logger.level = Logger::DEBUG module OpenTox - attr_accessor :subjectid, :uri, :response - attr_writer :metadata + attr_accessor :uri, :subjectid, :rdf, :response + # Ruby interface + + # Create a new OpenTox object (does not load data from service) + # @param [optional,String] URI + # @param [optional,String] subjectid + # @return [OpenTox] OpenTox object def initialize uri=nil, subjectid=nil - @uri = uri.chomp + @uri = uri.to_s.chomp @subjectid = subjectid + @rdf = RDF::Graph.new end - # Ruby interface + # Load metadata from service + def pull + kind_of?(OpenTox::Dataset) ? uri = File.join(@uri,"metadata") : uri = @uri + # TODO generic method for all formats + parse_rdfxml RestClientWrapper.get(uri,{},{:accept => $default_rdf, :subjectid => @subjectid}) + end - def metadata reload=true - if reload or @metadata.empty? - @metadata = {} - kind_of?(OpenTox::Dataset) ? uri = File.join(@uri,"metadata") : uri = @uri - RDF::Reader.for(:rdfxml).new( RestClientWrapper.get(uri) ) do |reader| - reader.each_statement do |statement| - @metadata[statement.predicate] = statement.object if statement.subject == @uri - end - end + # Get object metadata + # @return [Hash] Metadata + def metadata + pull if @rdf.empty? + metadata = {} + @rdf.query([RDF::URI.new(@uri),nil,nil]).collect do |statement| + metadata[statement.predicate] ||= [] + metadata[statement.predicate] << statement.object end - @metadata + metadata + end + + # Get metadata values + # @param [RDF] Key from RDF Vocabularies + # @return [Array] Values for supplied key + def [](key) + pull if @rdf.empty? + @rdf.query([RDF::URI.new(@uri),key,nil]).collect{|statement| statement.object} end + # Save object at service def save - post self.to_rdfxml, { :content_type => 'application/rdf+xml'} + #TODO: dynamic assignment + post self.to_rdfxml, { :content_type => $default_rdf} end - def to_rdfxml - rdf = RDF::Writer.for(:rdfxml).buffer do |writer| - @metadata.each { |p,o| writer << RDF::Statement.new(RDF::URI.new(@uri), p, o) } + RDF_FORMATS.each do |format| + + # rdf parse methods for all formats e.g. parse_rdfxml + send :define_method, "parse_#{format}".to_sym do |rdf| + @rdf = RDF::Graph.new + RDF::Reader.for(format).new(rdf) do |reader| + reader.each_statement{ |statement| @rdf << statement } + end + end + + # rdf serialization methods for all formats e.g. to_rdfxml + send :define_method, "to_#{format}".to_sym do + rdf = RDF::Writer.for(format).buffer do |writer| + @rdf.each{|statement| writer << statement} + end + rdf end - rdf end # REST API @@ -70,32 +91,49 @@ module OpenTox def delete headers={} headers[:subjectid] ||= @subjectid - @response = RestClientWrapper.delete(@uri.to_s,nil,nil,headers) + @response = RestClientWrapper.delete(@uri.to_s,nil,headers) end # class methods module ClassMethods + def all service_uri, subjectid=nil + uris = RestClientWrapper.get(service_uri, {}, :accept => 'text/uri-list').split("\n").compact + uris.collect{|uri| URI.task?(service_uri) ? from_uri(uri, subjectid, false) : from_uri(uri, subjectid)} + end + def create service_uri, subjectid=nil - uri = RestClientWrapper.post(service_uri, {}, :subjectid => subjectid).chomp - subjectid ? eval("#{self}.new(\"#{uri}\", #{subjectid})") : eval("#{self}.new(\"#{uri}\")") + uri = RestClientWrapper.post(service_uri, {}, {:accept => 'text/uri-list', :subjectid => subjectid}) + URI.task?(service_uri) ? from_uri(uri, subjectid, false) : from_uri(uri, subjectid) end def from_file service_uri, filename, subjectid=nil file = File.new filename - uri = RestClientWrapper.post(service_uri, {:file => file}, {:subjectid => subjectid, :content_type => file.mime_type, :accept => "text/uri-list"}) - puts uri + from_uri RestClientWrapper.post(service_uri, {:file => file}, {:subjectid => subjectid, :content_type => file.mime_type, :accept => "text/uri-list"}), subjectid end - def all service_uri, subjectid=nil - uris = RestClientWrapper.get(service_uri, {}, :accept => 'text/uri-list').split("\n").compact - uris.collect{|uri| subjectid ? eval("#{self}.new(\"#{uri}\", #{subjectid})") : eval("#{self}.new(\"#{uri}\")")} - end + private + def from_uri uri, subjectid=nil, wait=true + + uri.chomp! + # TODO add waiting task + if URI.task? uri and wait + t = OpenTox::Task.new(uri) + t.wait + uri = t.resultURI + end + # 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) + result = CLASSES.collect{|s| s if uri =~ /#{s.downcase}/}.compact + internal_server_error "Cannot determine class from URI: '#{uri}.\nCandidate classes are #{result.inspect}" unless result.size == 1 + klass = result.first + # initialize with/without subjectid + subjectid ? eval("#{self}.new(\"#{uri}\", #{subjectid})") : eval("#{self}.new(\"#{uri}\")") + end end # create default OpenTox classes - SERVICES.each do |klass| + CLASSES.each do |klass| c = Class.new do include OpenTox extend OpenTox::ClassMethods -- cgit v1.2.3