roadforest 0.0.3 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/examples/file-management.rb +7 -9
  3. data/lib/roadforest/application/dispatcher.rb +44 -31
  4. data/lib/roadforest/application/parameters.rb +5 -4
  5. data/lib/roadforest/application/path-provider.rb +14 -1
  6. data/lib/roadforest/application/route-adapter.rb +15 -4
  7. data/lib/roadforest/application/services-host.rb +41 -7
  8. data/lib/roadforest/application.rb +4 -8
  9. data/lib/roadforest/authorization.rb +231 -0
  10. data/lib/roadforest/blob-model.rb +2 -11
  11. data/lib/roadforest/content-handling/engine.rb +12 -6
  12. data/lib/roadforest/content-handling/handler-wrap.rb +45 -0
  13. data/lib/roadforest/content-handling/media-type.rb +20 -12
  14. data/lib/roadforest/content-handling/type-handler.rb +76 -0
  15. data/lib/roadforest/content-handling/type-handlers/jsonld.rb +2 -146
  16. data/lib/roadforest/content-handling/type-handlers/rdf-handler.rb +38 -0
  17. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/document-environment.rb +34 -0
  18. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/object-environment.rb +62 -0
  19. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/property-environment.rb +46 -0
  20. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/render-engine.rb +574 -0
  21. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/render-environment.rb +144 -0
  22. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/subject-environment.rb +80 -0
  23. data/lib/roadforest/content-handling/type-handlers/rdfa-writer.rb +163 -0
  24. data/lib/roadforest/content-handling/type-handlers/rdfa.rb +175 -0
  25. data/lib/roadforest/content-handling/type-handlers/rdfpost.rb +297 -0
  26. data/lib/roadforest/debug.rb +10 -0
  27. data/lib/roadforest/http/graph-response.rb +3 -7
  28. data/lib/roadforest/http/graph-transfer.rb +28 -106
  29. data/lib/roadforest/http/keychain.rb +79 -0
  30. data/lib/roadforest/http/message.rb +9 -1
  31. data/lib/roadforest/http/user-agent.rb +115 -0
  32. data/lib/roadforest/http.rb +8 -0
  33. data/lib/roadforest/model.rb +48 -3
  34. data/lib/roadforest/rdf/graph-focus.rb +5 -3
  35. data/lib/roadforest/rdf/graph-store.rb +4 -2
  36. data/lib/roadforest/rdf/normalization.rb +6 -1
  37. data/lib/roadforest/remote-host.rb +22 -7
  38. data/lib/roadforest/resource/rdf/read-only.rb +15 -1
  39. data/lib/roadforest/templates/base/doc.haml +13 -0
  40. data/lib/roadforest/templates/base/property_value.haml +12 -0
  41. data/lib/roadforest/templates/base/property_values.haml +6 -0
  42. data/lib/roadforest/templates/base/subject.haml +4 -0
  43. data/lib/roadforest/templates/distiller/doc.haml +20 -0
  44. data/lib/roadforest/templates/distiller/nil-object.haml +1 -0
  45. data/lib/roadforest/templates/distiller/property_value.haml +7 -0
  46. data/lib/roadforest/templates/distiller/property_values.haml +7 -0
  47. data/lib/roadforest/templates/distiller/subject.haml +5 -0
  48. data/lib/roadforest/templates/min/doc.haml +10 -0
  49. data/lib/roadforest/templates/min/property_values.haml +7 -0
  50. data/lib/roadforest/templates/min/subject.haml +2 -0
  51. data/lib/roadforest/templates/nil-object.haml +0 -0
  52. data/lib/roadforest/templates/node-object.haml +1 -0
  53. data/lib/roadforest/templates/object.haml +1 -0
  54. data/lib/roadforest/templates/uri-object.haml +1 -0
  55. data/lib/roadforest/templates/xml-literal-object.haml +1 -0
  56. data/lib/roadforest/utility/class-registry.rb +4 -0
  57. data/spec/client.rb +119 -77
  58. data/spec/{excon-adapater.rb → excon-adapter.rb} +4 -0
  59. data/spec/full-integration.rb +6 -2
  60. data/spec/graph-store.rb +1 -1
  61. data/spec/media-types.rb +29 -2
  62. metadata +102 -125
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f4089bbfd4e58f956b5088ab646d62d904f11120
4
+ data.tar.gz: ebbccc85db766f417254b23aee95d022392e1b58
5
+ SHA512:
6
+ metadata.gz: ecbf4fd992414ab2b73de911097455ef4712fbb9cb0c6f7bd7316a62abad9ca7b12ea5415b33817aaf9fc3bf83731500e684fe1099fa9ac217247ce94fe66883
7
+ data.tar.gz: 0a4125f562e7c390e5a515e4e06ba9099bd50268fa596734de825bce26c038d85c612594bc2b4db5ec521506430db1797e4ba3d3e772604f71de3c2a314d0c07
@@ -36,7 +36,7 @@ module FileManagementExample
36
36
  def nav_entry(graph, name, path)
