Changeset 157


Ignore:
Timestamp:
Sep 28, 2011, 12:51:50 PM (5 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 edited
1 copied

Legend:

Unmodified
Added
Removed
  • 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/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/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/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/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/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!"
Note: See TracChangeset for help on using the changeset viewer.