summaryrefslogtreecommitdiff
path: root/lib/opentox.rb
blob: 2fbf9dc9e5ad68ce38686e94ed3cadd410876e0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#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"]

class String
  def underscore
    self.gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr("-", "_").
    downcase
  end
end

module URI

  def self.task? uri
    uri =~ /task/ and URI.valid? uri
  end
  
  def self.dataset? uri, subjectid=nil
    uri =~ /dataset/ and URI.accessible? uri, subjectid=nil
  end
 
  def self.model? uri, subjectid=nil
    uri =~ /model/ and URI.accessible? uri, subjectid=nil
  end

  def self.accessible? uri, subjectid=nil
    Net::HTTP.get_response(URI.parse(uri))
    true
  rescue
    false
  end

  def self.valid? uri
    u = URI::parse(uri)
    u.scheme!=nil and u.host!=nil
  rescue URI::InvalidURIError
    false
  end
end

# defaults to stderr, may be changed to file output
$logger = OTLogger.new(STDERR) # no rotation
$logger.level = Logger::DEBUG

module OpenTox

  attr_accessor :subjectid, :uri, :response
  attr_writer :metadata

  def initialize uri=nil, subjectid=nil
    @uri = uri.chomp
    @subjectid = subjectid
  end

  # Ruby interface


  # override to read all error codes
  def metadata reload=true
    if reload
      @metadata = {}
      # ignore error codes from Task services (may contain eg 500 which causes exceptions in RestClient and RDF::Reader
      RestClient.get(@uri) do |response, request, result, &block|
        $logger.warn "#{@uri} returned #{result}" unless response.code == 200 or response.code == 202 or URI.task? @uri
        RDF::Reader.for(:rdfxml).new(response) do |reader|
          reader.each_statement do |statement|
            @metadata[statement.predicate] = statement.object if statement.subject == @uri
          end
        end
      end
    end
    @metadata
  end

  def save
    rdf = RDF::Writer.for(:rdfxml).buffer do |writer|
      @metadata.each { |p,o| writer << RDF::Statement.new(RDF::URI.new(@uri), p, o) }
    end
    post rdf, { :content_type => 'application/rdf+xml'}
  end

  # REST API
  def get params={}
    params[:subjectid] ||= @subjectid
    params[:accept] ||= 'application/rdf+xml'
    @response = RestClient.get @uri, params
  end

  def post payload={}, params={}
    params[:subjectid] ||= @subjectid
    params[:accept] ||= 'application/rdf+xml'
    @response = RestClient.post(@uri.to_s, payload, params)
    begin
      @response.to_s.to_object
    rescue
      @response
    end
  end

  def put payload={}, params={} 
    params[:subjectid] ||= @subjectid
    params[:accept] ||= 'application/rdf+xml'
    @response = RestClient.put(@uri.to_s, payload, params)
  end

  def delete params={}
    params[:subjectid] ||= @subjectid
    params[:accept] ||= 'application/rdf+xml'
    @response = RestClient.delete(@uri.to_s,:subjectid => @subjectid)
  end

  # class methods
  module ClassMethods

    def create service_uri, subjectid=nil
      uri = RestClient.post(service_uri, {}, :subjectid => subjectid).chomp
      subjectid ? eval("#{self}.new(\"#{uri}\", #{subjectid})") : eval("#{self}.new(\"#{uri}\")")
    end

    def from_file service_uri, file, subjectid=nil
      RestClient.post(service_uri, :file => File.new(file), :subjectid => subjectid).chomp.to_object
    end

    def all service_uri, subjectid=nil
      uris = RestClient.get(service_uri, {:accept => 'text/uri-list'}).split("\n").compact
      uris.collect{|uri| subjectid ? eval("#{self}.new(\"#{uri}\", #{subjectid})") : eval("#{self}.new(\"#{uri}\")")}
    end

  end

  # create default classes
  SERVICES.each do |s|
    eval "class #{s}
      include OpenTox
      extend OpenTox::ClassMethods
    end"
  end

end