37
37
  graph.add_node([:skos, :hasTopConcept], "#" + name) do |entry|
38
38
  entry[:rdf, :type] = [:skos, "Concept"]
39
- entry[:skos, :label] = name
39
+ entry[:skos, :prefLabel] = name
40
40
  entry[:foaf, "page"] = path
41
41
  end
42
42
  end
@@ -65,13 +65,11 @@ module FileManagementExample
65
65
  graph.add_list(:lc, "needs") do |list|
66
66
  services.file_records.each do |record|
67
67
  if !record.resolved
68
- # need = copy_from(:need, '*' => record.name)
69
- # list.add_node(need.url) do |node|
70
- # need.target = node
71
- # need[:lc, :name]
72
- # need[:lc, :digest]
73
- # end
74
- list << path_for(:need, '*' => record.name)
68
+ need = copy_model(graph, :need, '*' => [record.name])
69
+ need[:lc, :name]
70
+ need[:lc, :digest]
71
+
72
+ list.append(need.subject)
75
73
  end
76
74
  end
77
75
  end
@@ -79,7 +77,7 @@ module FileManagementExample
79
77
  end
80
78
 
81
79
  class NeedContent < RoadForest::BlobModel
82
- add_type "text/plain", TypeHandlers::Handler.new
80
+ add_type TypeHandlers::Handler.new, "text/plain"
83
81
  end
84
82
 
85
83
  class Need < RoadForest::RDFModel
@@ -3,39 +3,16 @@ require 'roadforest/application/route-adapter'
3
3
 
4
4
  module RoadForest
5
5
  class Dispatcher < Webmachine::Dispatcher
6
- def initialize(services)
6
+ def initialize(application)
7
7
  super(method(:create_resource))
8
- @services = services
8
+ @application = application
9
9
  @route_names = {}
10
10
  @trace_by_default = false
11
11
  end
12
- attr_accessor :services, :trace_by_default
12
+ attr_accessor :application, :trace_by_default
13
13
 
14
- def bundle(resource_class, &block)
15
- Application::RouteAdapter.new(resource_class, &block)
16
- end
17
-
18
- def bundle_typed_resource(resource_type, model_class, route_name)
19
- resource_class = Resource.get(resource_type)
20
- bundle(resource_class) do |resource, request, response|
21
- resource.model = model_class.new(route_name, resource.params, services)
22
- end
23
- end
24
-
25
- def bundle_traced_resource(resource_type, model_class, route_name)
26
- resource_class = Resource.get(resource_type)
27
- bundle(resource_class) do |resource, request, response|
28
- resource.model = model_class.new(route_name, resource.params, services)
29
- resource.trace = true
30
- end
31
- end
32
-
33
- def resource_route(resource, name, path_spec, bindings)
34
- route = Route.new(path_spec, resource, bindings || {})
35
- yield route if block_given?
36
- @route_names[name] = route
37
- @routes << route
38
- route
14
+ def route_for_name(name)
15
+ @route_names.fetch(name)
39
16
  end
