app/controllers/workflows_controller.rb
require 't2flow/model'
require 't2flow/parser'
require 't2flow/dot'
class WorkflowsController < ApplicationController
include IndexPager
include Seek::AssetsCommon
before_filter :workflows_enabled?
before_filter :find_and_filter_workflows, :only => [ :index ]
before_filter :find_and_authorize_requested_item, :except => [ :index, :new, :create, :preview ]
before_filter :find_display_asset, :only=>[:show, :download, :run]
before_filter :check_runs_before_destroy, :only => :destroy
include Seek::Publishing::PublishingCommon
include Seek::BreadCrumbs
def index
respond_to do |format|
format.html # index.html.erb
format.json # index.json.jbuilder
end
end
def show
end
def temp_link
workflow = Workflow.find(params[:id])
respond_to do |format|
format.html { render :partial => "sharing/temp_link", :locals => { :workflow => workflow } }
end
end
def run
end
def new
@workflow = Workflow.new(:category_id => params[:category_id])
#@data_file.parent_name = params[:parent_name]
#@data_file.is_with_sample= params[:is_with_sample]
@page_title = params[:page_title]
respond_to do |format|
if current_user.person.member?
format.html # new.html.erb
else
flash[:error] = "You are not authorized to upload new workflows. Only members of known projects, institutions or work groups are allowed to create new content."
format.html { redirect_to workflows_path }
end
end
end
def edit
end
def create
if handle_upload_data
@workflow = Workflow.new params[:workflow]
@workflow.policy.set_attributes_with_sharing params[:sharing], @workflow.projects
if @workflow.save
update_annotations @workflow
create_content_blobs
# Check if the uploaded file contains a Taverna workflow
if !taverna_workflow?(@workflow.content_blob.data_io_object)
@workflow.destroy
respond_to do |format|
flash[:error] = 'The uploaded file does not appear to be a Taverna workflow.'
format.html {redirect_to new_workflow_path}
end
return
end
# Pull title and from t2flow
extract_workflow_metadata
# update attributions
Relationship.create_or_update_attributions(@workflow, params[:attributions])
# update related publications
Relationship.create_or_update_attributions(@workflow, params[:related_publication_ids].collect { |i| ["Publication", i.split(",").first] }, Relationship::RELATED_TO_PUBLICATION) unless params[:related_publication_ids].nil?
#Add creators
AssetsCreator.add_or_update_creator_list(@workflow, params[:creators])
respond_to do |format|
flash[:notice] = "#{t('workflow')} was successfully uploaded and saved." if flash.now[:notice].nil?
format.html { redirect_to describe_ports_workflow_path(@workflow) }
end
else
respond_to do |format|
format.html {
render :action => "new"
}
end
end
else
handle_upload_data_failure
end
end
def update
if params[:workflow]
[:contributor_id, :contributor_type, :original_filename, :content_type, :content_blob_id, :created_at, :updated_at, :last_used_at].each do |column_name|
params[:workflow].delete(column_name)
end
params[:workflow][:last_used_at] = Time.now
end
publication_params = params[:related_publication_ids].nil?? [] : params[:related_publication_ids].collect { |i| ["Publication", i.split(",").first]}
@workflow.attributes = params[:workflow]
if params[:sharing]
@workflow.policy_or_default
@workflow.policy.set_attributes_with_sharing params[:sharing], @workflow.projects
end
if @workflow.save && !params[:sharing_form]
update_annotations @workflow
extract_workflow_metadata
# update attributions
Relationship.create_or_update_attributions(@workflow, params[:attributions])
# update related publications
Relationship.create_or_update_attributions(@workflow, publication_params, Relationship::RELATED_TO_PUBLICATION)
#Add creators
AssetsCreator.add_or_update_creator_list(@workflow, params[:creators])
respond_to do |format|
flash[:notice] = "#{t('workflow')} was successfully updated." if flash.now[:notice].nil?
format.html { redirect_to workflow_path(@workflow) }
end
else
if @workflow.save && params[:sharing_form]
flash[:notice] = "Sharing link has been #{!@workflow.special_auth_codes.empty? ? "enabled" : "disabled"}" if flash.now[:notice].nil?
end
respond_to do |format|
format.html {
render :action => "edit"
}
end
end
end
def destroy
if @workflow.runs.empty?
@workflow.destroy
respond_to do |format|
format.html { redirect_to(workflows_path) }
format.xml { head :ok }
end
else
flash[:error] = "This workflow has #{@workflow.runs.size} runs associated with it and so cannot be deleted. Please make it private instead."
respond_to do |format|
format.html { redirect_to(workflows_path) }
format.xml { head :forbidden }
end
end
end
def preview
element=params[:element]
workflow=Workflow.find_by_id(params[:id])
render :update do |page|
if workflow.try :can_view?
page.replace_html element,:partial=>"assets/resource_preview",:locals=>{:resource=>workflow}
else
page.replace_html element,:text=>"Nothing is selected to preview."
end
end
end
def new_version
if (handle_data nil)
comments=params[:revision_comment]
respond_to do |format|
if @workflow.save_as_new_version(comments)
create_content_blobs
extract_workflow_metadata
flash[:notice] = "New version uploaded - now on version #{@workflow.version}"
format.html { redirect_to describe_ports_workflow_path(@workflow) }
else
flash[:error] = "Unable to save new version"
format.html {redirect_to @workflow }
end
end
else
flash[:error]=flash.now[:error]
redirect_to @workflow
end
end
def describe_ports
end
def favourite
f = Favourite.new(:user => current_user, :resource => @workflow)
if Favourite.find_by_user_id_and_resource_type_and_resource_id(current_user,f.resource_type,f.resource_id).nil?
if f.save
flash[:notice] = "Added to favourites"
else
flash[:error] = "Couldn't add to favourites: #{f.errors.full_messages}"
end
else
flash[:error] = "This workflow is already in your favourites"
end
respond_to do |format|
format.html { redirect_to @workflow }
end
end
def favourite_delete
f = Favourite.find(:first, :conditions => {:user_id => current_user.id, :resource_type => 'Workflow', :resource_id => @workflow.id})
if f
if f.destroy
flash[:notice] = "Removed from favourites"
else
flash[:error] = "Couldn't remove from favourites: #{f.errors.full_messages}"
end
else
flash[:error] = "This workflow wasn't in your favourites"
end
respond_to do |format|
format.html { redirect_to @workflow }
end
end
private
# Checks if the uploaded file looks like a Taverna workflow
def taverna_workflow?(file)
first_couple_of_bytes = IO.read(file, 512) # returns string
if first_couple_of_bytes.include?('xmlns="http://taverna.sf.net/2008/xml/t2flow"') # This looks like a Taverna workflow
return true
else
return false
end
end
def extract_workflow_metadata
@t2flow = T2Flow::Parser.new.parse(@workflow.content_blob.data_io_object.read)
@workflow.title = @t2flow.annotations.titles.last unless @t2flow.annotations.titles.last.blank?
@workflow.description = @t2flow.annotations.descriptions.last
@t2flow.sources.each do |source|
unless @workflow.input_ports.detect { |i| i.name == source.name && i.workflow_version == @workflow.version }
@workflow.input_ports.build(:name => source.name,
:description => (source.descriptions || []).last,
:example_value => (source.example_values || []).last,
:port_type_id => WorkflowInputPortType.first.id)
end
end
@t2flow.sinks.each do |sink|
unless @workflow.output_ports.detect { |o| o.name == sink.name && o.workflow_version == @workflow.version }
@workflow.output_ports.build(:name => sink.name,
:description => (sink.descriptions || []).last,
:example_value => (sink.example_values || []).last,
:port_type_id => WorkflowOutputPortType.first.id)
end
end
@workflow.save
# Manually set workflow content type
@workflow.content_blob.content_type = 'application/vnd.taverna.t2flow+xml'
@workflow.content_blob.save
end
def find_and_filter_workflows
find_assets
# Has the user cleared the search box? - return all items.
uploader = params[:uploader_id]
category = params[:category_id]
params.delete(:visibility) unless logged_in?
visibility = params[:visibility]
search_query = params[:query] || []
search_included = (params[:commit] == 'Clear') ? false : true
# Filter by uploader and category
filter_results = Workflow.where(true)
filter_results = filter_results.by_category(category.to_i) unless category.blank?
filter_results = filter_results.by_visibility(visibility) unless visibility.blank?
filter_results = filter_results.by_uploader(uploader.to_i) unless uploader.blank?
@workflows = @workflows & filter_results
# Filter by search results
unless params[:query].blank? || search_included == false
search_results = Workflow.search do |query|
query.keywords(search_query.downcase)
end.results
@workflows = @workflows & search_results
end
@workflows
end
def check_runs_before_destroy
unless @workflow.runs.empty?
flash[:error] = "There are #{@workflow.runs.count} runs associated with this workflow and so it may not be deleted."
redirect_to @workflow
end
end
end