roadforest 0.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.
- 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
|