ldpath 0.3.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,19 +1,48 @@
1
1
  module Ldpath
2
2
  class Selector
3
3
  def evaluate(program, uris, context)
4
- Array(uris).map do |uri|
4
+ return to_enum(:evaluate, program, uris, context) unless block_given?
5
+ enum_wrap(uris).map do |uri|
5
6
  loading program, uri, context
6
- evaluate_one uri, context
7
- end.flatten.compact
7
+ enum_flatten_one(evaluate_one(uri, context)).each do |x|
8
+ yield x unless x.nil?
9
+ end
10
+ end
8
11
  end
9
12
 
10
13
  def loading(program, uri, context)
11
14
  program.loading uri, context
12
15
  end
16
+
17
+ protected
18
+
19
+ def enum_wrap(object)
20
+ if object.nil?
21
+ []
22
+ elsif object.respond_to?(:to_ary)
23
+ object.to_ary || [object]
24
+ elsif object.is_a? Hash
25
+ [object]
26
+ elsif object.is_a? Enumerable
27
+ object
28
+ else
29
+ [object]
30
+ end
31
+ end
32
+
33
+ def enum_flatten_one(object)
34
+ return to_enum(:enum_flatten_one, object) unless block_given?
35
+
36
+ enum_wrap(object).each do |e|
37
+ enum_wrap(e).each do |v|
38
+ yield v
39
+ end
40
+ end
41
+ end
13
42
  end
14
43
 
15
44
  class SelfSelector < Selector
16
- def evaluate_one(uri, context)
45
+ def evaluate_one(uri, _context)
17
46
  uri
18
47
  end
19
48
  end
@@ -27,7 +56,9 @@ module Ldpath
27
56
  end
28
57
 
29
58
  def evaluate(program, uris, context)
30
- Array(uris).map do |uri|
59
+ return to_enum(:evaluate, program, uris, context) unless block_given?
60
+
61
+ enum_wrap(uris).map do |uri|
31
62
  loading program, uri, context
32
63
  args = arguments.map do |i|
33
64
  case i
@@ -37,8 +68,10 @@ module Ldpath
37
68
  i
38
69
  end
39
70
  end
40
- program.func_call fname, uri, context, *args
41
- end.flatten.compact
71
+ enum_flatten_one(program.func_call(fname, uri, context, *args)).each do |x|
72
+ yield x unless x.nil?
73
+ end
74
+ end
42
75
  end
43
76
  end
44
77
 
@@ -49,7 +82,7 @@ module Ldpath
49
82
  end
50
83
 
51
84
  def evaluate_one(uri, context)
52
- context.query([uri, property, nil]).map(&:object)
85
+ context.query([uri, property, nil]).lazy.map(&:object)
53
86
  end
54
87
  end
55
88
 
@@ -62,15 +95,28 @@ module Ldpath
62
95
  def evaluate_one(uri, context)
63
96
  return PropertySelector.new(property).evaluate_one(uri_context) unless defined? RDF::Reasoner
64
97
 
65
- context.query([uri, nil, nil]).select do |result|
98
+ context.query([uri, nil, nil]).lazy.select do |result|
66
99
  result.predicate.entail(:subPropertyOf).include? property
67
100
  end.map(&:object)
68
101
  end
69
102
  end
70
103
 
104
+ class NegatedPropertySelector < Selector
105
+ attr_reader :properties
106
+ def initialize(*properties)
107
+ @properties = properties
108
+ end
109
+
110
+ def evaluate_one(uri, context)
111
+ context.query([uri, nil, nil]).lazy.reject do |result|
112
+ properties.include? result.predicate
113
+ end.map(&:object)
114
+ end
115
+ end
116
+
71
117
  class WildcardSelector < Selector
72
118
  def evaluate_one(uri, context)
73
- context.query([uri, nil, nil]).map(&:object)
119
+ context.query([uri, nil, nil]).lazy.map(&:object)
74
120
  end
75
121
  end
76
122
 
@@ -81,7 +127,7 @@ module Ldpath
81
127
  end
82
128
 
