openbel-api 0.4.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gemspec +65 -0
  3. data/CHANGELOG.md +22 -0
  4. data/INSTALL.md +19 -0
  5. data/INSTALL_RUBY.md +107 -0
  6. data/LICENSE +191 -0
  7. data/README.md +208 -0
  8. data/app/openbel/api/app.rb +83 -0
  9. data/app/openbel/api/config.rb +45 -0
  10. data/app/openbel/api/config.ru +3 -0
  11. data/app/openbel/api/helpers/pager.rb +109 -0
  12. data/app/openbel/api/middleware/auth.rb +112 -0
  13. data/app/openbel/api/resources/adapters/basic_json.rb +52 -0
  14. data/app/openbel/api/resources/annotation.rb +141 -0
  15. data/app/openbel/api/resources/base.rb +16 -0
  16. data/app/openbel/api/resources/completion.rb +89 -0
  17. data/app/openbel/api/resources/evidence.rb +115 -0
  18. data/app/openbel/api/resources/evidence_transform.rb +143 -0
  19. data/app/openbel/api/resources/function.rb +98 -0
  20. data/app/openbel/api/resources/match_result.rb +79 -0
  21. data/app/openbel/api/resources/namespace.rb +174 -0
  22. data/app/openbel/api/routes/annotations.rb +168 -0
  23. data/app/openbel/api/routes/authenticate.rb +108 -0
  24. data/app/openbel/api/routes/base.rb +326 -0
  25. data/app/openbel/api/routes/datasets.rb +519 -0
  26. data/app/openbel/api/routes/evidence.rb +330 -0
  27. data/app/openbel/api/routes/expressions.rb +560 -0
  28. data/app/openbel/api/routes/functions.rb +41 -0
  29. data/app/openbel/api/routes/namespaces.rb +382 -0
  30. data/app/openbel/api/routes/root.rb +39 -0
  31. data/app/openbel/api/schemas.rb +34 -0
  32. data/app/openbel/api/schemas/annotation_collection.schema.json +20 -0
  33. data/app/openbel/api/schemas/annotation_resource.schema.json +36 -0
  34. data/app/openbel/api/schemas/annotation_value_collection.schema.json +21 -0
  35. data/app/openbel/api/schemas/annotation_value_resource.schema.json +35 -0
  36. data/app/openbel/api/schemas/completion_collection.schema.json +21 -0
  37. data/app/openbel/api/schemas/completion_resource.schema.json +146 -0
  38. data/app/openbel/api/schemas/evidence.schema.json +198 -0
  39. data/app/openbel/api/schemas/evidence_collection.schema.json +98 -0
  40. data/app/openbel/api/schemas/evidence_resource.schema.json +29 -0
  41. data/app/openbel/api/schemas/namespace_value_collection.schema.json +21 -0
  42. data/app/openbel/api/schemas/namespace_value_resource.schema.json +43 -0
  43. data/app/openbel/api/util.rb +11 -0
  44. data/bin/openbel-api +78 -0
  45. data/bin/openbel-config +46 -0
  46. data/config/async_evidence.rb +12 -0
  47. data/config/async_jena.rb +14 -0
  48. data/config/config.yml +31 -0
  49. data/config/server_config.rb +184 -0
  50. data/lib/openbel/api/cache/cache.rb +30 -0
  51. data/lib/openbel/api/config/config.rb +33 -0
  52. data/lib/openbel/api/evidence/api.rb +39 -0
  53. data/lib/openbel/api/evidence/facet_api.rb +18 -0
  54. data/lib/openbel/api/evidence/facet_filter.rb +83 -0
  55. data/lib/openbel/api/evidence/mongo.rb +247 -0
  56. data/lib/openbel/api/evidence/mongo_facet.rb +105 -0
  57. data/lib/openbel/api/helpers/dependency_graph.rb +52 -0
  58. data/lib/openbel/api/model/rdf_resource.rb +74 -0
  59. data/lib/openbel/api/plugin/cache/kyotocabinet.rb +85 -0
  60. data/lib/openbel/api/plugin/configure_plugins.rb +97 -0
  61. data/lib/openbel/api/plugin/evidence/evidence.rb +58 -0
  62. data/lib/openbel/api/plugin/plugin.rb +99 -0
  63. data/lib/openbel/api/plugin/plugin_manager.rb +20 -0
  64. data/lib/openbel/api/plugin/plugin_repository.rb +60 -0
  65. data/lib/openbel/api/storage/cache_proxy.rb +74 -0
  66. data/lib/openbel/api/storage/triple_storage.rb +43 -0
  67. metadata +379 -0
