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,83 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
# TODO This should probably be in app-config.rb.
|
4
|
+
require 'jrjackson'
|
5
|
+
|
6
|
+
require_relative 'util'
|
7
|
+
|
8
|
+
require 'rack/cors'
|
9
|
+
require 'sinatra/base'
|
10
|
+
require "sinatra/reloader"
|
11
|
+
require "sinatra/cookies"
|
12
|
+
|
13
|
+
require_relative 'config'
|
14
|
+
require_relative 'routes/base'
|
15
|
+
require_relative 'routes/root'
|
16
|
+
require_relative 'routes/annotations'
|
17
|
+
require_relative 'routes/evidence'
|
18
|
+
require_relative 'routes/datasets'
|
19
|
+
require_relative 'routes/expressions'
|
20
|
+
require_relative 'routes/functions'
|
21
|
+
require_relative 'routes/namespaces'
|
22
|
+
require_relative 'routes/authenticate'
|
23
|
+
require_relative 'middleware/auth'
|
24
|
+
|
25
|
+
module OpenBEL
|
26
|
+
|
27
|
+
class Server < Sinatra::Application
|
28
|
+
|
29
|
+
configure :development do
|
30
|
+
register Sinatra::Reloader
|
31
|
+
end
|
32
|
+
|
33
|
+
configure do
|
34
|
+
config = OpenBEL::Config::load!
|
35
|
+
OpenBEL.const_set :Settings, config
|
36
|
+
end
|
37
|
+
|
38
|
+
if OpenBEL::Settings[:auth][:enabled]
|
39
|
+
enable :sessions
|
40
|
+
set :session_secret, OpenBEL::Settings['session_secret']
|
41
|
+
end
|
42
|
+
|
43
|
+
use Rack::Deflater
|
44
|
+
use Rack::Cors do
|
45
|
+
allow do
|
46
|
+
origins '*'
|
47
|
+
resource '*',
|
48
|
+
:headers => :any,
|
49
|
+
:methods => [ :get, :post, :put, :delete, :options ],
|
50
|
+
:max_age => 1,
|
51
|
+
:credentials => false,
|
52
|
+
:expose => [
|
53
|
+
'Allow',
|
54
|
+
'Content-Type',
|
55
|
+
'Content-Encoding',
|
56
|
+
'Content-Length',
|
57
|
+
'ETag',
|
58
|
+
'Last-Modified',
|
59
|
+
'Link',
|
60
|
+
'Location'
|
61
|
+
]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
disable :protection
|
65
|
+
|
66
|
+
# routes not requiring authentication
|
67
|
+
use OpenBEL::Routes::Root
|
68
|
+
use OpenBEL::Routes::Annotations
|
69
|
+
use OpenBEL::Routes::Expressions
|
70
|
+
use OpenBEL::Routes::Functions
|
71
|
+
use OpenBEL::Routes::Namespaces
|
72
|
+
use OpenBEL::Routes::Authenticate
|
73
|
+
|
74
|
+
# routes requiring authentication
|
75
|
+
if OpenBEL::Settings[:auth][:enabled]
|
76
|
+
use OpenBEL::JWTMiddleware::Authentication
|
77
|
+
end
|
78
|
+
use OpenBEL::Routes::Datasets
|
79
|
+
use OpenBEL::Routes::Evidence
|
80
|
+
end
|
81
|
+
end
|
82
|
+
# vim: ts=2 sts=2 sw=2
|
83
|
+
# encoding: utf-8
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'dot_hash'
|
2
|
+
|
3
|
+
module OpenBEL
|
4
|
+
module Config
|
5
|
+
include DotHash
|
6
|
+
|
7
|
+
CFG_VAR = 'OPENBEL_API_CONFIG_FILE'
|
8
|
+
|
9
|
+
def self.load!
|
10
|
+
config_file = ENV[CFG_VAR] || raise('No OpenBEL API configuration found. Set the OPENBEL_API_CONFIG_FILE environment variable.')
|
11
|
+
config = {}
|
12
|
+
File.open(config_file, 'r:UTF-8') do |cf|
|
13
|
+
config = YAML::load(cf)
|
14
|
+
if not config
|
15
|
+
config = {}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
cfg = Settings.new config, SilentProperties
|
19
|
+
|
20
|
+
failure = validate cfg
|
21
|
+
if failure
|
22
|
+
if block_given?
|
23
|
+
yield failure[1]
|
24
|
+
else
|
25
|
+
fail "Configuration error: #{failure[1]}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
cfg
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def self.validate(cfg)
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
class SilentProperties < Properties
|
39
|
+
def method_missing(key, *args, &block)
|
40
|
+
return nil unless has_key?(key)
|
41
|
+
execute(key, *args, &block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module OpenBEL
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
class Pager
|
5
|
+
|
6
|
+
NEGATIVE_FUNCTION = lambda { |v| v < 0 ? 0 : v }
|
7
|
+
FLOAT_FUNCTION = lambda { |v| Float(v) }
|
8
|
+
PREVIOUS_COND_FUNCTION = lambda { |pager, neg_proc, pos_proc|
|
9
|
+
[
|
10
|
+
pager.start_offset,
|
11
|
+
pager.page_size,
|
12
|
+
].any?(&(lambda { |v| v <= 0 })) ?
|
13
|
+
neg_proc.call(pager) :
|
14
|
+
pos_proc.call(pager)
|
15
|
+
}
|
16
|
+
NEXT_COND_FUNCTION = lambda { |pager, false_proc, true_proc|
|
17
|
+
test = pager.page_size > 0
|
18
|
+
test &= (pager.start_offset + pager.page_size) <= pager.total_size
|
19
|
+
|
20
|
+
test ?
|
21
|
+
true_proc.call(pager) :
|
22
|
+
false_proc.call(pager)
|
23
|
+
}
|
24
|
+
|
25
|
+
private_constant :NEGATIVE_FUNCTION
|
26
|
+
private_constant :FLOAT_FUNCTION
|
27
|
+
private_constant :PREVIOUS_COND_FUNCTION
|
28
|
+
private_constant :NEXT_COND_FUNCTION
|
29
|
+
|
30
|
+
def initialize(start_offset, page_size, total_size)
|
31
|
+
raise ArgumentError.new("start_offset must be >= 0") if start_offset < 0
|
32
|
+
raise ArgumentError.new("page_size must be >= 0") if page_size < 0
|
33
|
+
raise ArgumentError.new("total_size must be >= 0") if total_size < 0
|
34
|
+
|
35
|
+
@start_offset = NEGATIVE_FUNCTION.call(start_offset)
|
36
|
+
@page_size = FLOAT_FUNCTION.call(page_size)
|
37
|
+
@total_size = total_size
|
38
|
+
end
|
39
|
+
|
40
|
+
def start_offset
|
41
|
+
@start_offset
|
42
|
+
end
|
43
|
+
|
44
|
+
def current_page
|
45
|
+
return 0 if @total_size == 0
|
46
|
+
|
47
|
+
if @page_size > 0
|
48
|
+
((@start_offset + @page_size) / @page_size).floor
|
49
|
+
else
|
50
|
+
total_pages = total_pages()
|
51
|
+
|
52
|
+
case total_pages
|
53
|
+
when 1
|
54
|
+
1
|
55
|
+
when 2
|
56
|
+
midpoint = @total_size / total_pages
|
57
|
+
@start_offset < midpoint ? 1 : 2
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def page_size
|
63
|
+
@page_size.to_i
|
64
|
+
end
|
65
|
+
|
66
|
+
def total_pages
|
67
|
+
return 0 if @total_size == 0
|
68
|
+
|
69
|
+
if @page_size > 0
|
70
|
+
(@total_size / @page_size).ceil
|
71
|
+
else
|
72
|
+
@start_offset == 0 ? 1 : 2
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def total_size
|
77
|
+
@total_size
|
78
|
+
end
|
79
|
+
|
80
|
+
def previous_page
|
81
|
+
PREVIOUS_COND_FUNCTION.call(
|
82
|
+
self,
|
83
|
+
lambda { |_| nil },
|
84
|
+
lambda { |pager|
|
85
|
+
Pager.new(
|
86
|
+
NEGATIVE_FUNCTION.call(start_offset - page_size),
|
87
|
+
page_size,
|
88
|
+
total_size
|
89
|
+
)
|
90
|
+
}
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
def next_page
|
95
|
+
NEXT_COND_FUNCTION.call(
|
96
|
+
self,
|
97
|
+
lambda { |_| nil },
|
98
|
+
lambda { |pager|
|
99
|
+
Pager.new(
|
100
|
+
NEGATIVE_FUNCTION.call(start_offset + page_size),
|
101
|
+
page_size,
|
102
|
+
total_size
|
103
|
+
)
|
104
|
+
}
|
105
|
+
)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'sinatra/base'
|
3
|
+
require 'jwt'
|
4
|
+
|
5
|
+
module OpenBEL
|
6
|
+
module JWTMiddleware
|
7
|
+
|
8
|
+
def self.encode(payload, secret)
|
9
|
+
::JWT.encode(payload, secret, 'HS256')
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.decode(token, secret, verify, options)
|
13
|
+
::JWT.decode(token, secret, verify, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.check_cookie(env)
|
17
|
+
cookie_hdr = env['HTTP_COOKIE']
|
18
|
+
auth_hdr = env['HTTP_AUTHORIZATION']
|
19
|
+
if cookie_hdr.nil? and auth_hdr.nil?
|
20
|
+
raise 'missing authorization cookie/header'
|
21
|
+
end
|
22
|
+
|
23
|
+
if not cookie_hdr.nil?
|
24
|
+
cookies = cookie_hdr.split('; ')
|
25
|
+
selected = cookies.select {|x| x.start_with?('jwt=') }
|
26
|
+
if selected.size > 0
|
27
|
+
tokens = selected[0].split('=')
|
28
|
+
if tokens.size > 1
|
29
|
+
token = tokens[1]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
if token.nil?
|
33
|
+
raise 'missing authorization cookie'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if not auth_hdr.nil?
|
38
|
+
tokens = auth_hdr.split('Bearer ')
|
39
|
+
if tokens.size == 2
|
40
|
+
token = tokens[1]
|
41
|
+
end
|
42
|
+
if token.nil?
|
43
|
+
raise 'missing authorization header'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
secret = OpenBEL::Settings[:auth][:secret]
|
48
|
+
secret = Base64.decode64(secret)
|
49
|
+
# whether we should verify the token
|
50
|
+
verify = true
|
51
|
+
# JWT options passed to decode
|
52
|
+
options = {}
|
53
|
+
|
54
|
+
begin
|
55
|
+
decoded_token = decode(token, secret, verify, options)
|
56
|
+
rescue ::JWT::VerificationError => ve
|
57
|
+
raise 'invalid authorization token'
|
58
|
+
rescue ::JWT::DecodeError => je
|
59
|
+
puts je.inspect
|
60
|
+
raise 'malformed authorization token'
|
61
|
+
end
|
62
|
+
env['jwt.header'] = decoded_token.last unless decoded_token.nil?
|
63
|
+
env['jwt.payload'] = decoded_token.first unless decoded_token.nil?
|
64
|
+
|
65
|
+
exp = env['jwt.payload']['exp']
|
66
|
+
now = Time.now.to_i
|
67
|
+
if now > exp
|
68
|
+
raise 'token expired'
|
69
|
+
end
|
70
|
+
|
71
|
+
env['email'] = env['jwt.payload']['email']
|
72
|
+
end
|
73
|
+
|
74
|
+
class Authentication
|
75
|
+
def initialize(app, opts = {})
|
76
|
+
@app = app
|
77
|
+
@paths = opts.fetch(:paths, [])
|
78
|
+
end
|
79
|
+
|
80
|
+
def call(env)
|
81
|
+
check = false
|
82
|
+
if @paths.size == 0
|
83
|
+
# w/out paths, always check for token
|
84
|
+
check = true
|
85
|
+
else
|
86
|
+
path = env['PATH_INFO']
|
87
|
+
# w/ paths, only check for token iff matched
|
88
|
+
if @paths.any? {|x| path.start_with?(x)}
|
89
|
+
check = true
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
if check
|
94
|
+
begin
|
95
|
+
JWTMiddleware.check_cookie(env)
|
96
|
+
rescue Exception => e
|
97
|
+
return _401(e.message)
|
98
|
+
end
|
99
|
+
@app.call(env)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def _401(message)
|
106
|
+
hdrs = {'Content-Type' => 'application/json'}
|
107
|
+
msg = {error: message }
|
108
|
+
[401, hdrs, [msg.to_json]]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Oat
|
2
|
+
module Adapters
|
3
|
+
class BasicJson < Oat::Adapter
|
4
|
+
def link(rel, opts = {})
|
5
|
+
# no-op to maintain interface compatibility with hypermedia adapters
|
6
|
+
end
|
7
|
+
|
8
|
+
def link(rel, opts = {})
|
9
|
+
if opts.is_a?(Array)
|
10
|
+
data[:_links][rel] = opts.select { |link_obj| link_obj.include?(:href) }
|
11
|
+
else
|
12
|
+
data[:_links][rel] = opts if opts[:href]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def properties(&block)
|
17
|
+
data.merge! yield_props(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def property(key, value)
|
21
|
+
data[key] = value
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_method :meta, :property
|
25
|
+
|
26
|
+
def rel(rels)
|
27
|
+
# no-op to maintain interface compatibility with the Siren adapter
|
28
|
+
end
|
29
|
+
|
30
|
+
def entity(name, obj, serializer_class = nil, context_options = {}, &block)
|
31
|
+
entity_serializer = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
|
32
|
+
data[entity_name(name)] = entity_serializer ? entity_serializer.to_hash : nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def entities(name, collection, serializer_class = nil, context_options = {}, &block)
|
36
|
+
data[entity_name(name)] = collection.map do |obj|
|
37
|
+
entity_serializer = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
|
38
|
+
entity_serializer ? entity_serializer.to_hash : nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
alias_method :collection, :entities
|
42
|
+
|
43
|
+
def entity_name(name)
|
44
|
+
# entity name may be an array, but HAL only uses the first
|
45
|
+
name.respond_to?(:first) ? name.first : name
|
46
|
+
end
|
47
|
+
|
48
|
+
private :entity_name
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
module OpenBEL
|
4
|
+
module Resource
|
5
|
+
module Annotations
|
6
|
+
|
7
|
+
VOCABULARY_RDF = 'http://www.openbel.org/vocabulary/'
|
8
|
+
|
9
|
+
class AnnotationValueSearchResult < BEL::Resource::AnnotationValue
|
10
|
+
|
11
|
+
def match_text=(match_text)
|
12
|
+
@match_text = match_text
|
13
|
+
end
|
14
|
+
|
15
|
+
def match_text
|
16
|
+
@match_text
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class AnnotationSerializer < BaseSerializer
|
21
|
+
# adapter Oat::Adapters::HAL
|
22
|
+
schema do
|
23
|
+
type :annotation
|
24
|
+
property :rdf_uri, item.uri.to_s
|
25
|
+
property :name, item.prefLabel
|
26
|
+
property :prefix, item.prefix
|
27
|
+
property :domain, item.domain
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class AnnotationResourceSerializer < BaseSerializer
|
32
|
+
adapter Oat::Adapters::HAL
|
33
|
+
schema do
|
34
|
+
type :annotation
|
35
|
+
property :annotation, item
|
36
|
+
link :self, link_self(item[:prefix])
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def link_self(id)
|
42
|
+
{
|
43
|
+
:type => :annotation,
|
44
|
+
:href => "#{base_url}/api/annotations/#{id}"
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def link_collection
|
49
|
+
{
|
50
|
+
:type => :annotation_collection,
|
51
|
+
:href => "#{base_url}/api/annotations"
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class AnnotationCollectionSerializer < BaseSerializer
|
57
|
+
adapter Oat::Adapters::HAL
|
58
|
+
schema do
|
59
|
+
type :annotation_collection
|
60
|
+
property :annotation_collection, item
|
61
|
+
link :self, link_self
|
62
|
+
link :start, link_start
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def link_self
|
68
|
+
{
|
69
|
+
:type => :annotation_collection,
|
70
|
+
:href => "#{base_url}/api/annotations"
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def link_start
|
75
|
+
{
|
76
|
+
:type => :start,
|
77
|
+
:href => "#{base_url}/api/annotations/values"
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class AnnotationValueSerializer < BaseSerializer
|
83
|
+
#adapter Oat::Adapters::HAL
|
84
|
+
schema do
|
85
|
+
type :annotation_value
|
86
|
+
property :rdf_uri, item.uri.to_s
|
87
|
+
property :type, [item.type].flatten.map(&:to_s)
|
88
|
+
property :identifier, item.identifier
|
89
|
+
property :name, item.prefLabel
|
90
|
+
entity :annotation, item.annotation, AnnotationSerializer
|
91
|
+
|
92
|
+
# Support inclusion of the matched text when annotation values are filtered by
|
93
|
+
# a full-text search.
|
94
|
+
if item.match_text
|
95
|
+
property :match_text, item.match_text
|
96
|
+
end
|
97
|
+
|
98
|
+
setup(item)
|
99
|
+
link :self, link_self
|
100
|
+
link :collection, link_annotation
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def setup(item)
|
106
|
+
@annotation_id, @annotation_value_id = URI(item.uri).path.split('/')[3..-1]
|
107
|
+
end
|
108
|
+
|
109
|
+
def link_self
|
110
|
+
{
|
111
|
+
:type => :annotation_value,
|
112
|
+
:href => "#{base_url}/api/annotations/#{@annotation_id}/values/#{@annotation_value_id}"
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def link_annotation
|
117
|
+
{
|
118
|
+
:type => :annotation,
|
119
|
+
:href => "#{base_url}/api/annotations/#{@annotation_id}"
|
120
|
+
}
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class AnnotationValueResourceSerializer < BaseSerializer
|
125
|
+
adapter Oat::Adapters::HAL
|
126
|
+
schema do
|
127
|
+
type :annotation_value
|
128
|
+
property :annotation_value, item
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class AnnotationValueCollectionSerializer < BaseSerializer
|
133
|
+
adapter Oat::Adapters::HAL
|
134
|
+
schema do
|
135
|
+
type :annotation_value_collection
|
136
|
+
property :annotation_value_collection, item
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|