83
129
  def evaluate_one(uri, context)
84
- context.query([nil, property, uri]).map(&:subject)
130
+ context.query([nil, property, uri]).lazy.map(&:subject)
85
131
  end
86
132
  end
87
133
 
@@ -93,19 +139,20 @@ module Ldpath
93
139
  end
94
140
 
95
141
  def evaluate(program, uris, context)
96
- result = []
97
- input = Array(uris)
142
+ return to_enum(:evaluate, program, uris, context) unless block_given?
98
143
 
99
- Range.new(0, repeat.min, true).each do
100
- input = property.evaluate program, input, context
101
- end
144
+ input = enum_wrap(uris)
102
145
 
103
- repeat.each_with_index do |i, idx|
104
- break if input.empty? || idx > 25 # we're probably lost..
146
+ (0..repeat.max).each_with_index do |i, idx|
147
+ break if input.none? || (repeat.max == Ldpath::Transform::Infinity && idx > 25) # we're probably lost..
105
148
  input = property.evaluate program, input, context
106
- result |= input
149
+
150
+ next unless idx >= repeat.min
151
+
152
+ enum_wrap(input).each do |x|
153
+ yield x
154
+ end
107
155
  end
108
- result.flatten.compact
109
156
  end
110
157
  end
111
158
 
@@ -118,21 +165,47 @@ module Ldpath
118
165
  end
119
166
 
120
167
  class PathSelector < CompoundSelector
121
- def evaluate(program, uris, context)
168
+ def evaluate(program, uris, context, &block)
169
+ return to_enum(:evaluate, program, uris, context) unless block_given?
170
+
122
171
  output = left.evaluate(program, uris, context)
123
- right.evaluate(program, output, context)
172
+ right.evaluate(program, output, context, &block)
124
173
  end
125
174
  end
126
175
 
127
176
  class UnionSelector < CompoundSelector
128
177
  def evaluate(program, uris, context)
129
- left.evaluate(program, uris, context) | right.evaluate(program, uris, context)
178
+ return to_enum(:evaluate, program, uris, context) unless block_given?
179
+
180
+ enum_union(left.evaluate(program, uris, context), right.evaluate(program, uris, context)).each do |x|
181
+ yield x
182
+ end
183
+ end
184
+
185
+ private
186
+
187
+ def enum_union(left, right)
188
+ return to_enum(:enum_union, left, right) unless block_given?
189
+
190
+ enum_wrap(left).each do |e|
191
+ yield e
192
+ end
193
+
194
+ enum_wrap(right).each do |e|
195
+ yield e
196
+ end
130
197
  end
131
198
  end
132
199
 
133
200
  class IntersectionSelector < CompoundSelector
134
201
  def evaluate(program, uris, context)
135
- left.evaluate(program, uris, context) & right.evaluate(program, uris, context)
202
+ return to_enum(:evaluate, program, uris, context) unless block_given?
203
+
204
+ result = left.evaluate(program, uris, context).to_a & right.evaluate(program, uris, context).to_a
205
+
206
+ result.each do |x|
207
+ yield x
208
+ end
136
209
  end
137
210
  end
138
211
 
@@ -144,15 +217,19 @@ module Ldpath
144
217
  end
145
218
 
146
219
  def evaluate(program, uris, context)
220
+ return to_enum(:evaluate, program, uris, context) unless block_given?
221
+
147
222
  program.meta[identifier] = tap.evaluate(program, uris, context).map { |x| RDF::Literal.new(x.to_s).canonicalize.object }
148
223
 
149
- Array(uris).map do |uri|
224
+ enum_wrap(uris).map do |uri|
150
225
  loading program, uri, context
151
- evaluate_one uri, context
152
- end.flatten.compact
226
+ enum_flatten_one(evaluate_one(uri, context)).each do |x|
227
+ yield x unless x.nil?
228
+ end
229
+ end
153
230
  end
154
231
 
155
- def evaluate_one(uri, context)
232
+ def evaluate_one(uri, _context)
156
233
  uri
157
234
  end
158
235
  end
