openbel-api 0.4.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gemspec +65 -0
- data/CHANGELOG.md +22 -0
- data/INSTALL.md +19 -0
- data/INSTALL_RUBY.md +107 -0
- data/LICENSE +191 -0
- data/README.md +208 -0
- data/app/openbel/api/app.rb +83 -0
- data/app/openbel/api/config.rb +45 -0
- data/app/openbel/api/config.ru +3 -0
- data/app/openbel/api/helpers/pager.rb +109 -0
- data/app/openbel/api/middleware/auth.rb +112 -0
- data/app/openbel/api/resources/adapters/basic_json.rb +52 -0
- data/app/openbel/api/resources/annotation.rb +141 -0
- data/app/openbel/api/resources/base.rb +16 -0
- data/app/openbel/api/resources/completion.rb +89 -0
- data/app/openbel/api/resources/evidence.rb +115 -0
- data/app/openbel/api/resources/evidence_transform.rb +143 -0
- data/app/openbel/api/resources/function.rb +98 -0
- data/app/openbel/api/resources/match_result.rb +79 -0
- data/app/openbel/api/resources/namespace.rb +174 -0
- data/app/openbel/api/routes/annotations.rb +168 -0
- data/app/openbel/api/routes/authenticate.rb +108 -0
- data/app/openbel/api/routes/base.rb +326 -0
- data/app/openbel/api/routes/datasets.rb +519 -0
- data/app/openbel/api/routes/evidence.rb +330 -0
- data/app/openbel/api/routes/expressions.rb +560 -0
- data/app/openbel/api/routes/functions.rb +41 -0
- data/app/openbel/api/routes/namespaces.rb +382 -0
- data/app/openbel/api/routes/root.rb +39 -0
- data/app/openbel/api/schemas.rb +34 -0
- data/app/openbel/api/schemas/annotation_collection.schema.json +20 -0
- data/app/openbel/api/schemas/annotation_resource.schema.json +36 -0
- data/app/openbel/api/schemas/annotation_value_collection.schema.json +21 -0
- data/app/openbel/api/schemas/annotation_value_resource.schema.json +35 -0
- data/app/openbel/api/schemas/completion_collection.schema.json +21 -0
- data/app/openbel/api/schemas/completion_resource.schema.json +146 -0
- data/app/openbel/api/schemas/evidence.schema.json +198 -0
- data/app/openbel/api/schemas/evidence_collection.schema.json +98 -0
- data/app/openbel/api/schemas/evidence_resource.schema.json +29 -0
- data/app/openbel/api/schemas/namespace_value_collection.schema.json +21 -0
- data/app/openbel/api/schemas/namespace_value_resource.schema.json +43 -0
- data/app/openbel/api/util.rb +11 -0
- data/bin/openbel-api +78 -0
- data/bin/openbel-config +46 -0
- data/config/async_evidence.rb +12 -0
- data/config/async_jena.rb +14 -0
- data/config/config.yml +31 -0
- data/config/server_config.rb +184 -0
- data/lib/openbel/api/cache/cache.rb +30 -0
- data/lib/openbel/api/config/config.rb +33 -0
- data/lib/openbel/api/evidence/api.rb +39 -0
- data/lib/openbel/api/evidence/facet_api.rb +18 -0
- data/lib/openbel/api/evidence/facet_filter.rb +83 -0
- data/lib/openbel/api/evidence/mongo.rb +247 -0
- data/lib/openbel/api/evidence/mongo_facet.rb +105 -0
- data/lib/openbel/api/helpers/dependency_graph.rb +52 -0
- data/lib/openbel/api/model/rdf_resource.rb +74 -0
- data/lib/openbel/api/plugin/cache/kyotocabinet.rb +85 -0
- data/lib/openbel/api/plugin/configure_plugins.rb +97 -0
- data/lib/openbel/api/plugin/evidence/evidence.rb +58 -0
- data/lib/openbel/api/plugin/plugin.rb +99 -0
- data/lib/openbel/api/plugin/plugin_manager.rb +20 -0
- data/lib/openbel/api/plugin/plugin_repository.rb +60 -0
- data/lib/openbel/api/storage/cache_proxy.rb +74 -0
- data/lib/openbel/api/storage/triple_storage.rb +43 -0
- 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
|