roadforest 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/file-management.rb +98 -0
- data/lib/roadforest/application/dispatcher.rb +54 -0
- data/lib/roadforest/application/parameters.rb +39 -0
- data/lib/roadforest/application/path-provider.rb +18 -0
- data/lib/roadforest/application/route-adapter.rb +24 -0
- data/lib/roadforest/application/services-host.rb +10 -0
- data/lib/roadforest/application.rb +42 -0
- data/lib/roadforest/blob-model.rb +56 -0
- data/lib/roadforest/content-handling/engine.rb +113 -0
- data/lib/roadforest/content-handling/media-type.rb +222 -0
- data/lib/roadforest/content-handling/type-handlers/jsonld.rb +172 -0
- data/lib/roadforest/http/adapters/excon.rb +47 -0
- data/lib/roadforest/http/graph-response.rb +20 -0
- data/lib/roadforest/http/graph-transfer.rb +112 -0
- data/lib/roadforest/http/message.rb +91 -0
- data/lib/roadforest/model.rb +151 -0
- data/lib/roadforest/models.rb +2 -0
- data/lib/roadforest/rdf/context-fascade.rb +25 -0
- data/lib/roadforest/rdf/document.rb +23 -0
- data/lib/roadforest/rdf/focus-list.rb +19 -0
- data/lib/roadforest/rdf/focus-wrapping.rb +30 -0
- data/lib/roadforest/rdf/graph-copier.rb +16 -0
- data/lib/roadforest/rdf/graph-focus.rb +95 -0
- data/lib/roadforest/rdf/graph-reading.rb +145 -0
- data/lib/roadforest/rdf/graph-store.rb +217 -0
- data/lib/roadforest/rdf/investigation.rb +90 -0
- data/lib/roadforest/rdf/normalization.rb +150 -0
- data/lib/roadforest/rdf/parcel.rb +47 -0
- data/lib/roadforest/rdf/post-focus.rb +35 -0
- data/lib/roadforest/rdf/resource-pattern.rb +60 -0
- data/lib/roadforest/rdf/resource-query.rb +58 -0
- data/lib/roadforest/rdf/source-rigor/credence/any.rb +9 -0
- data/lib/roadforest/rdf/source-rigor/credence/none-if-role-absent.rb +19 -0
- data/lib/roadforest/rdf/source-rigor/credence/role-if-available.rb +19 -0
- data/lib/roadforest/rdf/source-rigor/credence-annealer.rb +22 -0
- data/lib/roadforest/rdf/source-rigor/credence.rb +29 -0
- data/lib/roadforest/rdf/source-rigor/http-investigator.rb +20 -0
- data/lib/roadforest/rdf/source-rigor/investigator.rb +17 -0
- data/lib/roadforest/rdf/source-rigor/null-investigator.rb +10 -0
- data/lib/roadforest/rdf/source-rigor.rb +44 -0
- data/lib/roadforest/rdf/update-focus.rb +73 -0
- data/lib/roadforest/rdf/vocabulary.rb +11 -0
- data/lib/roadforest/rdf.rb +6 -0
- data/lib/roadforest/remote-host.rb +96 -0
- data/lib/roadforest/resource/handlers.rb +43 -0
- data/lib/roadforest/resource/http/form-parsing.rb +81 -0
- data/lib/roadforest/resource/rdf/leaf-item.rb +21 -0
- data/lib/roadforest/resource/rdf/list.rb +19 -0
- data/lib/roadforest/resource/rdf/parent-item.rb +26 -0
- data/lib/roadforest/resource/rdf/read-only.rb +100 -0
- data/lib/roadforest/resource/rdf.rb +4 -0
- data/lib/roadforest/resource/role/has-children.rb +22 -0
- data/lib/roadforest/resource/role/writable.rb +43 -0
- data/lib/roadforest/server.rb +3 -0
- data/lib/roadforest/test-support/dispatcher-facade.rb +77 -0
- data/lib/roadforest/test-support/http-client.rb +151 -0
- data/lib/roadforest/test-support/matchers.rb +67 -0
- data/lib/roadforest/test-support/remote-host.rb +23 -0
- data/lib/roadforest/test-support/trace-formatter.rb +140 -0
- data/lib/roadforest/test-support.rb +2 -0
- data/lib/roadforest/utility/class-registry.rb +49 -0
- data/lib/roadforest.rb +2 -0
- data/spec/client.rb +152 -0
- data/spec/credence-annealer.rb +44 -0
- data/spec/graph-copier.rb +87 -0
- data/spec/graph-store.rb +142 -0
- data/spec/media-types.rb +14 -0
- data/spec/rdf-parcel.rb +158 -0
- data/spec/update-focus.rb +117 -0
- data/spec_support/gem_test_suite.rb +0 -0
- metadata +241 -0
@@ -0,0 +1,172 @@
|
|
1
|
+
#@require 'rdf/rdfa' #XXX Otherwise json-ld grabs RDFa documents. Awaiting fix
|
2
|
+
#upstream
|
3
|
+
require 'json/ld'
|
4
|
+
|
5
|
+
module RoadForest
|
6
|
+
module MediaType
|
7
|
+
module Handlers
|
8
|
+
module Wrap
|
9
|
+
class Wrapper
|
10
|
+
def initialize(type, handler)
|
11
|
+
@type = type
|
12
|
+
@handler = handler
|
13
|
+
end
|
14
|
+
attr_reader :type, :handler
|
15
|
+
|
16
|
+
def local_to_network(network)
|
17
|
+
@handler.local_to_network(network)
|
18
|
+
end
|
19
|
+
alias from_graph local_to_network
|
20
|
+
|
21
|
+
def network_to_local(source)
|
22
|
+
@handler.network_to_local(source)
|
23
|
+
end
|
24
|
+
alias to_graph network_to_local
|
25
|
+
end
|
26
|
+
|
27
|
+
class Render < Wrapper
|
28
|
+
def call(resource)
|
29
|
+
@handler.render_for(resource)
|
30
|
+
end
|
31
|
+
|
32
|
+
def content_type_header
|
33
|
+
@type.content_type_header
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Parse < Wrapper
|
38
|
+
def call(resource)
|
39
|
+
@handler.parse_for(resource)
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_child(resource)
|
43
|
+
@handler.add_child_to(resource)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Handler
|
49
|
+
def network_to_local(network)
|
50
|
+
return network
|
51
|
+
end
|
52
|
+
|
53
|
+
def local_to_network(local)
|
54
|
+
return local
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_for(resource)
|
58
|
+
source = resource.request_body
|
59
|
+
input_data = network_to_local(source)
|
60
|
+
model = resource.model
|
61
|
+
|
62
|
+
update_model(model, input_data)
|
63
|
+
|
64
|
+
renderer = model.type_handling.choose_renderer(resource.request_accept_header)
|
65
|
+
body = renderer.local_to_network(model.response_data)
|
66
|
+
|
67
|
+
build_response(resource)
|
68
|
+
end
|
69
|
+
|
70
|
+
def render_for(resource)
|
71
|
+
model = resource.model
|
72
|
+
output_data = get_output(model)
|
73
|
+
local_to_network(output_data)
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_child_to(resource)
|
77
|
+
model = resource.model
|
78
|
+
source = resource.request_body
|
79
|
+
input_data = network_to_local(source)
|
80
|
+
|
81
|
+
child_for_model(resource.model, input_data)
|
82
|
+
|
83
|
+
build_response(resource)
|
84
|
+
end
|
85
|
+
|
86
|
+
def build_response(resource)
|
87
|
+
model = resource.model
|
88
|
+
|
89
|
+
renderer = model.type_handling.choose_renderer(resource.request_accept_header)
|
90
|
+
body = renderer.local_to_network(model.response_data)
|
91
|
+
|
92
|
+
resource.response_content_type = renderer.content_type_header
|
93
|
+
resource.response_body = body
|
94
|
+
if model.response_location
|
95
|
+
resource.redirect_to(model.response_location)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def child_for_model(model, data)
|
100
|
+
model.add_child(data)
|
101
|
+
model.processed
|
102
|
+
end
|
103
|
+
|
104
|
+
def update_model(model, input_data)
|
105
|
+
result = model.update(input_data)
|
106
|
+
model.response_data = result
|
107
|
+
model.processed
|
108
|
+
result
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_output(model)
|
112
|
+
result = model.retrieve
|
113
|
+
model.response_data = result
|
114
|
+
model.processed
|
115
|
+
result
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
require 'roadforest/rdf/normalization'
|
120
|
+
class RDFHandler < Handler
|
121
|
+
include RDF::Normalization
|
122
|
+
|
123
|
+
def get_output(model)
|
124
|
+
graph = super
|
125
|
+
root_uri = model.canonical_uri
|
126
|
+
|
127
|
+
graph.each_statement do |statement|
|
128
|
+
original = statement.dup
|
129
|
+
if ::RDF::URI === statement.subject and statement.subject.relative?
|
130
|
+
statement.subject = normalize_resource(root_uri.join(statement.subject))
|
131
|
+
end
|
132
|
+
|
133
|
+
if ::RDF::URI === statement.object and statement.object.relative?
|
134
|
+
statement.object = normalize_resource(root_uri.join(statement.object))
|
135
|
+
end
|
136
|
+
|
137
|
+
if statement != original
|
138
|
+
graph.delete(original)
|
139
|
+
graph.insert(statement)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
graph
|
143
|
+
end
|
144
|
+
|
145
|
+
def child_for_model(model, data)
|
146
|
+
model.add_graph_child(data)
|
147
|
+
model.processed
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
#application/ld+json
|
152
|
+
class JSONLD < RDFHandler
|
153
|
+
def local_to_network(rdf)
|
154
|
+
JSON::LD::Writer.buffer do |writer|
|
155
|
+
rdf.each_statement do |statement|
|
156
|
+
writer << statement
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def network_to_local(source)
|
162
|
+
graph = ::RDF::Graph.new
|
163
|
+
reader = JSON::LD::Reader.new(source.to_s)
|
164
|
+
reader.each_statement do |statement|
|
165
|
+
graph.insert(statement)
|
166
|
+
end
|
167
|
+
graph
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'addressable/uri'
|
2
|
+
require 'excon'
|
3
|
+
require 'roadforest/http/message'
|
4
|
+
module RoadForest
|
5
|
+
module HTTP
|
6
|
+
class ExconAdapter
|
7
|
+
def initialize(url)
|
8
|
+
@root_url = Addressable::URI.parse(url)
|
9
|
+
@connections = Hash.new{|h,k| h[k] = build_site_connection(k)}
|
10
|
+
@connection_defaults = {}
|
11
|
+
end
|
12
|
+
attr_reader :connection_defaults
|
13
|
+
|
14
|
+
def build_site_connection(site)
|
15
|
+
Excon.new(site.to_s, @connection_defaults)
|
16
|
+
end
|
17
|
+
|
18
|
+
def site_connection(uri)
|
19
|
+
uri = Addressable::URI.parse(uri)
|
20
|
+
@connections[uri.normalized_site]
|
21
|
+
end
|
22
|
+
|
23
|
+
def do_request(request)
|
24
|
+
uri = @root_url.join(request.url)
|
25
|
+
|
26
|
+
connection = site_connection(uri)
|
27
|
+
excon_response = connection.request(
|
28
|
+
:method => request.method,
|
29
|
+
:path => uri.path,
|
30
|
+
:headers => request.headers,
|
31
|
+
:body => request.body
|
32
|
+
)
|
33
|
+
|
34
|
+
response = HTTP::Response.new
|
35
|
+
if excon_response.body.is_a? String
|
36
|
+
response.body_string = excon_response.body
|
37
|
+
else
|
38
|
+
response.body = excon_response.body
|
39
|
+
end
|
40
|
+
response.headers = excon_response.headers
|
41
|
+
response.status = excon_response.status
|
42
|
+
|
43
|
+
return response
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RoadForest
|
2
|
+
module HTTP
|
3
|
+
class GraphResponse
|
4
|
+
attr_accessor :graph
|
5
|
+
attr_reader :request, :response
|
6
|
+
|
7
|
+
def initialize(request, response, graph)
|
8
|
+
@request, @response, @graph = request, response, graph
|
9
|
+
end
|
10
|
+
|
11
|
+
def url
|
12
|
+
request.url
|
13
|
+
end
|
14
|
+
|
15
|
+
def status
|
16
|
+
response.status
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'roadforest/http/message'
|
2
|
+
require 'roadforest/http/graph-response'
|
3
|
+
require 'roadforest/content-handling/engine'
|
4
|
+
|
5
|
+
module RoadForest
|
6
|
+
module HTTP
|
7
|
+
class GraphTransfer
|
8
|
+
attr_accessor :http_client
|
9
|
+
attr_writer :type_handling
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@type_preferences = Hash.new{|h,k| k.nil? ? "*/*" : h[nil]}
|
13
|
+
end
|
14
|
+
|
15
|
+
def type_handling
|
16
|
+
@type_handling ||= ContentHandling::Engine.default
|
17
|
+
end
|
18
|
+
|
19
|
+
def put(url, graph)
|
20
|
+
make_request("PUT", url, graph)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get(url)
|
24
|
+
make_request("GET", url)
|
25
|
+
end
|
26
|
+
|
27
|
+
def post(url, graph)
|
28
|
+
make_request("POST", url, graph)
|
29
|
+
end
|
30
|
+
|
31
|
+
def make_request(method, url, graph=nil)
|
32
|
+
method = method.to_s.upcase
|
33
|
+
|
34
|
+
validate(method, url, graph)
|
35
|
+
|
36
|
+
request = setup_request(method, url)
|
37
|
+
|
38
|
+
response = send_request(request, graph)
|
39
|
+
|
40
|
+
return build_response(request, response)
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate(method, url, graph)
|
44
|
+
case method
|
45
|
+
when "GET", "HEAD", "DELETE"
|
46
|
+
raise "Method #{method} requires an empty body" unless graph.nil?
|
47
|
+
when "POST", "PATCH", "PUT"
|
48
|
+
raise "Method #{method} requires a body" if graph.nil?
|
49
|
+
#when "OPTION", "TRACE" #Need to put verbs where they go
|
50
|
+
else
|
51
|
+
raise "Unrecognized method: #{method}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def best_type_for(url)
|
56
|
+
return @type_preferences[url]
|
57
|
+
end
|
58
|
+
|
59
|
+
def setup_request(method, url)
|
60
|
+
request = Request.new(method, url)
|
61
|
+
request.headers["Accept"] = type_handling.parsers.types.accept_header
|
62
|
+
request
|
63
|
+
end
|
64
|
+
|
65
|
+
def select_renderer(url)
|
66
|
+
end
|
67
|
+
|
68
|
+
def record_accept_header(url, types)
|
69
|
+
return if types.nil? or types.empty?
|
70
|
+
@type_preferences[nil] = types
|
71
|
+
@type_preferences[url] = types
|
72
|
+
end
|
73
|
+
|
74
|
+
def render_graph(graph, request)
|
75
|
+
return unless request.needs_body?
|
76
|
+
|
77
|
+
content_type = best_type_for(request.url)
|
78
|
+
renderer = type_handling.choose_renderer(content_type)
|
79
|
+
request.headers["Content-Type"] = renderer.content_type_header
|
80
|
+
request.body_string = renderer.from_graph(graph)
|
81
|
+
end
|
82
|
+
|
83
|
+
class Retryable < StandardError; end
|
84
|
+
|
85
|
+
def send_request(request, graph)
|
86
|
+
retry_limit ||= 5
|
87
|
+
render_graph(graph, request)
|
88
|
+
|
89
|
+
response = http_client.do_request(request)
|
90
|
+
case response.status
|
91
|
+
when 415 #Type not accepted
|
92
|
+
record_accept_header(request.url, response.headers["Accept"])
|
93
|
+
raise Retryable
|
94
|
+
end
|
95
|
+
return response
|
96
|
+
rescue Retryable
|
97
|
+
raise unless (retry_limit -= 1) > 0
|
98
|
+
retry
|
99
|
+
end
|
100
|
+
|
101
|
+
def parse_response(response)
|
102
|
+
parser = type_handling.choose_parser(response.headers["Content-Type"])
|
103
|
+
parser.to_graph(response.body_string)
|
104
|
+
end
|
105
|
+
|
106
|
+
def build_response(request, response)
|
107
|
+
graph = parse_response(response)
|
108
|
+
return GraphResponse.new(request, response, graph)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module RoadForest
|
5
|
+
module HTTP
|
6
|
+
class Message
|
7
|
+
attr_accessor :headers
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@body_string = ""
|
11
|
+
@headers = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def body_string=(value)
|
15
|
+
@body_string = value
|
16
|
+
@body = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def body=(value)
|
20
|
+
@body = value
|
21
|
+
@body_string = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def body
|
25
|
+
return @body ||= StringIO.new(body_string||"")
|
26
|
+
end
|
27
|
+
|
28
|
+
def body_string
|
29
|
+
@body_string ||=
|
30
|
+
begin
|
31
|
+
case @body
|
32
|
+
when nil
|
33
|
+
nil
|
34
|
+
when StringIO
|
35
|
+
@body.string
|
36
|
+
when IO
|
37
|
+
@body.rewind
|
38
|
+
@body.read
|
39
|
+
else
|
40
|
+
raise "Unknown class for body: #{@body.class.name}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def inspect
|
46
|
+
"#<#{self.class.name}:#{'0x%0xd'%object_id}\n #{inspection_payload.join("\n ")}\n>"
|
47
|
+
end
|
48
|
+
|
49
|
+
def inspection_payload
|
50
|
+
old_pos = body.pos
|
51
|
+
body.rewind
|
52
|
+
[headers.inspect, body.read]
|
53
|
+
ensure
|
54
|
+
body.pos = old_pos
|
55
|
+
end
|
56
|
+
|
57
|
+
def empty?
|
58
|
+
if @body.nil?
|
59
|
+
@body_string.nil? || @body_string.empty?
|
60
|
+
else
|
61
|
+
@body.respond_to?(:size) && @body.size <= 0
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Request < Message
|
67
|
+
attr_accessor :method, :url
|
68
|
+
|
69
|
+
def initialize(method, url)
|
70
|
+
super()
|
71
|
+
@method, @url = method, url
|
72
|
+
end
|
73
|
+
|
74
|
+
def needs_body?
|
75
|
+
%w{POST PATCH PUT}.include?(@method)
|
76
|
+
end
|
77
|
+
|
78
|
+
def inspection_payload
|
79
|
+
["#{method} #{url}"] + super
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Response < Message
|
84
|
+
attr_accessor :status
|
85
|
+
|
86
|
+
def inspection_payload
|
87
|
+
[status] + super
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'roadforest/rdf/graph-store'
|
2
|
+
module RoadForest
|
3
|
+
class ProcessingSequenceError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class Model
|
7
|
+
def initialize(route_name, params, services)
|
8
|
+
@route_name = route_name
|
9
|
+
@params = params
|
10
|
+
@services = services
|
11
|
+
@data = nil
|
12
|
+
@response_values = {}
|
13
|
+
end
|
14
|
+
attr_reader :route_name, :params, :services, :data
|
15
|
+
|
16
|
+
def path_for(route_name = nil, params = nil)
|
17
|
+
services.router.path_for(route_name, (params || self.params).to_hash)
|
18
|
+
end
|
19
|
+
|
20
|
+
def canonical_host
|
21
|
+
services.canonical_host
|
22
|
+
end
|
23
|
+
|
24
|
+
def canonical_uri
|
25
|
+
Addressable::URI.parse(canonical_host.to_s).join(my_path)
|
26
|
+
end
|
27
|
+
|
28
|
+
def type_handling
|
29
|
+
services.type_handling
|
30
|
+
end
|
31
|
+
|
32
|
+
def my_path
|
33
|
+
path_for(route_name, params)
|
34
|
+
end
|
35
|
+
|
36
|
+
def my_url
|
37
|
+
canonical_uri.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
def reset
|
41
|
+
end
|
42
|
+
|
43
|
+
def exists?
|
44
|
+
!data.nil?
|
45
|
+
end
|
46
|
+
|
47
|
+
def etag
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def last_modified
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def response_location
|
56
|
+
@response_values.fetch(:location) do
|
57
|
+
raise ProcessingSequenceError, "Location not available until request processed"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def response_location=(location)
|
62
|
+
@response_values[:location] = location
|
63
|
+
end
|
64
|
+
|
65
|
+
def response_data
|
66
|
+
@response_values.fetch(:data) do
|
67
|
+
raise ProcessingSequenceError, "Location not available until request processed"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def response_data=(data)
|
72
|
+
@response_values[:data] = data
|
73
|
+
end
|
74
|
+
|
75
|
+
def processed
|
76
|
+
[:location, :data].each do |key|
|
77
|
+
unless @response_values.has_key?(key)
|
78
|
+
@response_values[key] = nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def expires
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def update(data)
|
88
|
+
raise NotImplementedError
|
89
|
+
end
|
90
|
+
|
91
|
+
def add_child(results)
|
92
|
+
raise NotImplementedError
|
93
|
+
end
|
94
|
+
|
95
|
+
def retrieve
|
96
|
+
raise NotImplementedError
|
97
|
+
end
|
98
|
+
alias retreive retrieve
|
99
|
+
|
100
|
+
def delete
|
101
|
+
false
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
class RDFModel < Model
|
107
|
+
def update(graph)
|
108
|
+
graph_update(start_focus(graph))
|
109
|
+
end
|
110
|
+
|
111
|
+
def graph_update(focus)
|
112
|
+
fill_graph(focus)
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_graph_child(graph)
|
116
|
+
add_child(start_focus(graph))
|
117
|
+
new_graph
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_child(focus)
|
121
|
+
new_graph
|
122
|
+
end
|
123
|
+
|
124
|
+
def retrieve
|
125
|
+
new_graph
|
126
|
+
end
|
127
|
+
|
128
|
+
def fill_graph(graph)
|
129
|
+
end
|
130
|
+
|
131
|
+
def start_focus(graph, resource_url=nil)
|
132
|
+
focus = RDF::GraphFocus.new
|
133
|
+
focus.graph = graph
|
134
|
+
focus.subject = resource_url || my_url
|
135
|
+
|
136
|
+
yield focus if block_given?
|
137
|
+
return focus
|
138
|
+
end
|
139
|
+
|
140
|
+
def start_graph(resource_url=nil, &block)
|
141
|
+
graph = ::RDF::Graph.new
|
142
|
+
start_focus(graph, resource_url, &block)
|
143
|
+
end
|
144
|
+
|
145
|
+
def new_graph
|
146
|
+
focus = start_graph(my_url)
|
147
|
+
fill_graph(focus)
|
148
|
+
self.response_data = focus.graph
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
|
3
|
+
module RoadForest::RDF
|
4
|
+
class ContextFascade
|
5
|
+
include ::RDF::Countable
|
6
|
+
include ::RDF::Enumerable
|
7
|
+
include ::RDF::Queryable
|
8
|
+
|
9
|
+
def initialize(store, resource, rigor)
|
10
|
+
@store, @resource, @rigor = store, resource, rigor
|
11
|
+
end
|
12
|
+
|
13
|
+
def query_execute(query, &block)
|
14
|
+
ResourceQuery.from(query, @resource, @rigor).execute(@store, &block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def query_pattern(pattern, &block)
|
18
|
+
ResourcePattern.from(pattern, {:context_roles => {:subject => @resource}, :source_rigor => @rigor}).execute(@store, &block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def each(&block)
|
22
|
+
@store.each(&block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'roadforest'
|
3
|
+
|
4
|
+
module RoadForest::RDF
|
5
|
+
#Wrapper for text to be parsed into RDF
|
6
|
+
class Document
|
7
|
+
attr_accessor :content_type, :code, :source, :root_url, :body, :body_string
|
8
|
+
def initialize
|
9
|
+
@content_type = "text/html"
|
10
|
+
@code = 200
|
11
|
+
@body_string = ""
|
12
|
+
end
|
13
|
+
|
14
|
+
def body_string=(value)
|
15
|
+
@body_string = value
|
16
|
+
@body = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def body
|
20
|
+
return @body ||= StringIO.new(body_string)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'roadforest/rdf/focus-wrapping'
|
2
|
+
require 'roadforest/rdf/normalization'
|
3
|
+
module RoadForest::RDF
|
4
|
+
class FocusList < ::RDF::List
|
5
|
+
include Normalization
|
6
|
+
|
7
|
+
attr_accessor :root_url, :base_node, :source_rigor
|
8
|
+
|
9
|
+
def first
|
10
|
+
base_node.unwrap_value(super)
|
11
|
+
end
|
12
|
+
|
13
|
+
def each
|
14
|
+
super do |value|
|
15
|
+
yield base_node.unwrap_value(value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rdf/model/node'
|
2
|
+
|
3
|
+
module RoadForest::RDF
|
4
|
+
module FocusWrapping
|
5
|
+
def new_focus
|
6
|
+
dup
|
7
|
+
end
|
8
|
+
|
9
|
+
def wrap_node(value)
|
10
|
+
next_step = new_focus
|
11
|
+
if ::RDF::Node === value
|
12
|
+
next_step.root_url = self.root_url
|
13
|
+
else
|
14
|
+
next_step.root_url = normalize_context(value)
|
15
|
+
end
|
16
|
+
next_step.subject = value
|
17
|
+
next_step.graph = graph
|
18
|
+
next_step.source_rigor = source_rigor
|
19
|
+
next_step
|
20
|
+
end
|
21
|
+
|
22
|
+
def unwrap_value(value)
|
23
|
+
if value.respond_to? :object
|
24
|
+
value.object
|
25
|
+
else
|
26
|
+
wrap_node(value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
require 'roadforest/rdf/graph-focus'
|
3
|
+
|
4
|
+
module RoadForest
|
5
|
+
module RDF
|
6
|
+
class GraphCopier < GraphFocus
|
7
|
+
attr_accessor :source_graph, :subject
|
8
|
+
|
9
|
+
alias target_graph graph
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@graph = ::RDF::Graph.new
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|