data/lib/ldpath/tests.rb CHANGED
@@ -10,7 +10,7 @@ module Ldpath
10
10
  def evaluate(program, uris, context)
11
11
  entries = delegate.evaluate program, uris, context
12
12
  entries.select do |uri|
13
- Array(test.evaluate(program, uri, context)).any? do |x|
13
+ enum_wrap(test.evaluate(program, uri, context)).any? do |x|
14
14
  x
15
15
  end
16
16
  end
@@ -23,11 +23,10 @@ module Ldpath
23
23
  @lang = lang
24
24
  end
25
25
 
26
- def evaluate(program, uri, context)
26
+ def evaluate(_program, uri, _context)
27
27
  return unless uri.literal?
28
- if (lang == "none" && !uri.has_language?) || uri.language == lang
29
- uri
30
- end
28
+
29
+ uri if (lang == "none" && !uri.has_language?) || uri.language == lang
31
30
  end
32
31
  end
33
32
 
@@ -37,11 +36,10 @@ module Ldpath
37
36
  @type = type
38
37
  end
39
38
 
40
- def evaluate(program, uri, context)
39
+ def evaluate(program, uri, _context)
41
40
  return unless uri.literal?
42
- if uri.has_datatype? && uri.datatype == type
43
- uri
44
- end
41
+
42
+ uri if uri.has_datatype? && uri.datatype == type
45
43
  end
46
44
  end
47
45
 
@@ -53,7 +51,7 @@ module Ldpath
53
51
  end
54
52
 
55
53
  def evaluate(program, uri, context)
56
- !Array(delegate.evaluate(program, uri, context)).any? { |x| x }
54
+ !enum_wrap(delegate.evaluate(program, uri, context)).any? { |x| x }
57
55
  end
58
56
  end
59
57
 
@@ -79,8 +77,8 @@ module Ldpath
79
77
  end
80
78
 
81
79
  def evaluate(program, uri, context)
82
- left.evaluate(program, uri, context).compact.any? &&
83
- right.evaluate(program, uri, context).compact.any?
80
+ left.evaluate(program, uri, context).any? &&
81
+ right.evaluate(program, uri, context).any?
84
82
  end
85
83
  end
86
84
 
@@ -93,7 +91,7 @@ module Ldpath
93
91
  end
94
92
 
95
93
  def evaluate(program, uri, context)
96
- left.evaluate(program, uri, context).compact.include?(right)
94
+ left.evaluate(program, uri, context).include?(right)
97
95
  end
98
96
  end
99
97
  end
@@ -15,7 +15,7 @@ module Ldpath
15
15
  "fn" => RDF::Vocabulary.new("http://www.newmedialab.at/lmf/functions/1.0/"), # (LMF index functions)
16
16
  "foaf" => RDF::Vocabulary.new("http://xmlns.com/foaf/0.1/"),
17
17
  "info" => RDF::Vocabulary.new("info:"),
18
- "urn" => RDF::Vocabulary.new("urn:"),
18
+ "urn" => RDF::Vocabulary.new("urn:")
19
19
  }
20
20
  end
21
21
  end
@@ -71,7 +71,7 @@ module Ldpath
71
71
  # Mappings
72
72
 
73
73
  rule(mapping: subtree(:mapping)) do
74
- FieldMapping.new mapping[:name].to_s, mapping[:selector], mapping[:field_type]
74
+ FieldMapping.new mapping
75
75
  end
76
76
 
77
77
  ## Selectors
@@ -106,18 +106,13 @@ module Ldpath
106
106
  end
107
107
 
108
108
  rule(range: subtree(:range)) do
109
- case range
110
- when "*"
111
- 0..Infinity
112
- when "+"
113
- 1..Infinity
114
- when "?"
115
- 0..1
116
- else
117
- range.fetch(:min, 0).to_i..range.fetch(:max, Infinity).to_f
118
- end
109
+ range.fetch(:min, 0).to_i..range.fetch(:max, Infinity).to_f
119
110
  end
120
111
 
