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