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,140 @@
|
|
1
|
+
module RoadForest
|
2
|
+
class TraceFormatter
|
3
|
+
DECISION_NAMES = {
|
4
|
+
:b13 => "Service available?",
|
5
|
+
:b12 => "Known method?",
|
6
|
+
:b11 => "URI too long?",
|
7
|
+
:b10 => "Method allowed?",
|
8
|
+
:b9 => "Content-MD5 present?",
|
9
|
+
:b9a => "Content-MD5 valid?",
|
10
|
+
:b9b => "Malformed?",
|
11
|
+
:b8 => "Authorized?",
|
12
|
+
:b7 => "Forbidden?",
|
13
|
+
:b6 => "Okay Content-* Headers?",
|
14
|
+
:b5 => "Known Content-Type?",
|
15
|
+
:b4 => "Req Entity Too Large?",
|
16
|
+
:b3 => "OPTIONS?",
|
17
|
+
:c3 => "Accept exists?",
|
18
|
+
:c4 => "Acceptable media type available?",
|
19
|
+
:d4 => "Accept-Language exists?",
|
20
|
+
:d5 => "Acceptable language available?",
|
21
|
+
:e5 => "Accept-Charset exists?",
|
22
|
+
:e6 => "Acceptable Charset available?",
|
23
|
+
:f6 => "Accept-Encoding exists? (also, set content-type header here, now that charset is chosen)",
|
24
|
+
:f7 => "Acceptable encoding available?",
|
25
|
+
:g7 => "Resource exists?",
|
26
|
+
:g8 => "If-Match exists?",
|
27
|
+
:g9 => "If-Match: * exists?",
|
28
|
+
:g11 => "ETag in If-Match",
|
29
|
+
:h7 => "If-Match exists?",
|
30
|
+
:h10 => "If-Unmodified-Since exists?",
|
31
|
+
:h12 => "Last-Modified > I-UM-S?",
|
32
|
+
:i4 => "Moved permanently? (apply PUT to different URI)",
|
33
|
+
:i7 => "PUT?",
|
34
|
+
:i12 => "If-none-match exists?",
|
35
|
+
:i13 => "If-none-match: * exists?",
|
36
|
+
:j18 => "GET or HEAD?",
|
37
|
+
:k5 => "Moved permanently?",
|
38
|
+
:k7 => "Previously existed?",
|
39
|
+
:k13 => "Etag in if-none-match?",
|
40
|
+
:l5 => "Moved temporarily?",
|
41
|
+
:l7 => "POST?",
|
42
|
+
:l13 => "If-Modified-Since exists?",
|
43
|
+
:l15 => "IMS > Now?",
|
44
|
+
:l17 => "Last-Modified > IMS?",
|
45
|
+
:m5 => "POST?",
|
46
|
+
:m7 => "Server allows POST to missing resource?",
|
47
|
+
:m16 => "DELETE?",
|
48
|
+
:m20 => "DELETE enacted immediately? (Also where DELETE is forced.)",
|
49
|
+
:m20b => "Did the DELETE complete?",
|
50
|
+
:n5 => "Server allows POST to missing resource?",
|
51
|
+
:n11 => "Redirect?",
|
52
|
+
:n16 => "POST?",
|
53
|
+
:o14 => "Conflict?",
|
54
|
+
:o16 => "PUT?",
|
55
|
+
:o18 => "Multiple representations? Also where body generation for GET and HEAD is done.",
|
56
|
+
:o18b => "Multiple choices?",
|
57
|
+
:o20 => "Response includes an entity?",
|
58
|
+
:p3 => "Conflict?",
|
59
|
+
:p11 => "New resource?",
|
60
|
+
}
|
61
|
+
|
62
|
+
def initialize(trace)
|
63
|
+
@trace = trace
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_s
|
67
|
+
Grouper.new(@trace).to_a.join("\n")
|
68
|
+
end
|
69
|
+
|
70
|
+
class Grouper
|
71
|
+
include Enumerable
|
72
|
+
|
73
|
+
def initialize(trace)
|
74
|
+
@trace = trace
|
75
|
+
end
|
76
|
+
|
77
|
+
def format_attempt(attempt)
|
78
|
+
unless attempt.length == 2 and
|
79
|
+
attempt[0][:type] == :attempt and
|
80
|
+
attempt[1][:type] == :result
|
81
|
+
raise "Can't format attempt: #{attempt.inspect}"
|
82
|
+
end
|
83
|
+
name= attempt[0][:name]
|
84
|
+
source= attempt[0][:source]
|
85
|
+
result= attempt[1][:value]
|
86
|
+
|
87
|
+
if source.nil?
|
88
|
+
" #{name} => #{result.inspect}"
|
89
|
+
else
|
90
|
+
"\n #{name}\n #{source}\n => #{result.inspect}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def format_request(request)
|
95
|
+
"\nRequest:\n #{request[:method]} #{request[:path]}\n#{request[:headers].map do |name, value|
|
96
|
+
" #{name}: #{value}"
|
97
|
+
end.join("\n")}#{request[:body].empty? ? "" : "\n\n #{request[:body]}"}\n.\n"
|
98
|
+
end
|
99
|
+
|
100
|
+
def format_response(response)
|
101
|
+
"\nResponse:\n #{response[:code]}\n#{response[:headers].map do |name, value|
|
102
|
+
" #{name}: #{value}"
|
103
|
+
end.join("\n")}#{response[:body].empty? ? "" : "\n\n #{response[:body]}"}\n.\n"
|
104
|
+
end
|
105
|
+
|
106
|
+
def format_decision(item)
|
107
|
+
"\nDecision: #{DECISION_NAMES[item[:decision]]} (#{item[:decision]})"
|
108
|
+
end
|
109
|
+
|
110
|
+
def each
|
111
|
+
enum = @trace.each
|
112
|
+
|
113
|
+
group = []
|
114
|
+
loop do
|
115
|
+
begin
|
116
|
+
item = enum.next
|
117
|
+
case item[:type]
|
118
|
+
when :request
|
119
|
+
yield format_request(item)
|
120
|
+
when :response
|
121
|
+
yield format_response(item)
|
122
|
+
when :attempt
|
123
|
+
group << item
|
124
|
+
when :result
|
125
|
+
group << item
|
126
|
+
yield format_attempt(group)
|
127
|
+
group = []
|
128
|
+
when :decision
|
129
|
+
yield format_decision(item)
|
130
|
+
else
|
131
|
+
raise "Don't know trace entry type: #{item.inspect}"
|
132
|
+
end
|
133
|
+
rescue StopIteration
|
134
|
+
break
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RoadForest
|
2
|
+
module Utility
|
3
|
+
class ClassRegistry
|
4
|
+
module Registrar
|
5
|
+
def registry
|
6
|
+
@registry ||= ClassRegistry.new(self)
|
7
|
+
end
|
8
|
+
|
9
|
+
def register(name)
|
10
|
+
registrar.registry.add(name, self)
|
11
|
+
end
|
12
|
+
|
13
|
+
def [](name)
|
14
|
+
registrar.registry.get(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.extended(mod)
|
18
|
+
(
|
19
|
+
class << mod; self; end
|
20
|
+
).instance_exec(mod) do |mod|
|
21
|
+
define_method :registrar do
|
22
|
+
mod
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(registrar)
|
29
|
+
if registrar.respond_to?(:registry_purpose)
|
30
|
+
@purpose = registrar.registry_purpose
|
31
|
+
else
|
32
|
+
@purpose = registrar.name
|
33
|
+
end
|
34
|
+
@classes = {}
|
35
|
+
end
|
36
|
+
|
37
|
+
def add(name, klass)
|
38
|
+
@classes[name.to_sym] = klass
|
39
|
+
@classes[name.to_s] = klass
|
40
|
+
end
|
41
|
+
|
42
|
+
def get(name)
|
43
|
+
@classes.fetch(name)
|
44
|
+
rescue KeyError
|
45
|
+
raise "No #@purpose class registered as name: #{name.inspect}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/roadforest.rb
ADDED
data/spec/client.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'roadforest/server'
|
2
|
+
require 'roadforest/test-support'
|
3
|
+
|
4
|
+
require 'examples/file-management'
|
5
|
+
|
6
|
+
describe RoadForest::RemoteHost do
|
7
|
+
let :destination_dir do
|
8
|
+
"spec_support/destination"
|
9
|
+
end
|
10
|
+
|
11
|
+
let :source_path do
|
12
|
+
"spec_support/test-file.txt"
|
13
|
+
end
|
14
|
+
|
15
|
+
let :services do
|
16
|
+
FileManagementExample::ServicesHost.new.tap do |host|
|
17
|
+
host.file_records = [
|
18
|
+
FileManagementExample::FileRecord.new("one", false),
|
19
|
+
FileManagementExample::FileRecord.new("two", false),
|
20
|
+
FileManagementExample::FileRecord.new("three", false)
|
21
|
+
]
|
22
|
+
host.destination_dir = destination_dir
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
let :server do
|
27
|
+
RoadForest::TestSupport::RemoteHost.new(FileManagementExample::Application.new("http://roadforest.test-domain.com/", services))
|
28
|
+
end
|
29
|
+
|
30
|
+
def dump_trace
|
31
|
+
tracing = true
|
32
|
+
tracing = false
|
33
|
+
if tracing
|
34
|
+
RoadForest::TestSupport::FSM.dump_trace
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
before :each do
|
39
|
+
RoadForest::TestSupport::FSM.trace_on
|
40
|
+
end
|
41
|
+
|
42
|
+
before :each do
|
43
|
+
require 'fileutils'
|
44
|
+
FileUtils.rm_f(destination_dir)
|
45
|
+
FileUtils.mkdir_p(destination_dir)
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "raw put of file data" do
|
49
|
+
before :each do
|
50
|
+
@destination = nil
|
51
|
+
server.getting do |graph|
|
52
|
+
items = graph.all(:skos, "hasTopConcept")
|
53
|
+
|
54
|
+
unresolved = items.find do |nav_item|
|
55
|
+
nav_item[:skos, "label"] == "Unresolved"
|
56
|
+
end
|
57
|
+
|
58
|
+
target = unresolved.first(:foaf, "page")
|
59
|
+
|
60
|
+
@destination = target.first(:lc, "needs").as_list.first[:lc, "contents"]
|
61
|
+
end
|
62
|
+
|
63
|
+
unless @destination.nil?
|
64
|
+
File::open(source_path) do |file|
|
65
|
+
server.put_file(@destination, "text/plain", file)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should be able to format traces correctly" do
|
71
|
+
RoadForest::TestSupport::FSM.trace_dump.should =~ /Decision/
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should set destination" do
|
75
|
+
@destination.to_context.to_s.should == "http://roadforest.test-domain.com/files/one"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should deliver file to destination path" do
|
79
|
+
File::read(File::join(destination_dir, "one")).should ==
|
80
|
+
File::read(source_path)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "posting data to server" do
|
85
|
+
before :each do
|
86
|
+
begin
|
87
|
+
server.posting do |graph|
|
88
|
+
items = graph.all(:skos, "hasTopConcept")
|
89
|
+
|
90
|
+
unresolved = items.find do |nav_item|
|
91
|
+
nav_item[:skos, "label"] == "Unresolved"
|
92
|
+
end
|
93
|
+
|
94
|
+
target = unresolved.first(:foaf, "page")
|
95
|
+
|
96
|
+
target.post_to do |new_need|
|
97
|
+
new_need[[:lc, "name"]] = "lawyers/guns/money"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
ensure
|
101
|
+
dump_trace
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should change the server state" do
|
106
|
+
services.file_records.find do |record|
|
107
|
+
record.name == "lawyers/guns/money"
|
108
|
+
end.should be_an_instance_of FileManagementExample::FileRecord
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "putting data to server" do
|
113
|
+
before :each do
|
114
|
+
server.putting do |graph|
|
115
|
+
items = graph.all(:skos, "hasTopConcept")
|
116
|
+
|
117
|
+
unresolved = items.find do |nav_item|
|
118
|
+
nav_item[:skos, "label"] == "Unresolved"
|
119
|
+
end
|
120
|
+
|
121
|
+
target = unresolved.first(:foaf, "page")
|
122
|
+
|
123
|
+
needs = target.first(:lc, "needs").as_list
|
124
|
+
|
125
|
+
needs.each do |need|
|
126
|
+
need[[:lc, "resolved"]] = true
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should change the server state" do
|
132
|
+
services.file_records.each do |record|
|
133
|
+
record.resolved.should == true
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should extract data from server responses" do
|
138
|
+
server.should match_query do
|
139
|
+
pattern(:subject, [:lc, "path"], nil)
|
140
|
+
pattern(:subject, [:lc, "file"], nil)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should return correct content-type" do
|
145
|
+
#test_server.http_exchanges.each{|ex| puts ex.response.body}
|
146
|
+
server.http_exchanges.should_not be_empty
|
147
|
+
server.http_exchanges.each do |exchange|
|
148
|
+
exchange.response.headers["Content-Type"].should == "application/ld+json"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'roadforest/rdf/source-rigor/credence-annealer'
|
2
|
+
require 'roadforest/rdf/graph-store'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
describe RoadForest::RDF::SourceRigor::CredenceAnnealer do
|
6
|
+
let :graph do
|
7
|
+
RoadForest::RDF::GraphStore.new
|
8
|
+
end
|
9
|
+
|
10
|
+
subject :annealer do
|
11
|
+
RoadForest::RDF::SourceRigor::CredenceAnnealer.new(graph)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should run it's block at least once" do
|
15
|
+
tested = false
|
16
|
+
annealer.resolve do
|
17
|
+
tested = true
|
18
|
+
end
|
19
|
+
tested.should be_true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should re-run it's block until the GraphStore settles" do
|
23
|
+
graph.stub(:quiet_impulse?).and_return(false, false, true)
|
24
|
+
|
25
|
+
times_run = 0
|
26
|
+
annealer.resolve do
|
27
|
+
times_run += 1
|
28
|
+
end
|
29
|
+
|
30
|
+
times_run.should == 3
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should produce an error in some infinite-loop style situation" do
|
34
|
+
graph.stub(:quiet_impulse?).and_return(false)
|
35
|
+
|
36
|
+
expect do
|
37
|
+
Timeout::timeout(1) do
|
38
|
+
annealer.resolve do
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end.to raise_error(/Annealing failed/)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'roadforest/test-support/matchers'
|
2
|
+
require 'roadforest/rdf/graph-copier'
|
3
|
+
|
4
|
+
#Leaving notes since being interrupted
|
5
|
+
#
|
6
|
+
#GC needs to tessellate the graph in the same way that Parceller should -
|
7
|
+
#probably should make sure that works first. Basically same resource should ==
|
8
|
+
#same subgraph copied, since otherwise client omission of a property isn't
|
9
|
+
#distinguishable from the intent to delete it. Only copy once so that you don't
|
10
|
+
#overwrite client changes.
|
11
|
+
#
|
12
|
+
#Also: "single put" involves a whole extra level of server code to accept the
|
13
|
+
#put, parcel it out, confirm IMS headers across everyone... so that's a v2
|
14
|
+
#feature
|
15
|
+
|
16
|
+
describe RoadForest::RDF::GraphCopier, :pending => "review of API" do
|
17
|
+
class TestVoc < ::RDF::Vocabulary("http://test.com/");end
|
18
|
+
|
19
|
+
let :start_subject do
|
20
|
+
RDF::Node.new
|
21
|
+
end
|
22
|
+
|
23
|
+
let :other_subject do
|
24
|
+
RDF::Node.new
|
25
|
+
end
|
26
|
+
|
27
|
+
let :starting_statements do
|
28
|
+
[
|
29
|
+
[start_subject, TestVoc[:a], 7],
|
30
|
+
[start_subject, TestVoc[:other], other_subject]
|
31
|
+
]
|
32
|
+
end
|
33
|
+
|
34
|
+
let :other_statements do
|
35
|
+
[
|
36
|
+
[other_subject, TestVoc[:a], 13]
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
let :source_graph do
|
41
|
+
::RDF::Graph.new.tap do |graph|
|
42
|
+
starting_statements.each do |stmt|
|
43
|
+
graph << stmt
|
44
|
+
end
|
45
|
+
|
46
|
+
other_statements.each do |stmt|
|
47
|
+
graph << stmt
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
let :document do
|
53
|
+
RoadForest::RDF::Document.new.tap do |doc|
|
54
|
+
doc.source =
|
55
|
+
doc.body_string = source_graph.dump(:rdfa)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
let :copier do
|
60
|
+
RoadForest::RDF::GraphCopier.new.tap do |copier|
|
61
|
+
copier.source_graph = source_graph
|
62
|
+
copier.subject = start_subject
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "reads the notes above, unless it wants the hose again" do
|
67
|
+
fail "shoulda read the notes"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should have a target graph" do
|
71
|
+
copier.target_graph.should be_an_instance_of(::RDF::Graph)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should have statements about starting subject" do
|
75
|
+
statements_from_graph(copier.target_graph).that_match_query(:subject => start_subject).should be_equivalent_to(starting_statements)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should not have statements about other subject" do
|
79
|
+
copier.target_graph.query(:subject => other_subject).to_a.should be_empty
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should get statements about other subject" do
|
83
|
+
copier[[:testvoc, :other]]
|
84
|
+
|
85
|
+
statements_from_graph(copier.target_graph).that_match_query(:subject => other_subject).should be_equivalent_to(other_statements)
|
86
|
+
end
|
87
|
+
end
|
data/spec/graph-store.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
#require 'rdf/rdfa'
|
3
|
+
require 'roadforest/rdf/document'
|
4
|
+
require 'roadforest/rdf/graph-store'
|
5
|
+
|
6
|
+
describe RoadForest::RDF do
|
7
|
+
let :source_rigor do
|
8
|
+
RoadForest::RDF::SourceRigor.new.tap do |skept|
|
9
|
+
skept.policy_list(:may_subject)
|
10
|
+
skept.investigator_list(:null)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
let :graph_store do
|
15
|
+
RoadForest::RDF::GraphStore.new
|
16
|
+
end
|
17
|
+
|
18
|
+
#merging graphs
|
19
|
+
|
20
|
+
describe RoadForest::RDF::GraphStore do
|
21
|
+
let :root_body do
|
22
|
+
store = RoadForest::RDF::GraphStore.new
|
23
|
+
step = RoadForest::RDF::GraphFocus.new("http://lrdesign.com/test-rdf", store, source_rigor)
|
24
|
+
step[[:foaf, :givenname]] = "Lester"
|
25
|
+
step[[:dc, :date]] = Time.now
|
26
|
+
step = step.node_at([:dc, :related], "http://lrdesign.com/test-rdf/sub")
|
27
|
+
step[[:dc, :date]] = Time.now
|
28
|
+
|
29
|
+
store.graph_dump(:rdfa)
|
30
|
+
end
|
31
|
+
|
32
|
+
let :second_body do
|
33
|
+
store = RoadForest::RDF::GraphStore.new
|
34
|
+
step = RoadForest::RDF::GraphFocus.new("http://lrdesign.com/test-rdf", store, source_rigor)
|
35
|
+
step[[:foaf, :givenname]] = "Foster"
|
36
|
+
step[[:dc, :date]] = Time.now
|
37
|
+
|
38
|
+
store.graph_dump(:rdfa)
|
39
|
+
end
|
40
|
+
|
41
|
+
let :first_doc do
|
42
|
+
RoadForest::RDF::Document.new.tap do |doc|
|
43
|
+
doc.source = "http://lrdesign.com/test-rdf"
|
44
|
+
doc.body_string = root_body
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
let :second_doc do
|
49
|
+
RoadForest::RDF::Document.new.tap do |doc|
|
50
|
+
doc.source = "http://lrdesign.com/test-rdf"
|
51
|
+
doc.body_string = second_body
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
before :each do
|
56
|
+
graph_store.insert_document(first_doc)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should transmit properties" do
|
60
|
+
step = RoadForest::RDF::GraphFocus.new("http://lrdesign.com/test-rdf", graph_store, source_rigor)
|
61
|
+
step[:dc, :date].should be_an_instance_of(Time)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should replace previous statements from same URL" do
|
65
|
+
expect{
|
66
|
+
graph_store.insert_document(second_doc)
|
67
|
+
}.to change{
|
68
|
+
RoadForest::RDF::GraphFocus.new("http://lrdesign.com/test-rdf", graph_store, source_rigor)[:foaf, :givenname]
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe RoadForest::RDF::GraphFocus do
|
74
|
+
let :main_subject do
|
75
|
+
RDF::URI.new("http://test.com/main")
|
76
|
+
end
|
77
|
+
|
78
|
+
let :creator do
|
79
|
+
RDF::Node.new
|
80
|
+
end
|
81
|
+
|
82
|
+
let :root do
|
83
|
+
RDF::Node.new
|
84
|
+
end
|
85
|
+
|
86
|
+
before :each do
|
87
|
+
graph_store.add_statement(root, [:dc, :relation], main_subject)
|
88
|
+
graph_store.add_statement(creator, [:foaf, :familyName], "Lester")
|
89
|
+
graph_store.add_statement(creator, [:foaf, :givenname], "Judson")
|
90
|
+
graph_store.add_statement(main_subject, [:dc, :creator], creator)
|
91
|
+
graph_store.add_statement(main_subject, [:dc, :date], Time.now)
|
92
|
+
end
|
93
|
+
|
94
|
+
let :step do
|
95
|
+
RoadForest::RDF::GraphFocus.new(main_subject, graph_store, source_rigor)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should enumerate forward properties" do
|
99
|
+
step.forward_properties.should include([:dc, :creator])
|
100
|
+
step.forward_properties.should include([:dc, :date])
|
101
|
+
step.forward_properties.should_not include([:foaf, :familyName])
|
102
|
+
step.forward_properties.should_not include([:dc, :relation])
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should get values for properties" do
|
106
|
+
step.get(:dc, :creator).rdf.should == creator
|
107
|
+
step.get(:dc, :date).should be_an_instance_of(Time)
|
108
|
+
step[:dc, :date].should be_an_instance_of(Time)
|
109
|
+
step[[:dc, :date]].should be_an_instance_of(Time)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should enumerate reverse properties" do
|
113
|
+
step.reverse_properties.should include([:dc, :relation])
|
114
|
+
step.reverse_properties.should_not include([:dc, :creator])
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should get values for inbound properties" do
|
118
|
+
step.rev(:dc, :relation).rdf.should == root
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should walk forward to properties" do
|
122
|
+
step[:dc,:creator][:foaf,:givenname].should == "Judson"
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should be able to add properties with []=", :pending => "Should GraphStores accept local writes?" do
|
126
|
+
step[[:dc, :dateCopyrighted]] = Time.now #slightly ugly syntax
|
127
|
+
step[:dc, :dateCopyrighted].should be_an_instance_of(Time)
|
128
|
+
RDF::Query.new do |query|
|
129
|
+
query.pattern [:subject, RDF::DC.dateCopyrighted, :value]
|
130
|
+
end.execute(graph_store).should_not be_empty
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should be able to add properties with set", :pending => "Should GraphStores accept local writes?" do
|
134
|
+
step.set(:dc, :dateCopyrighted, Time.now)
|
135
|
+
step[:dc, :dateCopyrighted].should be_an_instance_of(Time)
|
136
|
+
RDF::Query.new do |query|
|
137
|
+
query.pattern [:subject, RDF::DC.dateCopyrighted, :value]
|
138
|
+
store.execute(graph_store).should_not be_empty
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
data/spec/media-types.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'roadforest/content-handling/media-type'
|
2
|
+
describe RoadForest::ContentHandling::MediaType do
|
3
|
+
let :accepted_list do
|
4
|
+
RoadForest::ContentHandling::MediaTypeList.build("text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5")
|
5
|
+
end
|
6
|
+
|
7
|
+
let :provided_list do
|
8
|
+
RoadForest::ContentHandling::MediaTypeList.build("text/html;q=0.9;rdfa=true, application/json+ld;q=0.4")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should find best match" do
|
12
|
+
accepted_list.best_match_from(provided_list).should =~ "text/html"
|
13
|
+
end
|
14
|
+
end
|