112
+ rule(range: '*') { 0..Infinity }
113
+ rule(range: '+') { 1..Infinity }
114
+ rule(range: '?') { 0..1 }
115
+
121
116
  rule(delegate: subtree(:delegate), repeat: simple(:repeat)) do
122
117
  RecursivePathSelector.new delegate, repeat
123
118
  end
@@ -126,6 +121,10 @@ module Ldpath
126
121
  TapSelector.new identifier.to_s, tap
127
122
  end
128
123
 
124
+ rule(not: simple(:not), property: sequence(:property)) do
125
+ NegatedPropertySelector.new(*property)
126
+ end
127
+
129
128
  ### Test Selectors
130
129
 
131
130
  rule(delegate: subtree(:delegate), test: subtree(:test)) do
@@ -144,16 +143,16 @@ module Ldpath
144
143
  TypeTest.new type
145
144
  end
146
145
 
147
- rule(not: subtree(:not_op)) do
148
- NotTest.new not_op[:delegate]
146
+ rule(not: simple(:not_op), delegate: simple(:delegate)) do
147
+ NotTest.new delegate
149
148
  end
150
149
 
151
- rule(and: subtree(:op)) do
152
- AndTest.new op[:left], op[:right]
150
+ rule(op: '|', left_test: subtree(:left_test), right_test: subtree(:right_test)) do
151
+ OrTest.new left_test, right_test
153
152
  end
154
153
 
155
- rule(or: subtree(:op)) do
156
- OrTest.new op[:left], op[:right]
154
+ rule(op: '&', left_test: subtree(:left_test), right_test: subtree(:right_test)) do
155
+ AndTest.new left_test, right_test
157
156
  end
158
157
 
159
158
  rule(is: subtree(:is)) do
@@ -165,15 +164,17 @@ module Ldpath
165
164
  end
166
165
 
167
166
  ### Compound Selectors
168
- rule(left: subtree(:left), op: simple(:op), right: subtree(:right)) do
169
- case op
170
- when "/"
171
- PathSelector.new left, right
172
- when "|"
173
- UnionSelector.new left, right
174
- when "&"
175
- IntersectionSelector.new left, right
176
- end
167
+
168
+ rule(op: '/', left: subtree(:left), right: subtree(:right)) do
169
+ PathSelector.new left, right
170
+ end
171
+
172
+ rule(op: '|', left: subtree(:left), right: subtree(:right)) do
173
+ UnionSelector.new left, right
174
+ end
175
+
176
+ rule(op: '&', left: subtree(:left), right: subtree(:right)) do
177
+ IntersectionSelector.new left, right
177
178
  end
178
179
 
179
180
  Infinity = 1.0 / 0.0
@@ -1,3 +1,3 @@
1
1
  module Ldpath
2
- VERSION = "0.3.1"
2
+ VERSION = '1.0.0'.freeze
3
3
  end
data/lib/ldpath.rb CHANGED
@@ -10,8 +10,11 @@ module Ldpath
10
10
  require 'ldpath/transform'
11
11
  require 'ldpath/functions'
12
12
  require 'ldpath/program'
13
+ require 'ldpath/result'
13
14
 
14
15
  class << self
16
+ attr_writer :logger
17
+
15
18
  def evaluate(program, uri, context)
16
19
  Ldpath::Program.parse(program).evaluate(uri, context)
17
20
  end
@@ -25,9 +28,5 @@ module Ldpath
25
28
  end
26
29
  end
27
30
  end
28
-
29
- def logger=(logger)
30
- @logger = logger
31
- end
32
31
  end
33
32
  end
