Diff
Modified: branches/components/Rakefile (3201 => 3202)
--- branches/components/Rakefile 2012-11-26 13:56:31 UTC (rev 3201)
+++ branches/components/Rakefile 2012-11-26 13:58:33 UTC (rev 3202)
@@ -5,7 +5,7 @@
require 'rake'
require 'rake/testtask'
-require 'rake/rdoctask'
+require 'rdoc/task'
require 'tasks/rails'
Added: branches/components/app/models/semantic_annotation.rb (0 => 3202)
--- branches/components/app/models/semantic_annotation.rb (rev 0)
+++ branches/components/app/models/semantic_annotation.rb 2012-11-26 13:58:33 UTC (rev 3202)
@@ -0,0 +1,3 @@
+class SemanticAnnotation < ActiveRecord::Base
+ belongs_to :subject, :polymorphic => true
+end
Added: branches/components/app/models/workflow_port.rb (0 => 3202)
--- branches/components/app/models/workflow_port.rb (rev 0)
+++ branches/components/app/models/workflow_port.rb 2012-11-26 13:58:33 UTC (rev 3202)
@@ -0,0 +1,7 @@
+class WorkflowPort < ActiveRecord::Base
+
+ validates_inclusion_of :port_type, :in => ["input", "output"]
+ belongs_to :workflow
+ has_many :semantic_annotations, :as => :subject
+
+end
Modified: branches/components/config/default_settings.yml (3201 => 3202)
--- branches/components/config/default_settings.yml 2012-11-26 13:56:31 UTC (rev 3201)
+++ branches/components/config/default_settings.yml 2012-11-26 13:58:33 UTC (rev 3202)
@@ -544,6 +544,7 @@
topic_workflow_map: INNER JOIN topic_workflow_map ON contributions.id = topic_workflow_map.workflow_id
users: INNER JOIN users ON contributions.contributor_type = 'User' AND contributions.contributor_id = users.id
licences: LEFT OUTER JOIN licenses ON contributions.license_id = licenses.id
+ component_profiles: LEFT OUTER JOIN workflows ON RESULT_TYPE = 'Workflow' AND workflows.id = RESULT_ID LEFT OUTER JOIN component_profiles ON workflows.component_profile_id = component_profiles.id
order:
@@ -667,5 +668,11 @@
label_column: services.monitor_label
joins: [services]
+ - query_option: COMPONENT_PROFILE_ID
+ title: component profile
+ id_column: component_profiles.id
+ label_column: component_profiles.name
+ joins: [component_profiles]
+
num_options: ["10", "20", "25", "50", "100"]
Modified: branches/components/config/tables.xml
(Binary files differ)
Added: branches/components/db/migrate/20121126093655_create_semantic_annotations.rb (0 => 3202)
--- branches/components/db/migrate/20121126093655_create_semantic_annotations.rb (rev 0)
+++ branches/components/db/migrate/20121126093655_create_semantic_annotations.rb 2012-11-26 13:58:33 UTC (rev 3202)
@@ -0,0 +1,14 @@
+class CreateSemanticAnnotations < ActiveRecord::Migration
+ def self.up
+ create_table :semantic_annotations do |t|
+ t.integer :subject_id
+ t.string :subject_type
+ t.string :predicate
+ t.string :object
+ end
+ end
+
+ def self.down
+ drop_table :semantic_annotations
+ end
+end
Added: branches/components/db/migrate/20121126095828_create_workflow_ports.rb (0 => 3202)
--- branches/components/db/migrate/20121126095828_create_workflow_ports.rb (rev 0)
+++ branches/components/db/migrate/20121126095828_create_workflow_ports.rb 2012-11-26 13:58:33 UTC (rev 3202)
@@ -0,0 +1,13 @@
+class CreateWorkflowPorts < ActiveRecord::Migration
+ def self.up
+ create_table :workflow_ports do |t|
+ t.string :name
+ t.string :port_type
+ t.integer :workflow_id
+ end
+ end
+
+ def self.down
+ drop_table :workflow_ports
+ end
+end
Modified: branches/components/db/schema.rb (3201 => 3202)
--- branches/components/db/schema.rb 2012-11-26 13:56:31 UTC (rev 3201)
+++ branches/components/db/schema.rb 2012-11-26 13:58:33 UTC (rev 3202)
@@ -9,7 +9,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20121112134053) do
+ActiveRecord::Schema.define(:version => 20121126095828) do
create_table "activity_limits", :force => true do |t|
t.string "contributor_type", :null => false
@@ -143,6 +143,13 @@
add_index "comments", ["user_id"], :name => "index_comments_on_user_id"
+ create_table "component_profiles", :force => true do |t|
+ t.string "name"
+ t.string "url"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
create_table "concept_relations", :force => true do |t|
t.integer "subject_concept_id"
t.string "relation_type"
@@ -576,6 +583,13 @@
add_index "reviews", ["user_id"], :name => "index_reviews_on_user_id"
+ create_table "semantic_annotations", :force => true do |t|
+ t.integer "subject_id"
+ t.string "subject_type"
+ t.string "predicate"
+ t.string "object"
+ end
+
create_table "service_categories", :force => true do |t|
t.string "uri"
t.datetime "updated_at"
@@ -790,6 +804,12 @@
t.string "uri"
end
+ create_table "workflow_ports", :force => true do |t|
+ t.string "name"
+ t.string "port_type"
+ t.integer "workflow_id"
+ end
+
create_table "workflow_processors", :force => true do |t|
t.string "name"
t.string "wsdl_operation"
@@ -819,8 +839,6 @@
t.integer "preview_id"
end
- add_index "workflow_versions", ["workflow_id"], :name => "index_workflow_versions_on_workflow_id"
-
create_table "workflows", :force => true do |t|
t.integer "contributor_id"
t.string "contributor_type"
@@ -839,6 +857,7 @@
t.integer "content_type_id"
t.integer "license_id"
t.integer "preview_id"
+ t.integer "component_profile_id"
end
create_table "wsdl_deprecations", :force => true do |t|
Modified: branches/components/lib/rest.rb (3201 => 3202)
--- branches/components/lib/rest.rb 2012-11-26 13:56:31 UTC (rev 3201)
+++ branches/components/lib/rest.rb 2012-11-26 13:58:33 UTC (rev 3202)
@@ -2293,3 +2293,100 @@
end
end
+
+# Component Querying
+def get_components(opts)
+ puts "\n" * 10
+
+ query = opts[:query]
+ puts query.inspect
+
+ annotations = (query['hasAnnotations'] || "").split('","').collect {|a| a.gsub('"','')} # annotations on workflow itself
+ # annotations on workflow features
+ inputs = query["hasInput"] || {}#(query["inputs"] || "").split('),')
+ outputs = query["hasOutput"] || {} #(query["outputs"] || "").split('),')
+ processors = query["hasProcessor"] || {} #(query["processors"] || "").split('),')
+
+
+ workflows = Workflow.all # This should be filtered first
+
+ def get_workflow_feature_matches(workflows, features, model, query_conditions, query_conditions_excluding)
+ # "features" is an array of sets of annotations to be queried, in the form ['"<ann1>,"<ann2>"','"<ann3>"']
+ # The above example states that the workflow must have a <feature> that has annotations "pred1 obj1" and "pred2 obj2", AND
+ # another, different <feature> with "<ann3>".
+ #
+ # The annotations are in the form "<predicate> <object>".
+
+ # This method returns an array of arrays of workflows
+ selected = []
+ features.collect do |key,set|
+ raise "Bad Syntax" unless set =~ /^("[^ ]+ [^"]+")(,"[^ ]+ [^"]+")*$/
+
+ feature_annotations = set.split('","').collect {|a| a.gsub('"','')}
+ puts feature_annotations.inspect
+ # "<ann1>", "<ann2>" (example)
+ matching_features = feature_annotations.collect { |a|
+ # Find all <features> with semantic annotation "<predicate> <object>" (example)
+ predicate, object = a.split(" ", 2)
+ unless selected.empty?
+ model.find(:all, :include => :semantic_annotations,
+ :conditions => [query_conditions, workflows, predicate, object, selected])
+ else
+ model.find(:all, :include => :semantic_annotations,
+ :conditions => [query_conditions_excluding, workflows, predicate, object])
+ end
+
+ }.inject {|f, matches| matches & f} # Get the intersection of <features> that have each annotation.
+ # ie. the set of <features> that have ALL the required annotations
+ selected += matching_features
+ matching_features.collect {|wp| wp.workflow} # Get the workflows that those features belong to
+ end
+ end
+
+ begin
+ # Workflows that have the required inputs
+ matches_input_requirements = get_workflow_feature_matches(workflows, inputs, WorkflowPort,
+ "workflow_id IN (?) AND semantic_annotations.predicate = ? AND semantic_annotations.object = ? AND port_type = 'input' AND workflow_ports.id NOT IN (?)",
+ "workflow_id IN (?) AND semantic_annotations.predicate = ? AND semantic_annotations.object = ? AND port_type = 'input'")
+
+ # Workflows that have the required outputs
+ matches_output_requirements = get_workflow_feature_matches(workflows, outputs, WorkflowPort,
+ "workflow_id IN (?) AND semantic_annotations.predicate = ? AND semantic_annotations.object = ? AND port_type = 'output' AND workflow_ports.id NOT IN (?)",
+ "workflow_id IN (?) AND semantic_annotations.predicate = ? AND semantic_annotations.object = ? AND port_type = 'output'")
+
+ # Workflows that have the required processors
+ matches_processor_requirements = get_workflow_feature_matches(workflows, processors, WorkflowProcessor,
+ "workflow_id IN (?) AND semantic_annotations.predicate = ? AND semantic_annotations.object = ? AND workflow_processors.id NOT IN (?)",
+ "workflow_id IN (?) AND semantic_annotations.predicate = ? AND semantic_annotations.object = ?")
+
+ # Workflows that have the required semantic annotations
+ matches_semantic_annotation_requirements = annotations.collect do |p|
+ [Workflow.find(:all, :include => :semantic_annotations,
+ :conditions => {:id => workflows,
+ :semantic_annotations => {:value => p}})]
+ end
+ rescue RuntimeError => e
+ if e.message == "Bad Syntax"
+ return rest_response(400)
+ else
+ raise e
+ end
+ end
+
+ # Create an array containing arrays of each set of matches
+ matches = matches_input_requirements +
+ matches_output_requirements +
+ matches_processor_requirements +
+ matches_semantic_annotation_requirements
+
+ puts "\n" * 10
+ puts "Pre Matches:"
+ puts matches.inspect
+ puts "\n" * 10
+
+ # Workflows that match ALL the requirements - the intersection of all the sub arrays.
+ matches = matches.inject {|matches, matches_all| matches_all & matches}
+
+ # Render
+ produce_rest_list(opts[:uri], opts[:rules], query, matches, "workflows", [], opts[:user])
+end