roadforest 0.0.3 → 0.1

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 (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