@@ -0,0 +1,4 @@
1
+ <http://www.bbc.co.uk/programmes/b0081dq5> <http://xmlns.com/foaf/0.1/primaryTopic> <_:b0> .
2
+ <_:b0> <http://purl.org/ontology/po/pid> "b0081dq5" .
3
+ <_:b0> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/primaryTopic> .
4
+ <_:b0> <http://purl.org/dc/elements/1.1/title> "Huw Stephens" .
@@ -0,0 +1,3 @@
1
+ <http://id.loc.gov/authorities/names/n79021164> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.loc.gov/mads/rdf/v1#PersonalName> .
2
+ <http://id.loc.gov/authorities/names/n79021164> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.loc.gov/mads/rdf/v1#Authority> .
3
+ <http://id.loc.gov/authorities/names/n79021164> <http://www.loc.gov/mads/rdf/v1#authoritativeLabel> "Twain, Mark, 1835-1910 (network call to LOC)"@en .
@@ -200,12 +200,30 @@ describe Ldpath::Parser do
200
200
  end
201
201
 
202
202
  it "tap_selector" do
203
- subject.selector.parse('?<a><info:a>')
203
+ subject.selector.parse('?<__autocomplete>fn:predicates()')
204
204
  end
205
205
 
206
206
  it "loose_selector" do
207
207
  subject.selector.parse('~<info:a>')
208
208
  end
209
+
210
+ it "negated property selector" do
211
+ subject.selector.parse('!<info:a>')
212
+ end
213
+ end
214
+
215
+ describe "tests" do
216
+ it "should pass a simple property test" do
217
+ subject.selector.parse('.[info:a]')
218
+ end
219
+
220
+ it "should pass a property test with '&'" do
221
+ subject.selector.parse('.[info:a & info:b]')
222
+ end
223
+
224
+ it "should pass a property test with '|'" do
225
+ subject.selector.parse('.[info:a | info:b]')
226
+ end
209
227
  end
210
228
 
211
229
  describe "integration tests" do
@@ -36,19 +36,19 @@ EOF
36
36
  end
37
37
 
38
38
  it "should work" do
39
- graph << [object, RDF::DC.title, "Hello, world!"]
40
- graph << [object, RDF::DC.isPartOf, parent]
41
- graph << [object, RDF::DC.description, RDF::Literal.new("English!", language: "en")]
42
- graph << [object, RDF::DC.description, RDF::Literal.new("French!", language: "fr")]
39
+ graph << [object, RDF::Vocab::DC.title, "Hello, world!"]
40
+ graph << [object, RDF::Vocab::DC.isPartOf, parent]
41
+ graph << [object, RDF::Vocab::DC.description, RDF::Literal.new("English!", language: "en")]
42
+ graph << [object, RDF::Vocab::DC.description, RDF::Literal.new("French!", language: "fr")]
43
43
  graph << [object, RDF::URI.new("info:intProperty"), 1]
44
44
  graph << [object, RDF::URI.new("info:intProperty"), "garbage"]
45
45
  graph << [object, RDF::URI.new("info:numericProperty"), "1"]
46
- graph << [parent, RDF::DC.title, "Parent title"]
47
- graph << [child, RDF::DC.isPartOf, object]
48
- graph << [child, RDF::DC.title, "Child title"]
49
- graph << [parent, RDF::DC.isPartOf, grandparent]
46
+ graph << [parent, RDF::Vocab::DC.title, "Parent title"]
47
+ graph << [child, RDF::Vocab::DC.isPartOf, object]
48
+ graph << [child, RDF::Vocab::DC.title, "Child title"]
49
+ graph << [parent, RDF::Vocab::DC.isPartOf, grandparent]
50
50
 
51
- result = subject.evaluate object, graph
51
+ result = subject.evaluate object, context: graph
52
52
 
53
53
  expect(result["title"]).to match_array "Hello, world!"
54
54
  expect(result["parent_title"]).to match_array "Parent title"
@@ -97,17 +97,17 @@ EOF
97
97
 
98
98
  let(:graph) do
99
99
  graph = RDF::Graph.new
100
- graph << [object, RDF::DC.title, "Hello, world!"]
101
- graph << [object, RDF::DC.description, "Description"]
102
- graph << [object, RDF::DC.hasPart, "a"]
103
- graph << [object, RDF::DC.hasPart, "b"]
104
- graph << [object, RDF::DC.hasPart, "c"]
100
+ graph << [object, RDF::Vocab::DC.title, "Hello, world!"]
101
+ graph << [object, RDF::Vocab::DC.description, "Description"]
102
+ graph << [object, RDF::Vocab::DC.hasPart, "a"]
103
+ graph << [object, RDF::Vocab::DC.hasPart, "b"]
104
+ graph << [object, RDF::Vocab::DC.hasPart, "c"]
105
105
 