@@ -0,0 +1,105 @@
1
+ require 'mongo'
2
+ require 'multi_json'
3
+ require_relative 'facet_api'
4
+ require_relative 'facet_filter'
5
+
6
+ module OpenBEL
7
+ module Evidence
8
+
9
+ class EvidenceFacets
10
+ include FacetAPI
11
+ include Mongo
12
+ include FacetFilter
13
+
14
+ def initialize(options = {})
15
+ host = options.delete(:host)
16
+ port = options.delete(:port)
17
+ db = options.delete(:database)
18
+ @db = MongoClient.new(host, port).db(db)
19
+ @evidence = @db[:evidence]
20
+ @evidence_facets = @db[:evidence_facets]
21
+ end
22
+
23
+ def create_facets(_id, query_hash)
24
+ # create and save facets, identified by query
25
+ facets_doc = _id.merge({
26
+ :facets => evidence_facets(query_hash)
27
+ })
28
+ @evidence_facets.save(facets_doc, :j => true)
29
+
30
+ # return facets document
31
+ facets_doc
32
+ end
33
+
34
+ def find_facets(query_hash, filters)
35
+ _id = {:_id => to_facets_id(filters)}
36
+ @evidence_facets.find_one(_id) || create_facets(_id, query_hash)
37
+ end
38
+
39
+ def remove_facets_by_filters(filters = [], options = {})
40
+ remove_spec =
41
+ if filters.empty?
42
+ { :_id => "" }
43
+ else
44
+ {
45
+ :_id => {
46
+ :$in => filters.map { |filter|
47
+ to_regexp(MultiJson.load(filter))
48
+ }
49
+ }
50
+ }
51
+ end
52
+ @evidence_facets.remove(remove_spec, :j => true)
53
+ end
54
+
55
+ private
56
+
57
+ def to_regexp(filter)
58
+ filter_s = "#{filter['category']}|#{filter['name']}|#{filter['value']}"
59
+ %r{.*#{Regexp.escape(filter_s)}.*}
60
+ end
61
+
62
+
63
+ def to_facets_id(filters)
64
+ filters.map { |filter|
65
+ "#{filter['category']}|#{filter['name']}|#{filter['value']}"
66
+ }.sort.join(',')
67
+ end
68
+
69
+ def evidence_facets(query_hash = nil)
70
+ pipeline =
71
+ if query_hash.is_a?(Hash) && !query_hash.empty?
72
+ [{:'$match' => query_hash}] + AGGREGATION_PIPELINE
73
+ else
74
+ AGGREGATION_PIPELINE
75
+ end
76
+ @evidence.aggregate(pipeline)
77
+ end
78
+
79
+ AGGREGATION_PIPELINE = [
80
+ {
81
+ :'$project' => {
82
+ :_id => 0,
83
+ :facets => 1
84
+ }
85
+ },
86
+ {
87
+ :'$unwind' => '$facets'
88
+ },
89
+ {
90
+ :'$group' => {
91
+ :_id => '$facets',
92
+ :count => {
93
+ :'$sum' => 1
94
+ }
95
+ }
96
+ },
97
+ {
98
+ :'$sort' => {
99
+ :count => -1
100
+ }
101
+ }
102
+ ]
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,52 @@
1
+ require 'tsort'
2
+
3
+ module OpenBEL
4
+ module Helpers
5
+
6
+ class DependencyGraph
7
+ include TSort
8
+
9
+ def initialize
10
+ @hash = Hash.new { |hash, key| hash[key] = [] }
11
+ end
12
+
13
+ def [](key)
14
+ @hash[key]
15
+ end
16
+
17
+ def add_dependency(first, *dependency_requirements)
18
+ @hash[first] ||= []
19
+ (dependency_requirements || []).flatten.each do |dep|
20
+ _add_dependency(first, dep)
21
+ end
22
+ @hash[first]
23
+ end
24
+
25
+ def delete(key)
26
+ @hash.delete(key)
27
+ end
28
+
29
+ def each_key(&block)
30
+ @hash.each_key(&block)
31
+ end
32
+
33
+ def tsort_each_child(key, &block)
34
+ @hash[key].each(&block)
35
+ end
36
+
37
+ def tsort_each_node(&block)
38
+ @hash.each_key(&block)
39
+ end
40
+
41
+ private
42
+
43
+ def _add_dependency(key1, key2)
44
+ @hash[key1] << key2
45
+ @hash[key2] = []
46
+ key2
47
+ end
48
+ end
49
+ end
50
+ end
51
+ # vim: ts=2 sts=2 sw=2 expandtab
52
+ # encoding: utf-8
@@ -0,0 +1,74 @@
1
+ module OpenBEL
2
+ module Model
3
+
4
+ VOCABULARY_RDF = 'http://www.openbel.org/vocabulary/'
5
+
6
+ def self.included base
7
+ base.extend ClassMethods
8
+ end
9
+
10
+ module ClassMethods
11
+ def from(statements)
12
+ obj = self.new
13
+ statements.each do |sub, pred, obj_val|
14
+ index = pred.rindex('#') || pred.rindex('/')
15
+ if index
16
+ attribute = pred[index+1..-1]
17
+
18
+ # handle type statement
19
+ if attribute == 'type'
20
+ # ... the URI
21
+ if obj.respond_to?(:uri=)
22
+ obj.send(:uri=, sub)
23
+ end
24
+ # ... the BEL vocabulary type
25
+ if obj_val.start_with?(VOCABULARY_RDF) and obj.respond_to?(:type=)
26
+ obj.send(:type=, obj_val)
27
+ next
28
+ end
29
+ end
30
+ if obj.respond_to? :"#{attribute}="
31
+ obj.send(:"#{attribute}=", obj_val)
32
+ end
33
+ else
34
+ $stderr.puts "cannot parse local name for #{pred}"
35
+ end
36
+ end
37
+ (obj.respond_to? :uri and obj.uri) ? obj : nil
38
+ end
39
+ end
40
+
41
+ class RdfResource
42
+ include OpenBEL::Model
43
+
44
+ def initialize(attr_values = {})
45
+ attr_values.each { |k, v|
46
+ instance_variable_set(:"@#{k}", v)
47
+ }
48
+ end
49
+
50
+ attr_accessor :uri
51
+
52
+ def ==(other)
53
+ return false if other == nil
54
+ @uri == other.uri
55
+ end
56
+
57
+ def hash
58
+ @uri.hash
59
+ end
60
+
61
+ def to_hash
62
+ instance_variables.inject({}) { |res, attr|
63
+ res.merge({attr[1..-1] => instance_variable_get(attr)})
64
+ }
65
+ end
66
+
67
+ def to_s
68
+ @uri
69
+ end
70
+ end
71
+ end
72
+ end
73
+ # vim: ts=2 sts=2 sw=2
74
+ # encoding: utf-8
@@ -0,0 +1,85 @@
1
+ require 'pp'
2
+ require_relative '../plugin'
3
+
4
+ module OpenBEL
5
+ module Plugin
6
+
7
+ class CacheKyotoCabinet
8
+ include OpenBEL::Plugin
9
+
10
+ ID = 'kyotocabinet'
11
+ NAME = 'KyotoCabinet Cache'
12
+ DESC = 'Cache implementation using KyotoCabinet over FFI.'
13
+ MEMR_TYPES = [ :"memory-hash" ]
14
+ FILE_TYPES = [ :"file-hash" ]
15
+ TYPE_OPTION_VALUES = [ MEMR_TYPES, FILE_TYPES ].flatten
16
+ MODE_OPTION_VALUES = [ :reader, :writer, :create ]
17
+
18
+ CREATE_MUTEX = Mutex.new
19
+
20
+ def id
21
+ ID
22
+ end
23
+
24
+ def name
25
+ NAME
26
+ end
27
+
28
+ def description
29
+ DESC
30
+ end
31
+
32
+ def type
33
+ :cache
34
+ end
35
+
36
+ def on_load
37
+ require 'kyotocabinet_ffi'
38
+ end
39
+
40
+ def validate(extensions = {}, options = {})
41
+ type = options.delete(:type)
42
+ if not type
43
+ return ValidationError.new(self, :type, "Option is missing. Options are one of [#{TYPE_OPTION_VALUES.join(', ')}].")
44
+ end
45
+ type = type.to_sym
46
+ if not TYPE_OPTION_VALUES.include?(type)
47
+ return ValidationError.new(self, :type, "Value not supported. Options are one of [#{TYPE_OPTION_VALUES.join(', ')}].")
48
+ end
49
+
50
+ mode = options.delete(:mode)
51
+ if not mode
52
+ return ValidationError.new(self, :mode, "Option is missing. Options are one of [#{MODE_OPTION_VALUES.join(', ')}].")
53
+ end
54
+ mode = mode.map { |v| v.to_s.to_sym }
55
+
56
+ validation_successful
57
+ end
58
+
59
+ def configure(extensions = {}, options = {})
60
+ @options = options
61
+ end
62
+
63
+ def create_instance
64
+ CREATE_MUTEX.lock
65
+ begin
66
+ unless @instance
67
+ type = @options[:type].to_sym
68
+ mode = @options[:mode].map { |v| v.to_s.to_sym }
69
+
70
+ @instance = case type
71
+ when :"memory-hash"
72
+ KyotoCabinet::Db::MemoryHash.new mode
73
+ when :"file-hash"
74
+ KyotoCabinet::Db::PolymorphicDb::tmp_filedb(KyotoCabinet::FILE_HASH)
75
+ end
76
+ end
77
+ ensure
78
+ CREATE_MUTEX.unlock
79
+ end
80
+
81
+ @instance
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,97 @@
1
+ require_relative '../helpers/dependency_graph'
2
+
3
+ module OpenBEL
4
+ module ConfigurePlugins
5
+
6
+ def check_configuration(plugins, config)
7
+ sorted_plugin_config_ids = build_dependency_graph(config)
8
+
9
+ all_errors = []
10
+ valid_plugins = {}
11
+ sorted_plugin_config_ids.each do |plugin_config_id|
12
+ # validate plugin configuration...
13
+ plugin_config = config[plugin_config_id.to_s]
14
+
15
+ # ...check plugin defines required properties
16
+ ['type', 'plugin'].each do |p|
17
+ errors << %Q{The "#{p}" property (defined in "#{plugin_config_id}") does not define a type.} unless plugin_config.has_key?(p)
18
+ next
19
+ end
20
+ type = plugin_config['type']
21
+ plugin_id = plugin_config['plugin']
22
+
23
+ # ...check if any plugin(s) are loaded for specified type
24
+ if plugins.none? { |p| p.type.to_s.to_sym == type.to_s.to_sym }
25
+ errors << %Q{The "#{type}" type (defined in "#{plugin_config_id}") does not have any registered plugins.}
26
+ end
27
+
28
+ # ...check if plugin exists
29
+ plugin = plugins.find { |p| p.id == plugin_id }
30
+ unless plugin
31
+ errors << %Q{The "#{plugin_id}" plugin (defined in "#{plugin_config_id}") does not have any registered plugins.}
32
+ end
33
+
34
+ # ...check plugin extensions
35
+ extensions = plugin_config['extensions'] || {}
36
+ extensions.values.find_all { |ext|
37
+ not valid_plugins.has_key? ext.to_s
38
+ }.each do |ext|
39
+ all_errors << %Q{The "#{ext}" extension (defined in "#{plugin_config_id}") is not valid.}
40
+ end
41
+
42
+ # ...prepare extensions/options for plugin validation
43
+ extensions = Hash[extensions.map { |ext_type, ext_id|
44
+ [ext_type.to_s.to_sym, valid_plugins[ext_id.to_s]]
45
+ }]
46
+ options = Hash[(plugin_config['options'] || {}).map { |k, v|
47
+ [k.to_s.to_sym, v]
48
+ }]
49
+
50
+ # ...call plugin-specific validation
51
+ plugin_errors = [plugin.validate(extensions.dup, options.dup)].flatten.map(&:to_s)
52
+ if plugin_errors.empty?
53
+ valid_plugins[plugin_config_id.to_s] = plugin
54
+ else
55
+ all_errors.concat(plugin_errors)
56
+ end
57
+ # TODO Log successful plugin check if verbose.
58
+ end
59
+ all_errors
60
+ end
61
+
62
+ def configure_plugins(plugins, config)
63
+ sorted_plugin_config_ids = build_dependency_graph(config)
64
+ sorted_plugin_config_ids.inject({}) { |plugins_by_id, plugin_config_id|
65
+ plugin_config = config[plugin_config_id.to_s]
66
+
67
+ plugin_id = plugin_config['plugin']
68
+
69
+ plugin = plugins.find { |p| p.id == plugin_id }
70
+ extensions = Hash[(plugin_config['extensions'] || {}).map { |type, id|
71
+ [type.to_s.to_sym, plugins_by_id[id.to_s]]
72
+ }]
73
+ options = Hash[(plugin_config['options'] || {}).map { |k, v|
74
+ [k.to_s.to_sym, v]
75
+ }]
76
+
77
+ plugin.configure(extensions.dup, options.dup)
78
+ plugin.on_load
79
+
80
+ plugins_by_id[plugin_config_id.to_s] = plugin
81
+ plugins_by_id
82
+ }
83
+ end
84
+
85
+ private
86
+
87
+ def build_dependency_graph(config)
88
+ dependency_graph = Helpers::DependencyGraph.new
89
+ config.keys.each do |plugin_key|
90
+ block = config[plugin_key]
91
+ dependencies = (block['extensions'] || {}).each_value.to_a.map { |v| v.to_s.to_sym }
92
+ dependency_graph.add_dependency(plugin_key.to_s, *dependencies)
93
+ end
94
+ dependency_graph.tsort
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,58 @@
1
+ require_relative '../plugin'
2
+
3
+ module OpenBEL
4
+ module Plugin
5
+
6
+ class Evidence
7
+ include OpenBEL::Plugin
8
+
9
+ ID = 'evidence'
10
+ NAME = 'OpenBEL Evidence API'
11
+ DESC = 'API for accesing OpenBEL Evidence.'
12
+
13
+ def id
14
+ ID
15
+ end
16
+
17
+ def name
18
+ NAME
19
+ end
20
+
21
+ def description
22
+ DESC
23
+ end
24
+
25
+ def type
26
+ :evidence
27
+ end
28
+
29
+ def required_extensions
30
+ []
31
+ end
32
+
33
+ def optional_extensions
34
+ []
35
+ end
36
+
37
+ def on_load
38
+ require_relative '../../evidence/mongo'
39
+ end
40
+
41
+ def validate(extensions = {}, options = {})
42
+ [:host, :port, :database].map { |setting|
43
+ unless options[setting]
44
+ ValidationError.new(self, :storage, "The #{setting} setting is missing.")
45
+ end
46
+ }.compact!
47
+ end
48
+
49
+ def configure(extensions = {}, options = {})
50
+ @options = options
51
+ end
52
+
53
+ def create_instance
54
+ OpenBEL::Evidence::Evidence.new(@options)
55
+ end
56
+ end
57
+ end
58
+ end