40
17
 
41
18
  def add_route(name, path_spec, resource_type, model_class, bindings = nil, &block)
@@ -59,8 +36,27 @@ module RoadForest
59
36
  end
60
37
  alias add_traced add_traced_route
61
38
 
62
- def route_for_name(name)
63
- @route_names.fetch(name)
39
+ def resource_route(resource, name, path_spec, bindings)
40
+ route = Route.new(path_spec, resource, bindings || {})
41
+ yield route if block_given?
42
+ @route_names[name] = route
43
+ @routes << route
44
+ route
45
+ end
46
+
47
+ def bundle_typed_resource(resource_type, model_class, route_name)
48
+ resource_class = Resource.get(resource_type)
49
+ Application::RouteAdapter.new(route_name, resource_class, model_class) do |adapter|
50
+ adapter.application = application
51
+ end
52
+ end
53
+
54
+ def bundle_traced_resource(resource_type, model_class, route_name)
55
+ resource_class = Resource.get(resource_type)
56
+ Application::RouteAdapter.new(route_name, resource_class, model_class) do |adapter|
57
+ adapter.application = application
58
+ adapter.trace = true
59
+ end
64
60
  end
65
61
 
66
62
  class Route < Webmachine::Dispatcher::Route
@@ -68,7 +64,8 @@ module RoadForest
68
64
  # substitution.
69
65
  # @param [Hash] vars values for the path variables
70
66
  # @return [String] the valid URL for the route
71
- def build_path(vars = {})
67
+ def build_path(vars = nil)
68
+ vars ||= {}
72
69
  "/" + path_spec.map do |segment|
73
70
  case segment
74
71
  when '*',Symbol
@@ -78,6 +75,22 @@ module RoadForest
78
75
  end
79
76
  end.join("/")
80
77
  end
78
+
79
+ def build_params(vars = nil)
80
+ vars ||= {}
81
+ params = Application::Parameters.new
82
+ path_set = Hash[path_spec.find_all{|segment| segment.is_a? Symbol}.map{|seg| [seg, true]}]
83
+ vars.to_hash.each do |key, value|
84
+ if(path_set.has_key?(key))
85
+ params.path_info[key] = value
86
+ elsif(key == '*')
87
+ params.path_tokens = value
88
+ else
89
+ params.query_params[key] = value
90
+ end
91
+ end
92
+ params
93
+ end
81
94
  end
82
95
  end
83
96
  end
@@ -12,13 +12,14 @@ module RoadForest
12
12
  attr_accessor :path_info, :query_params, :path_tokens
13
13
 
14
14
  def [](field_name)
15
- return path_tokens if field_Name == '*'
16
- @path_info[field_name] || @query_params[field_name]
15
+ fetch(field_name)
16
+ rescue KeyError
17
+ nil
17
18
  end
18
19
 
19
20
  def fetch(field_name)
20
- return path_tokens if field_Name == '*'
21
- @path_info[field_name] || @query_params.fetch(field_name)
21
+ return path_tokens if field_name == '*'
22
+ @path_info.fetch(field_name){ @query_params.fetch(field_name) }
22
23
  end
23
24
 
24
25
  def slice(*fields)
@@ -10,9 +10,22 @@ module RoadForest
10
10
  # @param [Hash] vars the values for the required path variables
11
11
  # @raise [RuntimeError] Raised if the resource is not routable.
12
12
  # @return [String] the URL
13
- def path_for(name, vars = {})
13
+ def path_for(name, vars = nil)
14
+ vars ||= {}
14
15
  route = @dispatcher.route_for_name(name)
15
16
  ::RDF::URI.parse(route.build_path(vars))