106
106
  graph
107
107
  end
108
108
 
109
109
  subject do
110
- program.evaluate object, graph
110
+ program.evaluate object, context: graph
111
111
  end
112
112
 
113
113
  describe "concat" do
@@ -191,8 +191,13 @@ title = foaf:primaryTopic / dc:title :: xsd:string ;
191
191
  EOF
192
192
  end
193
193
 
194
+ before do
195
+ stub_request(:get, 'http://www.bbc.co.uk/programmes/b0081dq5')
196
+ .to_return(status: 200, body: webmock_fixture('bbc_b0081dq5.nt'), headers: { 'Content-Type' => 'application/n-triples' })
197
+ end
198
+
194
199
  it "should work" do
195
- result = subject.evaluate RDF::URI.new("http://www.bbc.co.uk/programmes/b0081dq5.rdf")
200
+ result = subject.evaluate RDF::URI.new("http://www.bbc.co.uk/programmes/b0081dq5")
196
201
  expect(result["title"]).to match_array "Huw Stephens"
197
202
  end
198
203
  end
@@ -205,9 +210,16 @@ predicates = <http://xmlns.com/foaf/0.1/primaryTopic> / fn:predicates() :: xsd:s
205
210
  EOF
206
211
  end
207
212
 
213
+ before do
214
+ stub_request(:get, 'http://www.bbc.co.uk/programmes/b0081dq5')
215
+ .to_return(status: 200, body: webmock_fixture('bbc_b0081dq5.nt'), headers: { 'Content-Type' => 'application/n-triples' })
216
+ end
217
+
208
218
  it "should work" do
209
- result = subject.evaluate RDF::URI.new("http://www.bbc.co.uk/programmes/b0081dq5.rdf")
210
- expect(result["predicates"]).to include "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "http://purl.org/ontology/po/pid", "http://purl.org/dc/elements/1.1/title"
219
+ result = subject.evaluate RDF::URI.new("http://www.bbc.co.uk/programmes/b0081dq5")
220
+ expect(result["predicates"]).to include "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
221
+ "http://purl.org/ontology/po/pid",
222
+ "http://purl.org/dc/elements/1.1/title"
211
223
  end
212
224
  end
213
225
 
@@ -219,9 +231,9 @@ EOF
219
231
  let(:graph) do
220
232
  graph = RDF::Graph.new
221
233
 
222
- graph << [object, RDF::DC.title, "Object"]
223
- graph << [child, RDF::DC.title, "Child"]
224
- graph << [object, RDF::DC.hasPart, child]
234
+ graph << [object, RDF::Vocab::DC.title, "Object"]
235
+ graph << [child, RDF::Vocab::DC.title, "Child"]
236
+ graph << [object, RDF::Vocab::DC.hasPart, child]
225
237
 
226
238
  graph
227
239
  end
@@ -236,7 +248,7 @@ child_title_with_tap = dcterms:hasPart / ?<tap>fn:predicates() / dcterms:title :
236
248
  end
237
249
 
238
250
  it "should work" do
239
- result = subject.evaluate object, graph
251
+ result = subject.evaluate object, context: graph
240
252
  expect(result["child_title_with_tap"]).to eq result["child_title"]
241
253
  expect(result["tap"]).to eq ["http://purl.org/dc/terms/title"]
242
254
  end
@@ -250,9 +262,9 @@ child_title_with_tap = dcterms:hasPart / ?<tap>fn:predicates() / dcterms:title :
250
262
  let(:graph) do
251
263
  graph = RDF::Graph.new
252
264
 
