SysMO-DB/seek

View on GitHub
app/controllers/data_fuse_controller.rb

Summary

Maintainability
A
2 hrs
Test Coverage
require 'libxml'
require 'csv'
require 'simple-spreadsheet-extractor'
require 'open-uri'

class DataFuseController < ApplicationController
  include Seek::MimeTypes
  include Seek::Models::ModelExtraction
  include SysMODB::SpreadsheetExtractor
  include Seek::JWS::DataFuseMethods

  before_filter :login_required
  before_filter :is_user_admin_auth

  @@model_builder = Seek::JWS::Builder.new

  def data_file_csv

    element=params[:element]
    data_file=DataFile.find_by_id(params[:id])

    last_sheet = find_last_sheet_index(data_file)
    csv = spreadsheet_to_csv(open(data_file.content_blob.filepath),last_sheet,true)

    render :update do |page|
      if data_file.try :can_download?
        page.replace_html element, :partial=>"data_fuse/csv_view", :locals=>{:csv=>csv}
      else
        page.replace_html element, :text=>"#{t('data_file')} not found, or not authorized to examine"
      end
    end

  end

  def preview_model
    element=params[:element]
    model = Model.find_by_id(params[:id])
    render :update do |page|
      page.replace_html element, :partial=>"models/resource_list_item", :locals=>{:resource=>model}
    end
  end

  def preview_data_file
    element=params[:element]
    df = DataFile.find_by_id(params[:id])
    render :update do |page|
      page.replace_html element, :partial=>"data_files/resource_list_item", :locals=>{:resource=>df}
    end
  end



  def matching_data_files
    element=params[:element]
    model = Model.find_by_id(params[:id])

    @matching_data_files = model.matching_data_files(true)
    render :update do |page|
      page.replace_html element, :partial=>"matching_data_select"
    end
  end

  def show
    @models=Model.all.select{|m| m.can_download? && m.is_jws_supported?}
    respond_to do |format|
      format.html
    end
  end

  def assets_selected
    @data_file = DataFile.find(params[:data_file_id])
    @model=Model.find(params[:model_id])
    params[:parameter_keys] ||= {}

    #FIXME: temporary way of making sure it isn't exploited to get at data. Should never get here if used through the UI
    raise Exception.new("Unauthorized") unless @model.can_download? && @data_file.can_download?

    @parameter_keys = params[:parameter_keys].keys

    @matching_csv,@matching_keys = matching_csv(@data_file,@parameter_keys)

    respond_to do |format|
      format.html
    end
  end

  def matching_csv data_file,parameter_keys
    last_sheet_index = find_last_sheet_index(data_file)
    csv = spreadsheet_to_csv(open(data_file.content_blob.filepath),last_sheet_index,true)

    #FIXME: temporary way of making sure it isn't exploited to get at data. Should never get here if used through the UI
    raise Exception.new("Unauthorized") unless @model.can_download?

    resolve_model_parameter_keys parameter_keys,csv

  end

  def submit
    @model=Model.find(params[:model_id])
    parameter_csv=params[:parameter_csv]
    matching_keys=params[:matching_keys]

    @results = submit_parameter_values_to_jws_online @model,matching_keys,parameter_csv

    respond_to do |format|
      format.html
    end
  end



  def find_last_sheet_index data_file
    #FIXME: this currently uses the XML to find the number of sheets. The spreadsheet extractor will be updated to provide a summary including this
    #information in the future which will be more efficient

    xml = spreadsheet_to_xml(open(data_file.content_blob.filepath))

    parser = LibXML::XML::Parser.string(xml)
    doc = parser.parse
    doc.root.namespaces.default_prefix="ss"

    doc.find("//ss:workbook/ss:sheet").count

  end

  def parameter_keys

    element=params[:element]
    model=Model.find_by_id(params[:id])

    ps=model.parameters_and_values.keys

    render :update do |page|
      if model.try :can_download?

        page.replace_html element, :partial=>"data_fuse/parameter_keys", :locals=>{:keys=>ps}
      else
        page.replace_html element, :text=>"#{t('model')} not found, or not authorized to examine"
      end
    end
  end

  def view_result_csv
    url = params[:url]
    @csv=open(url).read
    respond_to do |format|
      format.html
    end
  end

  def resolve_model_parameter_keys parameter_keys, csv

    matching_columns = {}
    matched_keys = []
    matching_csv = []

    CSV.parse(csv).each do |row|
      matched_row = []
      row.each_with_index do |v, i|
        if matching_columns[i]
          matched_row << v
        end
        k = matching_key? parameter_keys, v
        if k
          matched_row << k
          matching_columns[i]=k
          matched_keys << k
        end
      end
      matching_csv << matched_row unless matched_row.empty?
    end

    result = CSV.generate do |out|
      matching_csv.each do |row|
        out << row
      end
    end

    return result, matched_keys

  end

  def matching_key? parameter_keys, v
    v if parameter_keys.include?(v)
  end

end