16
17
  end
18
+
19
+ def request_for(name, vars = nil)
20
+ url = path_for(name, vars) #full url?
21
+
22
+ Webmachine::Request.new(method, url, headers, body)
23
+ end
24
+
25
+ def model_for(name, vars = nil)
26
+ route = @dispatcher.route_for_name(name)
27
+ params = route.build_params(vars)
28
+ route.resource.build_model(params)
29
+ end
17
30
  end
18
31
  end
@@ -1,17 +1,28 @@
1
1
  module RoadForest
2
2
  class Application
3
3
  class RouteAdapter
4
- def initialize(resource_class, &setup_block)
4
+ def initialize(route_name, resource_class, model_class)
5
5
  @resource_class = resource_class
6
- @setup_block = setup_block
6
+
7
+ @route_name = route_name
8
+ @model_class = model_class
9
+ @application = nil
10
+ @trace = false
11
+ yield self if block_given?
7
12
  end
13
+ attr_accessor :route_name, :resource_class, :model_class, :application, :trace
8
14
 
9
15
  def new(request, response)
10
- resource = @resource_class.new(request, response)
11
- @setup_block[resource, request, response]
16
+ resource = resource_class.new(request, response)
17
+ resource.model = build_model(resource.params)
18
+ resource.trace = trace
12
19
  resource
13
20
  end
14
21
 
22
+ def build_model(params)
23
+ model_class.new(route_name, params, application.services)
24
+ end
25
+
15
26
  def <(klass)
16
27
  if klass <= Webmachine::Resource
17
28
  return true
@@ -1,10 +1,44 @@
1
- class RoadForest::Application
2
- #XXX Worth doing some meta to get sanity checking of configs here? Better
3
- #fail early if there's no DB configured, right?
4
- class ServicesHost
5
- def initialize
6
- end
1
+ module RoadForest
2
+ class Application
3
+ #XXX Worth doing some meta to get reality checking of configs here? Better
4
+ #fail early if there's no DB configured, right?
5
+ class ServicesHost
6
+ def initialize
7
+ end
8
+
9
+ attr_writer :application
10
+ attr_writer :router, :canonical_host, :type_handling
11
+ attr_writer :logger, :authorization
12
+
13
+ def canonical_host
14
+ @application.canonical_host
15
+ end
16
+
17
+ def router
18
+ @router ||= PathProvider.new(@application.dispatcher)
19
+ end
7
20
 
8
- attr_accessor :router, :canonical_host, :type_handling, :logger
21
+ def authorization
22
+ @authorization ||=
23
+ begin
24
+ require 'roadforest/authorization'
25
+ Authorization::Manager.new
26
+ end
27
+ end
28
+
29
+ def type_handling
30
+ @type_handling ||= ContentHandling::Engine.default
31
+ end
32
+
33
+ def logger
34
+ @logger ||=
35
+ begin
36
+ require 'logger'
37
+ Logger.new("roadforest.log")
38
+ end
39
+ end
40
+
41
+ alias authz authorization
42
+ end
9
43
  end
10
44
  end
@@ -9,6 +9,7 @@ require 'roadforest/application/services-host'
9
9
  require 'roadforest/resource/rdf'
10
10
  require 'roadforest/content-handling/engine'
11
11
  require 'roadforest/rdf/normalization'
12
+ require 'roadforest/authorization'
12
13
 
13
14
  module RoadForest
14
15
  class Application
@@ -17,7 +18,7 @@ module RoadForest
17
18
  def initialize(canonical_host, services = nil, configuration = nil, dispatcher = nil)
18
19
  @canonical_host = normalize_resource(canonical_host)
19
20
  configuration ||= Webmachine::Configuration.default
20
- dispatcher ||= Dispatcher.new(services)
21
+ dispatcher ||= Dispatcher.new(self)
21
22
  super(configuration, dispatcher)