253
- graph << [object, RDF::DC.title, "Object"]
254
- graph << [child, RDF::DC.title, "Child"]
255
- graph << [object, RDF::DC.hasPart, child]
265
+ graph << [object, RDF::Vocab::DC.title, "Object"]
266
+ graph << [child, RDF::Vocab::DC.title, "Child"]
267
+ graph << [object, RDF::Vocab::DC.hasPart, child]
256
268
 
257
269
  graph
258
270
  end
@@ -267,7 +279,7 @@ title_with_loose = ~dc:title :: xsd:string ;
267
279
  end
268
280
 
269
281
  it "should work" do
270
- result = subject.evaluate object, graph
282
+ result = subject.evaluate object, context: graph
271
283
  expect(result["title_with_loose"]).to eq result["title"]
272
284
  end
273
285
  end
@@ -288,27 +300,70 @@ title_with_loose = ~dc:title :: xsd:string ;
288
300
  let(:graph) do
289
301
  graph = RDF::Graph.new
290
302
 
291
- graph << [object, RDF.type, RDF::DC.Agent]
292
- graph << [object, RDF::DC.title, "Title"]
293
- graph << [other_object, RDF::DC.title, "Other Title"]
303
+ graph << [object, RDF.type, RDF::Vocab::DC.Agent]
304
+ graph << [object, RDF::Vocab::DC.title, "Title"]
305
+ graph << [other_object, RDF::Vocab::DC.title, "Other Title"]
294
306
 
295
307
  graph
296
308
  end
297
309
 
298
310
  it "should work" do
299
- result = subject.evaluate object, graph
311
+ result = subject.evaluate object, context: graph
300
312
  expect(result["title"]).to eq ["Title"]
301
313
  end
302
314
 
303
315
  it "filters objects that don't match" do
304
- result = subject.evaluate other_object, graph
316
+ result = subject.evaluate other_object, context: graph
305
317
  expect(result).to be_empty
306
318
  end
307
319
  end
308
320
 
309
321
  describe "error handling" do
310
322
  it "should provide a reasonable exception" do
311
- expect { Ldpath::Program.parse "title .= <oops> ;" }.to raise_error /Expected "=", but got "."/
323
+ expect { Ldpath::Program.parse "title .= <oops> ;" }.to raise_error(/Expected "=", but got "."/)
324
+ end
325
+ end
326
+
327
+ describe '#evaluate' do
328
+ context 'when passing limit_to_context' do
329
+ subject do
330
+ Ldpath::Program.parse <<-EOF
331
+ @prefix madsrdf : <http://www.loc.gov/mads/rdf/v1#> ;
332
+ @prefix schema: <http://www.w3.org/2000/01/rdf-schema#> ;
333
+ property = madsrdf:authoritativeLabel :: xsd:string ;
334
+ EOF
335
+ end
336
+
337
+ let(:subject_uri) { RDF::URI('http://id.loc.gov/authorities/names/n79021164') }
338
+
339
+ let(:graph) do
340
+ graph = RDF::Graph.new
341
+ graph << [subject_uri, RDF::Vocab::MADS.authoritativeLabel, 'Mark Twain (passed in context)']
342
+ graph
343
+ end
344
+
345
+ before do
346
+ stub_request(:get, 'http://id.loc.gov/authorities/names/n79021164')
347
+ .to_return(status: 200, body: webmock_fixture('loc_n79021164.nt'), headers: { 'Content-Type' => 'application/n-triples' })
348
+ end
349
+
350
+ context 'as false' do
351
+ let(:expected_values) { ['Mark Twain (passed in context)', 'Twain, Mark, 1835-1910 (network call to LOC)'] }
352
+
353
+ it 'returns values from context and network call' do
354
+ result = subject.evaluate subject_uri, context: graph
355
+ expect(result['property']).to match_array expected_values
356
+ end
357
+ end
358
+
359
+ context 'as true' do
360
+ let(:expected_values) { ['Mark Twain (passed in context)'] }
361
+
362
+ it 'returns values from context only' do
363
+ result = subject.evaluate(subject_uri, context: graph, limit_to_context: true)
364
+ expect(result['property']).to match_array expected_values
365
+ end
366
+ end
312
367
  end
313
368
  end
314
369
  end