ldpath 0.3.1 → 1.0.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -4
- data/.rubocop_todo.yml +2 -33
- data/.travis.yml +4 -1
- data/CHANGELOG.md +98 -0
- data/CODE_OF_CONDUCT.md +36 -0
- data/CONTRIBUTING.md +161 -0
- data/Gemfile +6 -2
- data/README.md +31 -7
- data/SUPPORT.md +6 -0
- data/bin/ldpath +20 -12
- data/ldpath.gemspec +9 -4
- data/lib/ldpath/field_mapping.rb +43 -1
- data/lib/ldpath/functions.rb +84 -72
- data/lib/ldpath/parser.rb +31 -36
- data/lib/ldpath/program.rb +7 -62
- data/lib/ldpath/result.rb +83 -0
- data/lib/ldpath/selectors.rb +105 -28
- data/lib/ldpath/tests.rb +11 -13
- data/lib/ldpath/transform.rb +28 -27
- data/lib/ldpath/version.rb +1 -1
- data/lib/ldpath.rb +3 -4
- data/spec/fixtures/bbc_b0081dq5.nt +4 -0
- data/spec/fixtures/loc_n79021164.nt +3 -0
- data/spec/ldpath_parser_spec.rb +19 -1
- data/spec/ldpath_program_spec.rb +87 -32
- data/spec/ldpath_transform_spec.rb +10 -0
- data/spec/lib/functions/list_spec.rb +1 -1
- data/spec/spec_helper.rb +31 -1
- metadata +73 -9
- data/.rubocop_hound.yml +0 -1063
data/lib/ldpath/selectors.rb
CHANGED
@@ -1,19 +1,48 @@
|
|
1
1
|
module Ldpath
|
2
2
|
class Selector
|
3
3
|
def evaluate(program, uris, context)
|
4
|
-
|
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
|
7
|
-
|
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,
|
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
|
-
|
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
|
41
|
-
|
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
|
-
|
97
|
-
input = Array(uris)
|
142
|
+
return to_enum(:evaluate, program, uris, context) unless block_given?
|
98
143
|
|
99
|
-
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
224
|
+
enum_wrap(uris).map do |uri|
|
150
225
|
loading program, uri, context
|
151
|
-
evaluate_one
|
152
|
-
|
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,
|
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
|
-
|
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(
|
26
|
+
def evaluate(_program, uri, _context)
|
27
27
|
return unless uri.literal?
|
28
|
-
|
29
|
-
|
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,
|
39
|
+
def evaluate(program, uri, _context)
|
41
40
|
return unless uri.literal?
|
42
|
-
|
43
|
-
|
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
|
-
!
|
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).
|
83
|
-
right.evaluate(program, uri, context).
|
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).
|
94
|
+
left.evaluate(program, uri, context).include?(right)
|
97
95
|
end
|
98
96
|
end
|
99
97
|
end
|
data/lib/ldpath/transform.rb
CHANGED
@@ -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
|
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
|
-
|
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:
|
148
|
-
NotTest.new
|
146
|
+
rule(not: simple(:not_op), delegate: simple(:delegate)) do
|
147
|
+
NotTest.new delegate
|
149
148
|
end
|
150
149
|
|
151
|
-
rule(
|
152
|
-
|
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(
|
156
|
-
|
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
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
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
|
data/lib/ldpath/version.rb
CHANGED
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 .
|
data/spec/ldpath_parser_spec.rb
CHANGED
@@ -200,12 +200,30 @@ describe Ldpath::Parser do
|
|
200
200
|
end
|
201
201
|
|
202
202
|
it "tap_selector" do
|
203
|
-
subject.selector.parse('?<
|
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
|
data/spec/ldpath_program_spec.rb
CHANGED
@@ -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
|
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
|
210
|
-
expect(result["predicates"]).to include "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
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
|
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
|