22
23
  self.services = services unless services.nil?
23
24
 
@@ -31,17 +32,12 @@ module RoadForest
31
32
 
32
33
  alias router dispatcher
33
34
 
35
+ #XXX Is this the right place for this?
34
36
  def services=(service_host)
35
- router.services = service_host
36
37
  @services = service_host
38
+ service_host.application = self
37
39
  @services.canonical_host = canonical_host
38
40
  @services.router = PathProvider.new(@dispatcher)
39
- @services.type_handling ||= ContentHandling::Engine.default
40
- @services.logger ||=
41
- begin
42
- require 'logger'
43
- Logger.new("roadforest.log")
44
- end
45
41
  end
46
42
  end
47
43
  end
@@ -0,0 +1,231 @@
1
+ require 'base64'
2
+ require 'openssl'
3
+ require 'roadforest'
4
+ require 'roadforest/utility/class-registry'
5
+
6
+ module RoadForest
7
+ module Authorization
8
+ class GrantBuilder
9
+ def initialize(salt, cache)
10
+ @salt = salt
11
+ @cache = cache
12
+ @list = []
13
+ end
14
+ attr_reader :list
15
+
16
+ def add(name, params=nil)
17
+ canonical =
18
+ if params.nil?
19
+ [@salt, name]
20
+ else
21
+ [@salt, name, params.keys.sort.map do |key|
22
+ [key, params[key]]
23
+ end]
24
+ end
25
+ @list << @cache[canonical]
26
+ end
27
+ end
28
+
29
+ class GrantsHolder
30
+ def initialize(salt, hash_function)
31
+ @salt = salt
32
+
33
+ digester = OpenSSL::Digest.new(hash_function)
34
+ @grants_cache = Hash.new do |h, k| #XXX potential resource exhaustion here - only accumulate auth'd results
35
+ digester.reset
36
+ h[k] = digester.digest(h.inspect)
37
+ end
38
+ end
39
+
40
+ def get(key)
41
+ @grants_cache[key]
42
+ end
43
+ alias [] get
44
+
45
+ def build_grants
46
+ builder = GrantBuilder.new(@salt, self)
47
+ yield builder
48
+ return builder.list
49
+ end
50
+ end
51
+
52
+ class Manager
53
+ attr_accessor :authenticator
54
+ attr_accessor :policy
55
+ attr_reader :grants
56
+
57
+ HASH_FUNCTION = "SHA256".freeze
58
+
59
+ def initialize(salt = nil, authenticator = nil, policy = nil)
60
+ @grants = GrantsHolder.new(salt || "roadforest-insecure", HASH_FUNCTION)
61
+
62
+ @authenticator = authenticator || AuthenticationChain.new(DefaultAuthenticationStore.new)
63
+ @policy = policy || AuthorizationPolicy.new
64
+ @policy.grants_holder = @grants
65
+ end
66
+
67
+ def build_grants(&block)
68
+ @grants.build_grants(&block)
69
+ end
70
+
71
+ def challenge(options)
72
+ @authenticator.challenge(options)
73
+ end
74
+
75
+ # @returns [:public|:granted|:refused]
76
+ #
77
+ # :public means the request doesn't need authorization
78
+ # :granted means that it does need authz but the credentials passed are
79
+ # allowed to access the resource
80
+ # :refused means that the credentials passed are not allowed to access
81
+ # the resource
82
+ #
83
+ # TODO: Resource needs to add s-maxage=0 for :granted requests or public
84
+ # for :public requests to the CacheControl header
85
+ def authorization(header, required_grants)
86
+ entity = authenticator.authenticate(header)
87
+
88
+ return :refused if entity.nil?
89
+
90
+ available_grants = policy.grants_for(entity)
91
+
92
+ if required_grants.any?{|required| available_grants.include?(required)}
93
+ return :granted
94
+ else
95
+ return :refused
96
+ end
97
+ end
98
+ end
99
+
100
+ class AuthenticationChain
101
+ class Scheme
102
+ def self.registry_purpose; "authentication scheme"; end
103
+ extend Utility::ClassRegistry::Registrar
104
+
105
+ def self.register(name)
106
+ registrar.registry.add(name, self.new)
107
+ end
108
+
109
+ def authenticated_entity(credentials, store)
110
+ nil
111
+ end
112
+ end
113
+
114
+ class Basic < Scheme
115
+ register "Basic"
116
+
117
+ def challenge(options)
118
+ "Basic realm=\"#{options.fetch(:realm, "Roadforest App")}\""
119
+ end
120
+
121
+ def authenticated_entity(credentials, store)
122
+ username, password = Base64.decode64(credentials).split(':',2)
123
+
124
+ entity = store.by_username(username)
125
+ entity.authenticate_by_password(password)
126
+ entity
127
+ end
128
+ end
129
+
130
+ def initialize(store)
131
+ @store = store
132
+ end
133
+ attr_reader :store
134
+
135
+ def handler_for(scheme)
136
+ Scheme.get(scheme)
137
+ rescue
138
+ nil
139
+ end
140
+
141
+ def challenge(options)
142
+ (Scheme.registry.names.map do |scheme_name|
143
+ handler_for(scheme_name).challenge(options)
144
+ end).join(", ")
145
+ end
146
+
147
+ def add_account(user,password,token)
148
+ @store.add_account(user,password,token)
149
+ end
150
+
151
+ def authenticate(header)
152
+ return nil if header.nil?
153
+ scheme, credentials = header.split(/\s+/, 2)
154
+
155
+ handler = handler_for(scheme)
156
+ return nil if handler.nil?
157
+
158
+ entity = handler.authenticated_entity(credentials, store)
159
+ return nil if entity.nil?
160
+ return nil unless entity.authenticated?
161
+ return entity
162
+ end
163
+ end
164
+
165
+ class AuthEntity
166
+ def initialize
167
+ @authenticated = false
168
+ end
169
+ attr_accessor :username, :password, :token
170
+
171
+ def authenticated?
172
+ !!@authenticated
173
+ end
174
+
175
+ def authenticate_by_password(password)
176
+ @authenticated = (!password.nil? and password == @password)
177
+ end
178
+
179
+ def authenticate_by_token(token)
180
+ @authenticated = (!token.nil? and token == @token)
181
+ end
182
+
183
+ def authenticate!
184
+ @authenticated = true
185
+ end
186
+ end
187
+
188
+ class DefaultAuthenticationStore
189
+ def initialize
190
+ @accounts = []
191
+ end
192
+
193
+ def build_entity(account)
194
+ return nil if account.nil?
195
+ AuthEntity.new.tap do |entity|
196
+ entity.username = account[0]
197
+ entity.password = account[1]
198
+ entity.token = account[2]
199
+ end
200
+ end
201
+
202
+ def add_account(user, password, token)
203
+ @accounts << [user, password, token]
204
+ end
205
+
206
+ def by_username(username)
207
+ account = @accounts.find{|account| account[0] == username }
208
+ build_entity(account)
209
+ end
210
+
211
+ def by_token(token)
212
+ account = @accounts.find{|account| account[2] == token }
213
+ build_entity(account)
214
+ end
215
+ end
216
+
217
+ class AuthorizationPolicy
218
+ attr_accessor :grants_holder
219
+
220
+ def build_grants(&block)
221
+ grants_holder.build_grants(&block)
222
+ end
223
+
224
+ def grants_for(entity)
225
+ build_grants do |builder|
226
+ builder.add(:admin)
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
@@ -9,19 +9,10 @@ module RoadForest
9
9
  @engine ||= ContentHandling::Engine.new
