summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Helma <helma@in-silico.ch>2011-02-23 18:06:14 +0100
committerChristoph Helma <helma@in-silico.ch>2011-02-23 18:06:14 +0100
commit6e1a5e9b634ec6d1b947c27212cf434a412a589e (patch)
tree9e65de4ed6317b5e6b8d21e323f16def692a9dca
parentcaf06dfa4f49f35a1bef8e703a0658f040f11540 (diff)
application.rb and .gitignore fixed
-rw-r--r--.gitignore5
-rw-r--r--application.rb337
2 files changed, 324 insertions, 18 deletions
diff --git a/.gitignore b/.gitignore
index e3debba..f52f036 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
+api_key.rb
+*.sqlite3
tmp/*
log/*
-public/*.owl
-*.*~
+public/*
diff --git a/application.rb b/application.rb
index 15088d5..de11313 100644
--- a/application.rb
+++ b/application.rb
@@ -1,27 +1,332 @@
require 'rubygems'
-# AM LAST: can include both libs, no problems
-require File.join(File.expand_path(File.dirname(__FILE__)), 'libfminer/libbbrc/bbrc') # has to be included before openbabel, otherwise we have strange SWIG overloading problems
-require File.join(File.expand_path(File.dirname(__FILE__)), 'libfminer/liblast/last') # has to be included before openbabel, otherwise we have strange SWIG overloading problems
-require File.join(File.expand_path(File.dirname(__FILE__)), 'last-utils/lu.rb') # AM LAST
gem "opentox-ruby", "~> 0"
require 'opentox-ruby'
-#require 'smarts.rb'
-#require 'similarity.rb'
-require 'openbabel.rb'
-require 'fminer.rb'
-require 'lazar.rb'
-
set :lock, true
+helpers do
+ def next_id
+ id = Dir["./public/*yaml"].collect{|f| File.basename(f.sub(/.yaml/,'')).to_i}.sort.last
+ id = 0 if id.nil?
+ id + 1
+ end
+
+ def uri(id)
+ url_for "/#{id}", :full
+ end
+
+ # subjectid ist stored as memeber variable, not in params
+ def load_dataset(id, params,content_type,input_data)
+
+ @uri = uri id
+ raise "store subject-id in dataset-object, not in params" if params.has_key?(:subjectid) and @subjectid==nil
+
+ content_type = "application/rdf+xml" if content_type.nil?
+ dataset = OpenTox::Dataset.new(nil, @subjectid)
+
+ case content_type
+
+ when /yaml/
+ dataset.load_yaml(input_data)
+
+ when /application\/rdf\+xml/
+ dataset.load_rdfxml(input_data)
+
+ when /multipart\/form-data/ , "application/x-www-form-urlencoded" # file uploads
+
+ case params[:file][:type]
+
+ when /yaml/
+ dataset.load_yaml(params[:file][:tempfile].read)
+
+ when "application/rdf+xml"
+ dataset.load_rdfxml_file(params[:file][:tempfile])
+
+ when "text/csv"
+ dataset = OpenTox::Dataset.new @uri
+ dataset.load_csv(params[:file][:tempfile].read)
+ dataset.add_metadata({
+ DC.title => File.basename(params[:file][:filename],".csv"),
+ OT.hasSource => File.basename(params[:file][:filename])
+ })
+
+ when /ms-excel/
+ extension = File.extname(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
+ raise "#{params[:file][:filename]} is not a valid Excel input file."
+ end
+ dataset.load_spreadsheet(book)
+ dataset.add_metadata({
+ DC.title => File.basename(params[:file][:filename],extension),
+ OT.hasSource => File.basename(params[:file][:filename])
+ })
+
+ else
+ raise "MIME type \"#{params[:file][:type]}\" not supported."
+ end
+
+ else
+ raise "MIME type \"#{content_type}\" not supported."
+ end
+
+ dataset.uri = @uri # update uri (also in metdata)
+ dataset.features.keys.each { |f| dataset.features[f][OT.hasSource] = dataset.metadata[OT.hasSource] unless dataset.features[f][OT.hasSource]}
+ File.open("public/#{@id}.yaml","w+"){|f| f.puts dataset.to_yaml}
+ end
+end
+
before do
- LOGGER.debug "Request: " + request.path
+ @accept = request.env['HTTP_ACCEPT']
+ @accept = 'application/rdf+xml' if @accept == '*/*' or @accept == '' or @accept.nil?
+ @id = request.path_info.match(/^\/\d+/)
+ unless @id.nil?
+ @id = @id.to_s.sub(/\//,'').to_i
+
+ @uri = uri @id
+ @yaml_file = "public/#{@id}.yaml"
+ halt 404, "Dataset #{@id} not found." unless File.exists? @yaml_file
+
+ extension = File.extname(request.path_info)
+ #extension = File.extname(params[:id]).sub(/\./,'')
+ unless extension.empty?
+ #request.path_info.sub!(/\.#{extension}$/,'')
+ case extension
+ when "html"
+ @accept = 'text/html'
+ when "yaml"
+ @accept = 'application/x-yaml'
+ when "csv"
+ @accept = 'text/csv'
+ when "rdfxml"
+ @accept = 'application/rdf+xml'
+ when "xls"
+ @accept = 'application/ms-excel'
+ else
+ halt 404, "File format #{extension} not supported."
+ end
+ end
+ end
+
+ # make sure subjectid is not included in params, subjectid is set as member variable
+ params.delete(:subjectid)
end
-# Get a list of available algorithms
-#
-# @return [text/uri-list] algorithm URIs
+## REST API
+
+# Get a list of available datasets
+# @return [text/uri-list] List of available datasets
get '/?' do
- response['Content-Type'] = 'text/uri-list'
- [ url_for('/lazar', :full), url_for('/fminer/bbrc', :full), url_for('/fminer/last', :full) ].join("\n") + "\n"
+ response['Content-Type'] = 'text/uri-list'
+ Dir["./public/*yaml"].collect{|f| File.basename(f.sub(/.yaml/,'')).to_i}.sort.collect{|n| uri n}.join("\n") + "\n"
+end
+
+# Get a dataset representation
+# @param [Header] Accept one of `application/rdf+xml, application-x-yaml, text/csv, application/ms-excel` (default application/rdf+xml)
+# @return [application/rdf+xml, application-x-yaml, text/csv, application/ms-excel] Dataset representation
+get '/:id' do
+
+ case @accept
+
+ when /rdf/ # redland sends text/rdf instead of application/rdf+xml
+ file = "public/#{params[:id]}.rdfxml"
+ unless File.exists? file # lazy rdfxml generation
+ dataset = YAML.load_file(@yaml_file)
+ File.open(file,"w+") { |f| f.puts dataset.to_rdfxml }
+ end
+ response['Content-Type'] = 'application/rdf+xml'
+ File.read(file)
+
+ when /yaml/
+ response['Content-Type'] = 'application/x-yaml'
+ File.read(@yaml_file)
+
+ when /html/
+ response['Content-Type'] = 'text/html'
+ OpenTox.text_to_html File.read(@yaml_file)
+
+ when "text/csv"
+ response['Content-Type'] = 'text/csv'
+ YAML.load_file(@yaml_file).to_csv
+
+ when /ms-excel/
+ file = "public/#{params[:id]}.xls"
+ YAML.load_file(@yaml_file).to_xls.write(file) unless File.exists? file # lazy xls generation
+ response['Content-Type'] = 'application/ms-excel'
+ File.open(file).read
+
+ else
+ halt 404, "Content-type #{@accept} not supported."
+ end
+end
+
+# Get metadata of the dataset
+# @return [application/rdf+xml] Metadata OWL-DL
+get '/:id/metadata' do
+
+ metadata = YAML.load_file(@yaml_file).metadata
+
+ 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), metadata
+ serializer.to_rdfxml
+ when /yaml/
+ response['Content-Type'] = 'application/x-yaml'
+ metadata.to_yaml
+ end
+
+end
+
+# Get a dataset feature
+# @param [Header] Accept one of `application/rdf+xml or application-x-yaml` (default application/rdf+xml)
+# @return [application/rdf+xml,application/x-yaml] Feature metadata
+get %r{/(\d+)/feature/(.*)$} do |id,feature|
+
+ @id = id
+ @uri = uri @id
+ @yaml_file = "public/#{@id}.yaml"
+ feature_uri = url_for("/#{@id}/feature/#{URI.encode(feature)}",:full) # work around racks internal uri decoding
+ metadata = YAML.load_file(@yaml_file).features[feature_uri]
+
+ 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.to_rdfxml
+ when /yaml/
+ response['Content-Type'] = 'application/x-yaml'
+ metadata.to_yaml
+ end
+
+end
+
+# Get a list of all features
+# @param [Header] Accept one of `application/rdf+xml, application-x-yaml, text/uri-list` (default application/rdf+xml)
+# @return [application/rdf+xml, application-x-yaml, text/uri-list] Feature list
+get '/:id/features' do
+
+ features = YAML.load_file(@yaml_file).features
+
+ case @accept
+ when /rdf/ # redland sends text/rdf instead of application/rdf+xml
+ response['Content-Type'] = 'application/rdf+xml'
+ serializer = OpenTox::Serializer::Owl.new
+ features.each { |feature,metadata| serializer.add_feature feature, metadata }
+ serializer.to_rdfxml
+ when /yaml/
+ response['Content-Type'] = 'application/x-yaml'
+ features.to_yaml
+ when "text/uri-list"
+ response['Content-Type'] = 'text/uri-list'
+ features.keys.join("\n") + "\n"
+ end
+end
+
+# Get a list of all compounds
+# @return [text/uri-list] Feature list
+get '/:id/compounds' do
+ response['Content-Type'] = 'text/uri-list'
+ YAML.load_file(@yaml_file).compounds.join("\n") + "\n"
+end
+
+# Create a new dataset.
+#
+# Posting without parameters creates and saves an empty dataset (with assigned URI).
+# Posting with parameters creates and saves a new dataset.
+# Data can be submitted either
+# - in the message body with the appropriate Content-type header or
+# - as file uploads with Content-type:multipart/form-data and a specified file type
+# @example
+# curl -X POST -F "file=@training.csv;type=text/csv" http://webservices.in-silico.ch/dataset
+# @param [Header] Content-type one of `application/x-yaml, application/rdf+xml, multipart/form-data/`
+# @param [BODY] - string with data in selected Content-type
+# @param [optional] file, for file uploads, Content-type should be multipart/form-data, please specify the file type `application/rdf+xml, application-x-yaml, text/csv, application/ms-excel`
+# @return [text/uri-list] Task URI or Dataset URI (empty datasets)
+post '/?' do
+
+ response['Content-Type'] = 'text/uri-list'
+
+ # it could be that the read function works only once!, store in varible
+ input_data = request.env["rack.input"].read
+ @id = next_id
+ @uri = uri @id
+ @yaml_file = "public/#{@id}.yaml"
+ if params.size == 0 and input_data.size==0
+ File.open(@yaml_file,"w+"){|f| f.puts OpenTox::Dataset.new(@uri).to_yaml}
+ OpenTox::Authorization.check_policy(@uri, @subjectid) if File.exists? @yaml_file
+ @uri
+ else
+ task = OpenTox::Task.create("Converting and saving dataset ", @uri) do
+ load_dataset @id, params, request.content_type, input_data
+ OpenTox::Authorization.check_policy(@uri, @subjectid) if File.exists? @yaml_file
+ @uri
+ end
+ halt 503,task.uri+"\n" if task.status == "Cancelled"
+ halt 202,task.uri+"\n"
+ end
+end
+
+# Save a dataset, will overwrite all existing data
+#
+# Data can be submitted either
+# - in the message body with the appropriate Content-type header or
+# - as file uploads with Content-type:multipart/form-data and a specified file type
+# @example
+# curl -X POST -F "file=@training.csv;type=text/csv" http://webservices.in-silico.ch/dataset/1
+# @param [Header] Content-type one of `application/x-yaml, application/rdf+xml, multipart/form-data/`
+# @param [BODY] - string with data in selected Content-type
+# @param [optional] file, for file uploads, Content-type should be multipart/form-data, please specify the file type `application/rdf+xml, application-x-yaml, text/csv, application/ms-excel`
+# @return [text/uri-list] Task ID
+post '/:id' do
+ LOGGER.debug @uri
+ response['Content-Type'] = 'text/uri-list'
+ task = OpenTox::Task.create("Converting and saving dataset ", @uri) do
+ FileUtils.rm Dir["public/#{@id}.*"]
+ load_dataset @id, params, request.content_type, request.env["rack.input"].read
+ @uri
+ end
+ halt 503,task.uri+"\n" if task.status == "Cancelled"
+ halt 202,task.uri.to_s+"\n"
+end
+
+# Delete a dataset
+# @return [text/plain] Status message
+delete '/:id' do
+ LOGGER.debug "deleting dataset with id "+@id.to_s
+ begin
+ FileUtils.rm Dir["public/#{@id}.*"]
+ if @subjectid and !File.exists? @yaml_file and @uri
+ begin
+ res = OpenTox::Authorization.delete_policies_from_uri(@uri, @subjectid)
+ LOGGER.debug "Policy deleted for Dataset URI: #{@uri} with result: #{res}"
+ rescue
+ LOGGER.warn "Policy delete error for Dataset URI: #{@uri}"
+ end
+ end
+ response['Content-Type'] = 'text/plain'
+ "Dataset #{@id} deleted."
+ rescue
+ halt 404, "Dataset #{@id} does not exist."
+ end
+end
+
+# Delete all datasets
+# @return [text/plain] Status message
+delete '/?' do
+ FileUtils.rm Dir["public/*.rdfxml"]
+ FileUtils.rm Dir["public/*.xls"]
+ FileUtils.rm Dir["public/*.yaml"]
+ response['Content-Type'] = 'text/plain'
+ "All datasets deleted."
end