Changeset 157

Show
Ignore:
Timestamp:
28-09-11 12:51:50 (3 years ago)
Author:
kostas.karasavvas@…
Message:

Removed an external dependency (input_type). Cleaned namespace and improved file structure.

Location:
myexperiment-rest/trunk
Files:
4 added
6 modified
1 copied

Legend:

Unmodified
Added
Removed
  • myexperiment-rest/trunk/bin/get_workflow_data.rb

    r151 r157  
    77 
    88my_exp_workflow = ARGV[0] || "http://www.myexperiment.org/workflows/74/download/bioaid_proteindiscovery_221429.xml?version=3" 
    9 wkf = Workflows.new.read(my_exp_workflow) 
     9wkf = Workflow.from_uri(my_exp_workflow) 
    1010 
    1111 
    12  
    13 puts wkf.input_type 
     12# general 
    1413puts wkf.xml_uri 
    1514puts wkf.title 
    1615puts wkf.description 
     16puts wkf.uploader_uri 
    1717puts "--------------------------" 
    1818 
     19# inputs 
    1920wkf.inputs.each do |i| 
    2021  puts i.name 
     
    2829end 
    2930 
    30 puts wkf.user.name 
    31 puts wkf.user.description 
    32 puts wkf.user.email 
    33 puts wkf.user.avatar 
    34 puts wkf.user.website 
    35 puts wkf.user.created_at 
     31# outputs 
     32wkf.outputs.each do |i| 
     33  puts i.name 
     34  i.descriptions.each do |d| 
     35    puts d 
     36  end 
     37  i.examples.each do |e| 
     38    puts e 
     39  end 
     40  puts "--------------------------" 
     41end 
    3642 
     43 
     44user = User.from_uri(wkf.uploader_uri) 
     45puts user.id 
     46puts user.created_at 
     47puts user.name 
     48puts user.description 
     49puts user.email 
     50puts user.avatar_uri 
     51puts user.city 
     52puts user.country 
     53puts user.website 
     54 
  • myexperiment-rest/trunk/CHANGES

    r151 r157  
    11= Changes log for the MyExperiment via REST Gem 
     2 
     3== Version 0.3.0 
     4* Added User class to acquire myExperiment's user resource 
     5* Added a constants.rb file 
     6* XML parsing of sub-objects is done on the specific elements now and not from the main doc 
     7* REST call is outside the XML parsing objects 
     8* Renamed populate_workflow with parse 
     9* Added from_uri and other from_ methods to retrieve data 
     10* Renamed TavernaWorkflow to MyExperimentWorkflow 
     11* Added MyExperimentUser class 
     12* Removed input_type -- it was unrelated to the library! 
     13 
    214 
    315== Version 0.2.8 
    416* Added user information for workflow 
     17 
    518 
    619== Version 0.2.7 
  • myexperiment-rest/trunk/lib/myexperiment-rest.rb

    r139 r157  
    1 require 'myexperiment-rest/myexperiment_rest.rb' 
     1require 'rubygems' 
     2require 'rest_client' 
     3 
     4require 'myexperiment-rest/constants' 
     5require 'myexperiment-rest/workflow' 
     6require 'myexperiment-rest/user' 
     7 
    28 
    39module MyExperimentREST 
    410 
     11   
     12  # Get information from myExperiment using the REST API. Resources supported currently 
     13  # are +WORKFLOW_URL+"+ and +USER_URL+. 
     14  def self.get_myexperiment_data(resource_url, params) 
     15    case resource_url 
     16 
     17    when Urls::WORKFLOW_URL 
     18      begin 
     19        # Get workflow resource information -- if version is empty it returns the current version 
     20        response = RestClient.get("#{Urls::MYEXPERIMENT_URL}/#{Urls::WORKFLOW_URL}", 
     21                                         {:params => {'id' => "#{params[:id]}", 
     22                                                      'version' => "#{params[:version]}", 
     23                                                      'elements' => 'title,description,content-uri,components,uploader'} } ) 
     24        response 
     25      rescue Exception => e 
     26        raise "REST call to acquire workflow resource failed!\n" + e 
     27      end 
     28 
     29    when Urls::USER_URL 
     30      begin 
     31        # Get user resource information 
     32        response = RestClient.get("#{Urls::MYEXPERIMENT_URL}/#{Urls::USER_URL}", 
     33                                         {:params => {'id' => "#{params[:id]}" } } ) 
     34        response 
     35      rescue Exception => e 
     36        raise "REST call to acquire user resource failed!\n" + e 
     37      end 
     38 
     39    else 
     40      raise "This is not a supported resource type!\n" 
     41    end 
     42 
     43  end 
     44 
     45 
    546end 
  • myexperiment-rest/trunk/lib/myexperiment-rest/workflow.rb

    r151 r157  
    1 require 'rubygems' 
    2 require 'rest_client' 
    3 require 'open-uri' 
    41require 'libxml' 
    52 
     
    74 
    85  # 
    9   # Connects to myExperiment REST API and creates a _TavernaWorkflow_ object. 
     6  # Connects to myExperiment REST API and creates a _MyExperimentWorkflow_ object. 
    107  # 
    11   class Workflows 
    12     include LibXML 
     8  class Workflow 
    139 
    14     attr_reader(:uri) 
    15  
    16     #def initialize 
    17     #end 
    18  
    19     # Requires the URI of the workflow in the repository as a String. 
    20     def read(uri) 
     10    # Returns a _MyExperimentWorkflow_ object given a URI of the workflow in the repository as a String. 
     11    def self.from_uri(uri) 
    2112 
    2213      workflow_id = '' 
    2314      workflow_version = '' 
    2415 
    25       # Get workflow id 
    26       uri_id = uri.match(/workflows\/(\d+)/) 
     16      # Get workflow id - will match both workflow/74 and workflows.xml?id=74 
     17      uri_id = uri.match(/workflow.*[\/?](id=)?(\d+)/) 
    2718      if uri_id != nil 
    28         workflow_id = uri_id[1] 
     19        workflow_id = uri_id[2] 
    2920      else 
    3021        raise "Could not match workflow id." 
     
    3728      end 
    3829 
    39       # Get workflow resource information -- if version is empty it returns the current version 
    40       response = RestClient.get('http://www.myexperiment.org/workflow.xml', {:params => {'id' => "#{workflow_id}",  
    41                                                                                          'version' => "#{workflow_version}", 
    42                                                                                          'elements' => 'title,description,content-uri,components,uploader'} } ) 
    43  
    44       populate_workflow(response) 
     30      # Get workflow resource information  
     31      xml = MyExperimentREST.get_myexperiment_data(Urls::WORKFLOW_URL, :id => workflow_id, :version => workflow_version) 
     32       
     33      MyExperimentWorkflow.parse(xml) 
    4534    end 
    4635 
    4736 
    48     private 
     37    # Returns a _MyExperimentWorkflow_ object given a myExperiment id and version for that workflow. 
     38    def self.from_id_and_version(id, version='') 
    4939 
    50     # Acquire data from XML response and instantiate a _Taverna_Workflow_ object 
    51     #-- 
    52     # TODO: refactor so that each (logical) workflow element is an object with 
    53     # its own read from_xml method... 
    54     def populate_workflow(response) 
    55       doc = XML::Document.string(response) 
    56       wkf_xml_uri = doc.find_first("/workflow/content-uri").content 
    57       wkf_title = doc.find_first("/workflow/title").content 
    58       wkf_descr = doc.find_first("/workflow/description").content 
    59       wkf_inputs = get_IOData(doc, "source") 
    60       wkf_outputs = get_IOData(doc, "sink") 
    61       wkf_user = get_user(doc.find_first("/workflow/uploader").attributes['uri']) 
     40      # Get workflow resource information 
     41      xml = MyExperimentREST.get_myexperiment_data(Urls::WORKFLOW_URL, :id => id, :version => version) 
    6242 
    63       TavernaWorkflow.new(TavernaWorkflow::MY_EXPERIMENT, wkf_xml_uri, wkf_title, wkf_descr, wkf_inputs, wkf_outputs, wkf_user) 
    64  
     43      MyExperimentWorkflow.parse(xml) 
    6544    end 
    6645 
    6746 
    68     # 
    69     # Populate _TavernaIOData_ objects for specified type: value +source+'+ is for inputs 
    70     # and +sink+ for outputs 
    71     # 
    72     def get_IOData(doc, type) 
    73       io_data = [] 
    74  
    75       # Get all sources or sinks and create appropriate objects 
    76       doc.find("//workflow/components/dataflows/dataflow[@role='top']/#{type}s/#{type}").each do |node| 
    77         name = '' 
    78         descriptions = [] 
    79         examples = [] 
    80  
    81         node.each_element do |n| 
    82           if n.name.eql? "name" 
    83             name = n.children[0].to_s 
    84           elsif n.name.eql? "descriptions" 
    85             n.each_element do |d| 
    86               descriptions << d.children[0].to_s 
    87             end if n.children? 
    88           elsif n.name.eql? "examples" 
    89             n.each_element do |e| 
    90               examples << e.children[0].to_s 
    91             end if n.children? 
    92           end 
    93         end 
    94  
    95         io_data << TavernaIOData.new(name, descriptions, examples) 
    96       end 
    97  
    98       io_data 
    99     end 
    100  
    101  
    102     # 
    103     # Populate _TavernaUser_ object for specified user resource 
    104     # 
    105     def get_user(user_uri) 
    106       doc = XML::Document.file(user_uri) 
    107       user = TavernaUser.new(doc.find_first("/user/name").content, 
    108                              doc.find_first("/user/description").content, 
    109                              doc.find_first("/user/email").content, 
    110                              doc.find_first("/user/avatar").attributes['uri'], 
    111                              doc.find_first("/user/website").content, 
    112                              doc.find_first("/user/created-at").content) 
    113       user 
    114     end 
    115  
    116  
    117  
    118   end 
     47  end  # class Workflow 
    11948 
    12049 
    12150 
    12251  # 
    123   # Contains all available information about a workflow: _input_type_, _xml_uri_, 
    124   # _title_, _description_,_inputs_, _outputs_ and _user_. The _xml_uri_ specifies 
    125   # the XML description on myExperiment and not the XML of the workflow itself. 
    126   # _input_type_ specifies the kind of input. Currently, either "myexperiment" 
    127   # (myExperiment's xml uri) or "t2flow" (filename) 
     52  # Contains all available information about a workflow: _xml_uri_, 
     53  # _title_, _description_,_inputs_, _outputs_ and _uploader_uri_. The _xml_uri_ 
     54  # specifies the XML description on myExperiment and not the XML of the workflow 
     55  # itself. 
    12856  # 
    129   class TavernaWorkflow 
     57  class MyExperimentWorkflow 
    13058     
    131     # possible input types 
    132     MY_EXPERIMENT = 'myexperiment' 
    133     T2_FLOW = 't2flow' 
     59    attr_reader(:xml_uri, :title, :description, :inputs, :outputs, :uploader_uri) 
    13460 
    135     attr_reader(:input_type, :xml_uri, :title, :description, :inputs, :outputs, :user) 
     61    def initialize(attributes) 
     62      @xml_uri = attributes[:xml_uri] 
     63      @title = attributes[:title] 
     64      @description = attributes[:description] 
     65      @inputs = attributes[:inputs] 
     66      @outputs = attributes[:outputs] 
     67      @uploader_uri = attributes[:uploader_uri] 
     68    end 
    13669 
    137     def initialize(input_type, xml_uri, title, description, inputs, outputs, user) 
    138       @input_type = input_type 
    139       @xml_uri = xml_uri 
    140       @title = title 
    141       @description = description 
    142       @inputs = inputs 
    143       @outputs = outputs 
    144       @user = user 
     70    # Parse workflow information XML and instantiate a _MyExperimentWorkflow_ object 
     71    def self.parse(xml) 
     72 
     73      wkf_inputs = [] 
     74      wkf_outputs = [] 
     75 
     76      doc = LibXML::XML::Document.string(xml) 
     77 
     78      doc.find("//workflow/components/dataflows/dataflow[@role='top']/sources/source").each do |element| 
     79        wkf_inputs << MyExperimentIOData.from_xml(element) 
     80      end 
     81 
     82      doc.find("//workflow/components/dataflows/dataflow[@role='top']/sinks/sink").each do |element| 
     83        wkf_outputs << MyExperimentIOData.from_xml(element) 
     84      end 
     85 
     86 
     87      new(:xml_uri => doc.find_first("/workflow/content-uri").content, 
     88          :title => doc.find_first("/workflow/title").content, 
     89          :description => doc.find_first("/workflow/description").content, 
     90          :inputs => wkf_inputs, 
     91          :outputs => wkf_outputs, 
     92          :uploader_uri => doc.find_first("/workflow/uploader").attributes['uri']) 
     93 
    14594    end 
    14695 
     
    155104  # changes we can subclass this one. 
    156105  # 
    157   class TavernaIOData 
     106  class MyExperimentIOData 
    158107    attr_reader(:name, :descriptions, :examples) 
    159108 
    160     def initialize(name, descriptions, examples) 
    161       @name = name 
    162       @descriptions = descriptions 
    163       @examples = examples 
     109    def initialize(attributes) 
     110      @name = attributes[:name] 
     111      @descriptions = attributes[:descriptions] 
     112      @examples = attributes[:examples] 
    164113    end 
    165114 
    166   end 
     115    def self.from_xml(xml_node) 
     116      name = '' 
     117      descriptions = [] 
     118      examples = [] 
     119 
     120      xml_node.each_element do |n| 
     121        if n.name.eql? "name" 
     122          name = n.children[0].to_s 
     123        elsif n.name.eql? "descriptions" 
     124          n.each_element do |d| 
     125            descriptions << d.children[0].to_s 
     126          end if n.children? 
     127        elsif n.name.eql? "examples" 
     128          n.each_element do |e| 
     129            examples << e.children[0].to_s 
     130          end if n.children? 
     131        end 
     132      end 
    167133 
    168134 
    169   # 
    170   # Contains all available information about an input or output: name, descriptions 
    171   # and examples. The last two are lists. 
    172   # 
    173   class TavernaUser 
    174     attr_reader(:name, :description, :email, :avatar, :website, :created_at) 
     135      new( 
     136        :name => name, 
     137        :descriptions => descriptions, 
     138        :examples => examples) 
    175139 
    176     def initialize(name, description, email, avatar, website, created_at) 
    177       @name = name 
    178       @description = description 
    179       @email = email 
    180       @avatar = avatar 
    181       @website = website 
    182       @created_at = created_at 
    183140    end 
    184141 
    185   end 
     142  end  # class MyExperimentIOData 
    186143 
     144end  # module 
    187145 
    188  
    189 end 
    190  
  • myexperiment-rest/trunk/Rakefile

    r151 r157  
    1 #  
    2 # To change this template, choose Tools | Templates 
    3 # and open the template in the editor. 
    4   
    5  
    61require 'rubygems' 
    72require 'rake' 
     
    138spec = Gem::Specification.new do |s| 
    149  s.name = 'myexperiment-rest' 
    15   s.version = '0.2.8' 
     10  s.version = '0.3.0' 
    1611  s.extra_rdoc_files = ['README', 'LICENSE', 'CHANGES'] 
    17   s.summary = 'This is a simple library to access data on myExperiment via its REST API. Currently supports a subset of the workflow information available.' 
    18   s.description = s.summary 
     12  s.summary = 'This is a simple library to access data on myExperiment via its REST API.' 
     13  s.description = 'This is a simple library to access data on myExperiment via its REST API. Currently supports a subset of the workflow information available.' 
    1914  s.author = 'Konstantinos Karasavvas' 
    2015  s.email = 'kostas.karasavvas@nbic.nl' 
     
    2419  s.bindir = "bin" 
    2520  s.add_dependency 'rest-client', '~> 1.6.3' 
    26   s.add_dependency 'libxml-ruby', '~> 2.0.5' 
     21  s.add_dependency 'libxml-ruby', '~> 2.0.9' 
    2722end 
    2823 
  • myexperiment-rest/trunk/README

    r151 r157  
    22 
    33Authors::     Konstantinos Karasavvas 
    4 Gem Version:: 0.2.8 
     4Gem Version:: 0.3.0 
    55Contact::     mailto:kostas.karasavvas@nbic.nl 
    66Licence::     MIT (See LICENCE or http://www.opensource.org/licenses/mit-license) 
     
    1515== Features/Problems 
    1616 
    17 Only a subset of myExperiment workflow data can be currently accessed. 
     17Only a subset of myExperiment workflow and user data can be currently accessed. 
    1818 
    1919 
     
    2121 
    2222There is an example script inside the <tt>bin</tt> directory that demonstrates 
    23 how you can use the library. 
     23how you can use the library: $ get_workflow_data.rb. 
    2424 
    2525 
  • myexperiment-rest/trunk/test/test_read_workflow.rb

    r152 r157  
    1010   
    1111  def setup 
    12     @wkf = Workflows.new.read('http://www.myexperiment.org/workflows/74/download/bioaid_proteindiscovery_781733.xml?version=5') 
     12    @wkf = Workflow.from_uri('http://www.myexperiment.org/workflows/74/download/bioaid_proteindiscovery_781733.xml?version=5') 
    1313  end 
    1414   
    1515  def test_workflow_values 
    16     assert_equal 'myexperiment', @wkf.input_type, "Workflow's input type not properly initialized!" 
    1716    assert_equal 'http://www.myexperiment.org/workflows/74/download/bioaid_proteindiscovery_781733.t2flow', @wkf.xml_uri, "Workflow's XML URI not properly initialized!" 
    1817    assert_equal 'BioAID_ProteinDiscovery', @wkf.title, "Workflow's title not properly initialized!" 
    19     assert_equal '<p>The workflow extracts protein names from documents retrieved from MedLine based on a user Query (cf Apache Lucene syntax). The protein names are filtered by checking if there exists a valid UniProt ID for the given protein name.</p>', 
     18    assert_equal '<p>The workflow extracts protein names from documents retrieved from MedLine based ' + 
     19                 'on a user Query (cf Apache Lucene syntax). The protein names are filtered by checking ' + 
     20                 'if there exists a valid UniProt ID for the given protein name.</p>', 
    2021                 @wkf.description, "Workflow's description not properly initialized!" 
     22    assert_equal 'http://www.myexperiment.org/user.xml?id=18', @wkf.uploader_uri, "Workflow's uploader URI not properly initialized!" 
    2123    assert_equal 2, @wkf.inputs.size, "Workflow's inputs size not properly initialized!" 
    2224    assert_equal 2, @wkf.outputs.size, "Workflow's outputs size not properly initialized!"