10
10
  end
11
11
 
12
- def add_type(type, handler)
13
- add_parser(type, handler)
14
- add_renderer(type, handler)
12
+ def add_type(handler, type)
13
+ type_handling.add_type(handler, type)
15
14
  end
16
15
  alias add add_type
17
-
18
- def add_parser(type, handler)
19
- type_handling.add_parser(type, handler)
20
- end
21
-
22
- def add_renderer(type, handler)
23
- type_handling.add_renderer(type, handler)
24
- end
25
16
  end
26
17
 
27
18
  def type_handling
@@ -1,4 +1,5 @@
1
1
  require 'roadforest/content-handling/media-type'
2
+ require 'roadforest/content-handling/handler-wrap'
2
3
 
3
4
  module RoadForest
4
5
  module ContentHandling
@@ -47,8 +48,13 @@ module RoadForest
47
48
 
48
49
  def self.default
49
50
  require 'roadforest/content-handling/type-handlers/jsonld'
51
+ require 'roadforest/content-handling/type-handlers/rdfa'
50
52
  self.new.tap do |engine|
51
- engine.add "application/ld+json", RoadForest::MediaType::Handlers::JSONLD.new
53
+ engine.add RoadForest::MediaType::Handlers::RDFa.new, "text/html;q=1;rdfa=1"
54
+ engine.add RoadForest::MediaType::Handlers::RDFa.new, "application/xhtml+xml;q=1;rdfa=1"
55
+ engine.add RoadForest::MediaType::Handlers::JSONLD.new, "application/ld+json"
56
+ engine.add RoadForest::MediaType::Handlers::RDFa.new, "text/html;q=0.5"
57
+ engine.add RoadForest::MediaType::Handlers::RDFa.new, "application/xhtml+xml;q=0.5"
52
58
  end
