summaryrefslogtreecommitdiff
path: root/application.rb
blob: 079614eb1ffe3cdd46a9746983fb4d66824b6e31 (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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
require 'rubygems'
gem "opentox-ruby-api-wrapper", "= 1.6.6"
require 'opentox-ruby-api-wrapper'
require 'parser'

class Dataset

  include DataMapper::Resource
  property :id, Serial
  property :uri, String, :length => 255
  property :yaml, Text, :length => 2**32-1 
  property :created_at, DateTime

end

DataMapper.auto_upgrade!


## REST API

get '/?' do
  response['Content-Type'] = 'text/uri-list'
  Dataset.all(params).collect{|d| d.uri}.join("\n") + "\n"
end

get '/:id' do

  accept = request.env['HTTP_ACCEPT']
  accept = 'application/rdf+xml' if accept == '*/*' or accept == '' or accept.nil?

  begin
    dataset = OpenTox::Dataset.from_yaml(Dataset.get(params[:id]).yaml)
    halt 404, "Dataset #{params[:id]} not found." if dataset.nil? # not sure how an empty dataset can be returned, but if this happens stale processes keep runing at 100% cpu
  rescue => e
    LOGGER.error e.message
    LOGGER.info e.backtrace
    halt 404, "Dataset #{params[:id]} not found."
  end
  
  case accept

  when /rdf/ # redland sends text/rdf instead of application/rdf+xml
    file = "public/#{params[:id]}.rdfxml"
    if File.exists? file
      response['Content-Type'] = 'application/rdf+xml'
      #redirect url_for("/#{params[:id]}",:full)+ ".rdfxml" # confuses curl (needs -L flag)
      File.read(file)
    else
      task_uri = OpenTox::Task.as_task("Converting dataset to OWL-DL (RDF/XML)", url_for(params[:id],:full)) do 
        File.open(file,"w+") { |f| f.puts dataset.rdfxml }
        url_for("/#{params[:id]}",:full)+ ".rdfxml"
      end
      response['Content-Type'] = 'text/uri-list'
      halt 202,task_uri.to_s+"\n"
    end

  when /yaml/
    response['Content-Type'] = 'application/x-yaml'
    dataset.yaml
 
  when "text/csv"
    response['Content-Type'] = 'text/csv'
    dataset.csv

  when /ms-excel/
    file = "public/#{params[:id]}.xls"
    if File.exists? file
      response['Content-Type'] = 'application/ms-excel'
      File.read(file)
    else
      task_uri = OpenTox::Task.as_task("Converting dataset to Excel", url_for(params[:id],:full)) do 
        dataset.excel.write(file)
        url_for("/#{params[:id]}",:full)+ ".xls"
      end
      response['Content-Type'] = 'text/uri-list'
      halt 202,task_uri.to_s+"\n"
    end

  else
    halt 404, "Content-type #{accept} not supported."
  end
end

get '/:id/metadata/?' do

  metadata = YAML.load(Dataset.get(params[:id]).yaml).metadata
  accept = request.env['HTTP_ACCEPT']
  accept = 'application/rdf+xml' if accept == '*/*' or accept == '' or accept.nil?
  
  case accept
  when /rdf/ # redland sends text/rdf instead of application/rdf+xml
    response['Content-Type'] = 'application/rdf+xml'
    serializer = OpenTox::Serializer::Owl.new
    serializer.add_metadata url_for(params[:id],:full), "Dataset", metadata
    serializer.rdfxml
  when /yaml/
    response['Content-Type'] = 'application/x-yaml'
    metadata.to_yaml
  end

end

get %r{/(\d+)/feature/(.*)$} do |id,feature|

  feature_uri = url_for("/#{id}/feature/#{feature}",:full)
  dataset = OpenTox::Dataset.from_yaml(Dataset.get(id).yaml)
  metadata = dataset.features[feature_uri]

  accept = request.env['HTTP_ACCEPT']
  accept = 'application/rdf+xml' if accept == '*/*' or accept == '' or accept.nil?
  
  case accept
  when /rdf/ # redland sends text/rdf instead of application/rdf+xml
    response['Content-Type'] = 'application/rdf+xml'
    serializer = OpenTox::Serializer::Owl.new
    serializer.add_feature feature_uri, metadata
    serializer.rdfxml
  when /yaml/
    response['Content-Type'] = 'application/x-yaml'
    metadata.to_yaml
  end

end

get '/:id/features/?' do
  response['Content-Type'] = 'text/uri-list'
  YAML.load(Dataset.get(params[:id]).yaml).features.keys.join("\n") + "\n"
end

get '/:id/compounds/?' do
  response['Content-Type'] = 'text/uri-list'
  YAML.load(Dataset.get(params[:id]).yaml).compounds.join("\n") + "\n"
end

post '/?' do # create an empty dataset
  response['Content-Type'] = 'text/uri-list'
  dataset = Dataset.create
  dataset.update(:uri => url_for("/#{dataset.id}", :full))
  dataset.update(:yaml => OpenTox::Dataset.new(url_for("/#{dataset.id}", :full)).to_yaml)
  "#{dataset.uri}\n"
end

post '/:id/?' do # insert data into a dataset

  begin
    dataset = Dataset.get(params[:id])
    halt 404, "Dataset #{params[:id]} not found." unless dataset
    data = request.env["rack.input"].read

    content_type = request.content_type
    content_type = "application/rdf+xml" if content_type.nil?

    case content_type

    when /yaml/
      dataset.update(:yaml => data)

    when "application/rdf+xml"
      dataset.update(:yaml => OpenTox::Dataset.from_rdfxml(data).yaml)

    when /multipart\/form-data/ # for file uploads

      case params[:file][:type]

      when /yaml/
        dataset.update(:yaml => params[:file][:tempfile].read)

      when "application/rdf+xml"
        dataset.update(:yaml => OpenTox::Dataset.from_rdfxml(params[:file][:tempfile]).yaml)

      when "text/csv"
        metadata = {DC.title => File.basename(params[:file][:filename],".csv"), OT.hasSource => File.basename(params[:file][:filename])}
        d = OpenTox::Dataset.from_csv(File.open(params[:file][:tempfile]).read)
        d.add_metadata metadata
        dataset.update(:yaml => d.yaml, :uri => d.uri)

      when /ms-excel/
        extension =  File.extname(params[:file][:filename])
        metadata = {DC.title => File.basename(params[:file][:filename],extension), OT.hasSource => File.basename(params[:file][:filename])}
        case extension
        when ".xls"
          xls = params[:file][:tempfile].path + ".xls"
          File.rename params[:file][:tempfile].path, xls # roo needs these endings
          book = Excel.new xls
        when ".xlsx"
          xlsx = params[:file][:tempfile].path + ".xlsx"
          File.rename params[:file][:tempfile].path, xlsx # roo needs these endings
          book = Excel.new xlsx
        else
          halt 404, "#{params[:file][:filename]} is not a valid Excel input file."
        end
        d = OpenTox::Dataset.from_spreadsheet(book)
        d.add_metadata metadata
        dataset.update(:yaml => d.yaml, :uri => d.uri)

      else
        halt 404, "MIME type \"#{params[:file][:type]}\" not supported."
      end

    else
      halt 404, "MIME type \"#{content_type}\" not supported."
    end

    FileUtils.rm Dir["public/#{params[:id]}.*"] # delete all serialization files, will be recreated at next reques
    response['Content-Type'] = 'text/uri-list'
    "#{dataset.uri}\n"

  rescue => e
    LOGGER.error e.message
    LOGGER.info e.backtrace
    halt 500, "Could not save dataset #{dataset.uri}."
  end
end

delete '/:id/?' do
  begin
    dataset = Dataset.get(params[:id])
    FileUtils.rm Dir["public/#{params[:id]}.*"]
    dataset.destroy!
    response['Content-Type'] = 'text/plain'
    "Dataset #{params[:id]} deleted."
  rescue
    halt 404, "Dataset #{params[:id]} does not exist."
  end
end

delete '/?' do
  Dataset.all {|d| FileUtils.rm Dir["public/#{d.id}.*"] }
  Dataset.auto_migrate!
  response['Content-Type'] = 'text/plain'
  "All datasets deleted."
end