53
59
  end
54
60
 
@@ -59,21 +65,21 @@ module RoadForest
59
65
  end
60
66
  attr_reader :renderers, :parsers
61
67
 
62
- def add_type(type, handler)
68
+ def add_type(handler, type)
63
69
  type = MediaType.parse(type)
64
- add_parser(type, handler)
65
- add_renderer(type, handler)
70
+ add_parser(handler, type)
71
+ add_renderer(handler, type)
66
72
  end
67
73
  alias add add_type
68
74
 
69
- def add_parser(type, object)
75
+ def add_parser(object, type)
70
76
  type = MediaType.parse(type)
71
77
  wrapper = RoadForest::MediaType::Handlers::Wrap::Parse.new(type, object)
72
78
  parsers.add(wrapper)
73
79
  end
74
80
  alias accept add_parser
75
81
 
76
- def add_renderer(type, object)
82
+ def add_renderer(object, type)
77
83
  type = MediaType.parse(type)
78
84
  wrapper = RoadForest::MediaType::Handlers::Wrap::Render.new(type, object)
79
85
  renderers.add(wrapper)
@@ -0,0 +1,45 @@
1
+ module RoadForest
2
+ module MediaType
3
+ module Handlers
4
+ module Wrap
5
+ class Wrapper
6
+ def initialize(type, handler)
7
+ @type = type
8
+ @handler = handler
9
+ end
10
+ attr_reader :type, :handler
11
+
12
+ def local_to_network(base_uri, network)
13
+ @handler.local_to_network(base_uri, network)
14
+ end
15
+ alias from_graph local_to_network
16
+
17
+ def network_to_local(base_uri, source)
18
+ @handler.network_to_local(base_uri, source)
19
+ end
20
+ alias to_graph network_to_local
21
+ end
22
+
23
+ class Render < Wrapper
24
+ def call(resource)
25
+ @handler.render_for(resource)
26
+ end
27
+
28
+ def content_type_header
29
+ @type.content_type_header
30
+ end
31
+ end
32
+
33
+ class Parse < Wrapper
34
+ def call(resource)
35
+ @handler.parse_for(resource)
36
+ end
37
+
38
+ def add_child(resource)
39
+ @handler.add_child_to(resource)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end