ldpath 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.circleci/config.yml +49 -0
- data/.rubocop.yml +40 -1
- data/CONTRIBUTING.md +45 -13
- data/Gemfile +3 -6
- data/README.md +7 -2
- data/Rakefile +2 -0
- data/bin/ldpath +6 -1
- data/ldpath.gemspec +10 -8
- data/lib/ldpath/field_mapping.rb +2 -0
- data/lib/ldpath/functions.rb +4 -4
- data/lib/ldpath/loaders/direct.rb +13 -7
- data/lib/ldpath/loaders/graph.rb +12 -6
- data/lib/ldpath/loaders/linked_data_fragment.rb +22 -16
- data/lib/ldpath/loaders.rb +8 -4
- data/lib/ldpath/parser.rb +4 -2
- data/lib/ldpath/program.rb +7 -7
- data/lib/ldpath/result.rb +7 -7
- data/lib/ldpath/selectors.rb +45 -26
- data/lib/ldpath/tests.rb +21 -3
- data/lib/ldpath/transform.rb +16 -14
- data/lib/ldpath/version.rb +3 -1
- data/lib/ldpath.rb +8 -7
- data/spec/ldpath_parser_spec.rb +6 -4
- data/spec/ldpath_program_spec.rb +70 -67
- data/spec/ldpath_spec.rb +2 -0
- data/spec/ldpath_transform_spec.rb +5 -3
- data/spec/lib/functions/list_spec.rb +2 -0
- data/spec/spec_helper.rb +2 -18
- metadata +33 -19
data/lib/ldpath/selectors.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Ldpath
|
2
4
|
class Selector
|
3
5
|
def evaluate(program, uris, context)
|
4
6
|
return to_enum(:evaluate, program, uris, context) unless block_given?
|
7
|
+
|
5
8
|
enum_wrap(uris).map do |uri|
|
6
9
|
loading program, uri, context
|
7
10
|
enum_flatten_one(evaluate_one(uri, context)).each do |x|
|
@@ -14,6 +17,10 @@ module Ldpath
|
|
14
17
|
program.loading uri, context
|
15
18
|
end
|
16
19
|
|
20
|
+
def initialize(*_args)
|
21
|
+
# abstract base class
|
22
|
+
end
|
23
|
+
|
17
24
|
protected
|
18
25
|
|
19
26
|
def enum_wrap(object)
|
@@ -29,14 +36,12 @@ module Ldpath
|
|
29
36
|
[object]
|
30
37
|
end
|
31
38
|
end
|
32
|
-
|
33
|
-
def enum_flatten_one(object)
|
39
|
+
|
40
|
+
def enum_flatten_one(object, &block)
|
34
41
|
return to_enum(:enum_flatten_one, object) unless block_given?
|
35
42
|
|
36
43
|
enum_wrap(object).each do |e|
|
37
|
-
enum_wrap(e).each
|
38
|
-
yield v
|
39
|
-
end
|
44
|
+
enum_wrap(e).each(&block)
|
40
45
|
end
|
41
46
|
end
|
42
47
|
end
|
@@ -53,6 +58,8 @@ module Ldpath
|
|
53
58
|
def initialize(fname, arguments = [])
|
54
59
|
@fname = fname
|
55
60
|
@arguments = Array(arguments)
|
61
|
+
|
62
|
+
super
|
56
63
|
end
|
57
64
|
|
58
65
|
def evaluate(program, uris, context)
|
@@ -77,8 +84,11 @@ module Ldpath
|
|
77
84
|
|
78
85
|
class PropertySelector < Selector
|
79
86
|
attr_reader :property
|
87
|
+
|
80
88
|
def initialize(property)
|
81
89
|
@property = property
|
90
|
+
|
91
|
+
super
|
82
92
|
end
|
83
93
|
|
84
94
|
def evaluate_one(uri, context)
|
@@ -88,8 +98,11 @@ module Ldpath
|
|
88
98
|
|
89
99
|
class LoosePropertySelector < Selector
|
90
100
|
attr_reader :property
|
101
|
+
|
91
102
|
def initialize(property)
|
92
103
|
@property = property
|
104
|
+
|
105
|
+
super
|
93
106
|
end
|
94
107
|
|
95
108
|
def evaluate_one(uri, context)
|
@@ -103,8 +116,11 @@ module Ldpath
|
|
103
116
|
|
104
117
|
class NegatedPropertySelector < Selector
|
105
118
|
attr_reader :properties
|
119
|
+
|
106
120
|
def initialize(*properties)
|
107
121
|
@properties = properties
|
122
|
+
|
123
|
+
super
|
108
124
|
end
|
109
125
|
|
110
126
|
def evaluate_one(uri, context)
|
@@ -122,8 +138,11 @@ module Ldpath
|
|
122
138
|
|
123
139
|
class ReversePropertySelector < Selector
|
124
140
|
attr_reader :property
|
141
|
+
|
125
142
|
def initialize(property)
|
126
143
|
@property = property
|
144
|
+
|
145
|
+
super
|
127
146
|
end
|
128
147
|
|
129
148
|
def evaluate_one(uri, context)
|
@@ -133,34 +152,39 @@ module Ldpath
|
|
133
152
|
|
134
153
|
class RecursivePathSelector < Selector
|
135
154
|
attr_reader :property, :repeat
|
155
|
+
|
136
156
|
def initialize(property, repeat)
|
137
157
|
@property = property
|
138
158
|
@repeat = repeat
|
159
|
+
|
160
|
+
super
|
139
161
|
end
|
140
162
|
|
141
|
-
def evaluate(program, uris, context)
|
163
|
+
def evaluate(program, uris, context, &block)
|
142
164
|
return to_enum(:evaluate, program, uris, context) unless block_given?
|
143
165
|
|
144
166
|
input = enum_wrap(uris)
|
145
167
|
|
146
|
-
(0..repeat.max).each_with_index do |
|
147
|
-
break if input.none? || (repeat.max == Ldpath::Transform::
|
168
|
+
(0..repeat.max).each_with_index do |_i, idx|
|
169
|
+
break if input.none? || (repeat.max == Ldpath::Transform::INFINITY && idx > 25) # we're probably lost..
|
170
|
+
|
148
171
|
input = property.evaluate program, input, context
|
149
172
|
|
150
173
|
next unless idx >= repeat.min
|
151
174
|
|
152
|
-
enum_wrap(input).each
|
153
|
-
yield x
|
154
|
-
end
|
175
|
+
enum_wrap(input).each(&block)
|
155
176
|
end
|
156
177
|
end
|
157
178
|
end
|
158
179
|
|
159
180
|
class CompoundSelector < Selector
|
160
181
|
attr_reader :left, :right
|
182
|
+
|
161
183
|
def initialize(left, right)
|
162
184
|
@left = left
|
163
185
|
@right = right
|
186
|
+
|
187
|
+
super
|
164
188
|
end
|
165
189
|
end
|
166
190
|
|
@@ -174,46 +198,41 @@ module Ldpath
|
|
174
198
|
end
|
175
199
|
|
176
200
|
class UnionSelector < CompoundSelector
|
177
|
-
def evaluate(program, uris, context)
|
201
|
+
def evaluate(program, uris, context, &block)
|
178
202
|
return to_enum(:evaluate, program, uris, context) unless block_given?
|
179
203
|
|
180
|
-
enum_union(left.evaluate(program, uris, context), right.evaluate(program, uris, context)).each
|
181
|
-
yield x
|
182
|
-
end
|
204
|
+
enum_union(left.evaluate(program, uris, context), right.evaluate(program, uris, context)).each(&block)
|
183
205
|
end
|
184
206
|
|
185
207
|
private
|
186
208
|
|
187
|
-
def enum_union(left, right)
|
209
|
+
def enum_union(left, right, &block)
|
188
210
|
return to_enum(:enum_union, left, right) unless block_given?
|
189
211
|
|
190
|
-
enum_wrap(left).each
|
191
|
-
yield e
|
192
|
-
end
|
212
|
+
enum_wrap(left).each(&block)
|
193
213
|
|
194
|
-
enum_wrap(right).each
|
195
|
-
yield e
|
196
|
-
end
|
214
|
+
enum_wrap(right).each(&block)
|
197
215
|
end
|
198
216
|
end
|
199
217
|
|
200
218
|
class IntersectionSelector < CompoundSelector
|
201
|
-
def evaluate(program, uris, context)
|
219
|
+
def evaluate(program, uris, context, &block)
|
202
220
|
return to_enum(:evaluate, program, uris, context) unless block_given?
|
203
221
|
|
204
222
|
result = left.evaluate(program, uris, context).to_a & right.evaluate(program, uris, context).to_a
|
205
223
|
|
206
|
-
result.each
|
207
|
-
yield x
|
208
|
-
end
|
224
|
+
result.each(&block)
|
209
225
|
end
|
210
226
|
end
|
211
227
|
|
212
228
|
class TapSelector < Selector
|
213
229
|
attr_reader :identifier, :tap
|
230
|
+
|
214
231
|
def initialize(identifier, tap)
|
215
232
|
@identifier = identifier
|
216
233
|
@tap = tap
|
234
|
+
|
235
|
+
super
|
217
236
|
end
|
218
237
|
|
219
238
|
def evaluate(program, uris, context)
|
data/lib/ldpath/tests.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Ldpath
|
2
4
|
class TestSelector < Selector
|
3
5
|
attr_reader :delegate, :test
|
4
6
|
|
5
|
-
def initialize(delegate, test)
|
7
|
+
def initialize(delegate = nil, test = nil)
|
6
8
|
@delegate = delegate
|
7
9
|
@test = test
|
10
|
+
|
11
|
+
super
|
8
12
|
end
|
9
13
|
|
10
14
|
def evaluate(program, uris, context)
|
@@ -22,8 +26,11 @@ module Ldpath
|
|
22
26
|
|
23
27
|
class LanguageTest < TestSelector
|
24
28
|
attr_reader :lang
|
29
|
+
|
25
30
|
def initialize(lang)
|
26
31
|
@lang = lang
|
32
|
+
|
33
|
+
super
|
27
34
|
end
|
28
35
|
|
29
36
|
def evaluate(_program, uri, _context)
|
@@ -35,11 +42,14 @@ module Ldpath
|
|
35
42
|
|
36
43
|
class TypeTest < TestSelector
|
37
44
|
attr_reader :type
|
45
|
+
|
38
46
|
def initialize(type)
|
39
47
|
@type = type
|
48
|
+
|
49
|
+
super
|
40
50
|
end
|
41
51
|
|
42
|
-
def evaluate(
|
52
|
+
def evaluate(_program, uri, _context)
|
43
53
|
return unless uri.literal?
|
44
54
|
|
45
55
|
uri if uri.has_datatype? && uri.datatype == type
|
@@ -51,10 +61,12 @@ module Ldpath
|
|
51
61
|
|
52
62
|
def initialize(delegate)
|
53
63
|
@delegate = delegate
|
64
|
+
|
65
|
+
super
|
54
66
|
end
|
55
67
|
|
56
68
|
def evaluate(program, uri, context)
|
57
|
-
|
69
|
+
enum_wrap(delegate.evaluate(program, uri, context)).none? { |x| x }
|
58
70
|
end
|
59
71
|
end
|
60
72
|
|
@@ -64,6 +76,8 @@ module Ldpath
|
|
64
76
|
def initialize(left, right)
|
65
77
|
@left = left
|
66
78
|
@right = right
|
79
|
+
|
80
|
+
super
|
67
81
|
end
|
68
82
|
|
69
83
|
def evaluate(program, uri, context)
|
@@ -77,6 +91,8 @@ module Ldpath
|
|
77
91
|
def initialize(left, right)
|
78
92
|
@left = left
|
79
93
|
@right = right
|
94
|
+
|
95
|
+
super
|
80
96
|
end
|
81
97
|
|
82
98
|
def evaluate(program, uri, context)
|
@@ -91,6 +107,8 @@ module Ldpath
|
|
91
107
|
def initialize(left, right)
|
92
108
|
@left = left
|
93
109
|
@right = right
|
110
|
+
|
111
|
+
super
|
94
112
|
end
|
95
113
|
|
96
114
|
def evaluate(program, uri, context)
|
data/lib/ldpath/transform.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Ldpath
|
2
4
|
class Transform < Parslet::Transform
|
3
5
|
attr_reader :prefixes
|
@@ -5,17 +7,17 @@ module Ldpath
|
|
5
7
|
class << self
|
6
8
|
def default_prefixes
|
7
9
|
@default_prefixes ||= {
|
8
|
-
"rdf"
|
10
|
+
"rdf" => RDF::Vocabulary.new("http://www.w3.org/1999/02/22-rdf-syntax-ns#"),
|
9
11
|
"rdfs" => RDF::Vocabulary.new("http://www.w3.org/2000/01/rdf-schema#"),
|
10
|
-
"owl"
|
12
|
+
"owl" => RDF::Vocabulary.new("http://www.w3.org/2002/07/owl#"),
|
11
13
|
"skos" => RDF::Vocabulary.new("http://www.w3.org/2004/02/skos/core#"),
|
12
|
-
"dc"
|
13
|
-
"xsd"
|
14
|
-
"lmf"
|
15
|
-
"fn"
|
14
|
+
"dc" => RDF::Vocabulary.new("http://purl.org/dc/elements/1.1/"),
|
15
|
+
"xsd" => RDF::Vocabulary.new("http://www.w3.org/2001/XMLSchema#"), # (LMF base index datatypes/XML Schema)
|
16
|
+
"lmf" => RDF::Vocabulary.new("http://www.newmedialab.at/lmf/types/1.0/"), # (LMF extended index datatypes)
|
17
|
+
"fn" => RDF::Vocabulary.new("http://www.newmedialab.at/lmf/functions/1.0/"), # (LMF index functions)
|
16
18
|
"foaf" => RDF::Vocabulary.new("http://xmlns.com/foaf/0.1/"),
|
17
19
|
"info" => RDF::Vocabulary.new("info:"),
|
18
|
-
"urn"
|
20
|
+
"urn" => RDF::Vocabulary.new("urn:")
|
19
21
|
}
|
20
22
|
end
|
21
23
|
end
|
@@ -29,8 +31,8 @@ module Ldpath
|
|
29
31
|
end
|
30
32
|
|
31
33
|
# Core types
|
32
|
-
rule(true
|
33
|
-
rule(false
|
34
|
+
rule(true => simple(true)) { true }
|
35
|
+
rule(false => simple(false)) { false }
|
34
36
|
rule(integer: simple(:integer)) { integer.to_i }
|
35
37
|
rule(double: simple(:double)) { double.to_f }
|
36
38
|
rule(decimal: simple(:decimal)) { decimal.to_f }
|
@@ -71,7 +73,7 @@ module Ldpath
|
|
71
73
|
# Mappings
|
72
74
|
|
73
75
|
rule(mapping: subtree(:mapping)) do
|
74
|
-
FieldMapping.new
|
76
|
+
FieldMapping.new(**mapping)
|
75
77
|
end
|
76
78
|
|
77
79
|
## Selectors
|
@@ -106,11 +108,11 @@ module Ldpath
|
|
106
108
|
end
|
107
109
|
|
108
110
|
rule(range: subtree(:range)) do
|
109
|
-
range.fetch(:min, 0).to_i..range.fetch(:max,
|
111
|
+
range.fetch(:min, 0).to_i..range.fetch(:max, INFINITY).to_f
|
110
112
|
end
|
111
113
|
|
112
|
-
rule(range: '*') { 0..
|
113
|
-
rule(range: '+') { 1..
|
114
|
+
rule(range: '*') { 0..INFINITY }
|
115
|
+
rule(range: '+') { 1..INFINITY }
|
114
116
|
rule(range: '?') { 0..1 }
|
115
117
|
|
116
118
|
rule(delegate: subtree(:delegate), repeat: simple(:repeat)) do
|
@@ -177,6 +179,6 @@ module Ldpath
|
|
177
179
|
IntersectionSelector.new left, right
|
178
180
|
end
|
179
181
|
|
180
|
-
|
182
|
+
INFINITY = 1.0 / 0.0
|
181
183
|
end
|
182
184
|
end
|
data/lib/ldpath/version.rb
CHANGED
data/lib/ldpath.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "ldpath/version"
|
2
4
|
require 'logger'
|
3
5
|
require 'nokogiri'
|
4
6
|
require 'rdf'
|
7
|
+
require 'rdf/vocab'
|
5
8
|
# require rdf/ntriples may not be necessary, may only really be necessary
|
6
9
|
# for ldpath_program_spec.rb tests, but I'm not certain, and I don't think it hurts
|
7
10
|
# to do it here.
|
@@ -26,13 +29,11 @@ module Ldpath
|
|
26
29
|
end
|
27
30
|
|
28
31
|
def logger
|
29
|
-
@logger ||=
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
end
|
32
|
+
@logger ||= if defined? Rails
|
33
|
+
Rails.logger
|
34
|
+
else
|
35
|
+
Logger.new($stderr)
|
36
|
+
end
|
36
37
|
end
|
37
38
|
end
|
38
39
|
end
|
data/spec/ldpath_parser_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
require 'pp'
|
3
5
|
require 'parslet/convenience'
|
@@ -228,10 +230,10 @@ describe Ldpath::Parser do
|
|
228
230
|
|
229
231
|
describe "integration tests" do
|
230
232
|
it "should parse a simple example" do
|
231
|
-
tree = subject.parse
|
232
|
-
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
233
|
-
topic = <http://xmlns.com/foaf/0.1/primaryTopic> :: xsd:string ;
|
234
|
-
EOF
|
233
|
+
tree = subject.parse <<~EOF
|
234
|
+
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
235
|
+
topic = <http://xmlns.com/foaf/0.1/primaryTopic> :: xsd:string ;
|
236
|
+
EOF
|
235
237
|
expect(tree.length).to eq 2
|
236
238
|
expect(tree.first).to include :prefixID
|
237
239
|
expect(tree.first[:prefixID]).to include id: 'dcterms'
|
data/spec/ldpath_program_spec.rb
CHANGED
@@ -1,31 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Ldpath::Program do
|
4
6
|
describe "Simple program" do
|
5
7
|
subject do
|
6
|
-
Ldpath::Program.parse
|
7
|
-
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
8
|
-
title = dcterms:title :: xsd:string ;
|
9
|
-
parent_title = dcterms:isPartOf / dcterms:title :: xsd:string ;
|
10
|
-
parent_title_en = dcterms:isPartOf / dcterms:title[@en] :: xsd:string ;
|
11
|
-
titles = dcterms:title | (dcterms:isPartOf / dcterms:title) | (^dcterms:isPartOf / dcterms:title) :: xsd:string ;
|
12
|
-
no_titles = dcterms:title & (dcterms:isPartOf / dcterms:title) & (^dcterms:isPartOf / dcterms:title) :: xsd:string ;
|
13
|
-
self = . :: xsd:string ;
|
14
|
-
wildcard = * ::xsd:string ;
|
15
|
-
child_title = ^dcterms:isPartOf / dcterms:title :: xsd:string ;
|
16
|
-
child_description_en = ^dcterms:isPartOf / dcterms:description[@en] :: xsd:string ;
|
17
|
-
recursive = (dcterms:isPartOf)* ;
|
18
|
-
en_description = dcterms:description[@en] ;
|
19
|
-
conditional = dcterms:isPartOf[dcterms:title] ;
|
20
|
-
conditional_false = dcterms:isPartOf[dcterms:description] ;
|
21
|
-
int_value = <info:intProperty>[^^xsd:integer] :: xsd:integer ;
|
22
|
-
numeric_value = <info:numericProperty> :: xsd:integer ;
|
23
|
-
escaped_string = "\\"" :: xsd:string;
|
24
|
-
and_test = .[dcterms:title & dcterms:gone] ;
|
25
|
-
or_test = .[dcterms:title | dcterms:gone] ;
|
26
|
-
is_test = .[dcterms:title is "Hello, world!"] ;
|
27
|
-
is_not_test = .[!(dcterms:title is "Hello, world!")] ;
|
28
|
-
EOF
|
8
|
+
Ldpath::Program.parse <<~EOF
|
9
|
+
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
10
|
+
title = dcterms:title :: xsd:string ;
|
11
|
+
parent_title = dcterms:isPartOf / dcterms:title :: xsd:string ;
|
12
|
+
parent_title_en = dcterms:isPartOf / dcterms:title[@en] :: xsd:string ;
|
13
|
+
titles = dcterms:title | (dcterms:isPartOf / dcterms:title) | (^dcterms:isPartOf / dcterms:title) :: xsd:string ;
|
14
|
+
no_titles = dcterms:title & (dcterms:isPartOf / dcterms:title) & (^dcterms:isPartOf / dcterms:title) :: xsd:string ;
|
15
|
+
self = . :: xsd:string ;
|
16
|
+
wildcard = * ::xsd:string ;
|
17
|
+
child_title = ^dcterms:isPartOf / dcterms:title :: xsd:string ;
|
18
|
+
child_description_en = ^dcterms:isPartOf / dcterms:description[@en] :: xsd:string ;
|
19
|
+
recursive = (dcterms:isPartOf)* ;
|
20
|
+
en_description = dcterms:description[@en] ;
|
21
|
+
conditional = dcterms:isPartOf[dcterms:title] ;
|
22
|
+
conditional_false = dcterms:isPartOf[dcterms:description] ;
|
23
|
+
int_value = <info:intProperty>[^^xsd:integer] :: xsd:integer ;
|
24
|
+
numeric_value = <info:numericProperty> :: xsd:integer ;
|
25
|
+
escaped_string = "\\"" :: xsd:string;
|
26
|
+
and_test = .[dcterms:title & dcterms:gone] ;
|
27
|
+
or_test = .[dcterms:title | dcterms:gone] ;
|
28
|
+
is_test = .[dcterms:title is "Hello, world!"] ;
|
29
|
+
is_not_test = .[!(dcterms:title is "Hello, world!")] ;
|
30
|
+
EOF
|
29
31
|
end
|
30
32
|
|
31
33
|
let(:object) { RDF::URI.new("info:a") }
|
@@ -77,24 +79,24 @@ EOF
|
|
77
79
|
|
78
80
|
describe "functions" do
|
79
81
|
let(:program) do
|
80
|
-
Ldpath::Program.parse
|
81
|
-
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
82
|
-
ab = fn:concat("a", "b") ;
|
83
|
-
title = fn:concat(dcterms:title, dcterms:description) ;
|
84
|
-
title_mix = fn:concat("!", dcterms:title) ;
|
85
|
-
title_missing = fn:concat("z", dcterms:genre) ;
|
86
|
-
first_a = fn:first("a", "b") ;
|
87
|
-
first_b = fn:first(dcterms:genre, "b") ;
|
88
|
-
last_a = fn:last("a", dcterms:genre) ;
|
89
|
-
last_b = fn:last("a", "b") ;
|
90
|
-
count_5 = fn:count("a", "b", "c", "d", "e");
|
91
|
-
count_3 = fn:count(dcterms:hasPart);
|
92
|
-
count_still_3 = fn:count(dcterms:hasPart, dcterms:genre);
|
93
|
-
eq_true = fn:eq("a", "a");
|
94
|
-
eq_false = fn:eq("a", "b");
|
95
|
-
eq_node_true = fn:eq(dcterms:description, "Description");
|
96
|
-
xpath_test = fn:xpath("//title", "<root><title>xyz</title></root>");
|
97
|
-
EOF
|
82
|
+
Ldpath::Program.parse <<~EOF
|
83
|
+
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
84
|
+
ab = fn:concat("a", "b") ;
|
85
|
+
title = fn:concat(dcterms:title, dcterms:description) ;
|
86
|
+
title_mix = fn:concat("!", dcterms:title) ;
|
87
|
+
title_missing = fn:concat("z", dcterms:genre) ;
|
88
|
+
first_a = fn:first("a", "b") ;
|
89
|
+
first_b = fn:first(dcterms:genre, "b") ;
|
90
|
+
last_a = fn:last("a", dcterms:genre) ;
|
91
|
+
last_b = fn:last("a", "b") ;
|
92
|
+
count_5 = fn:count("a", "b", "c", "d", "e");
|
93
|
+
count_3 = fn:count(dcterms:hasPart);
|
94
|
+
count_still_3 = fn:count(dcterms:hasPart, dcterms:genre);
|
95
|
+
eq_true = fn:eq("a", "a");
|
96
|
+
eq_false = fn:eq("a", "b");
|
97
|
+
eq_node_true = fn:eq(dcterms:description, "Description");
|
98
|
+
xpath_test = fn:xpath("//title", "<root><title>xyz</title></root>");
|
99
|
+
EOF
|
98
100
|
end
|
99
101
|
|
100
102
|
let(:object) { RDF::URI.new("info:a") }
|
@@ -192,16 +194,16 @@ EOF
|
|
192
194
|
Ldpath::Program.parse <<-EOF, context
|
193
195
|
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
194
196
|
title = foaf:primaryTopic / dc:title :: xsd:string ;
|
195
|
-
|
197
|
+
EOF
|
196
198
|
end
|
197
199
|
let(:context) { {} }
|
198
200
|
|
199
201
|
context 'with direct loading' do
|
200
|
-
let(:context) { { default_loader: Ldpath::Loaders::Direct.new }}
|
202
|
+
let(:context) { { default_loader: Ldpath::Loaders::Direct.new } }
|
201
203
|
|
202
204
|
before do
|
203
205
|
stub_request(:get, 'http://www.bbc.co.uk/programmes/b0081dq5')
|
204
|
-
|
206
|
+
.to_return(status: 200, body: webmock_fixture('bbc_b0081dq5.nt'), headers: { 'Content-Type' => 'application/n-triples' })
|
205
207
|
end
|
206
208
|
|
207
209
|
it "should work" do
|
@@ -213,10 +215,11 @@ EOF
|
|
213
215
|
context 'with an existing graph' do
|
214
216
|
let(:graph) { RDF::Graph.new }
|
215
217
|
let(:graph_loader) { Ldpath::Loaders::Graph.new graph: graph }
|
216
|
-
let(:context) { { default_loader: graph_loader }}
|
218
|
+
let(:context) { { default_loader: graph_loader } }
|
217
219
|
|
218
220
|
before do
|
219
|
-
graph << [RDF::URI('http://www.bbc.co.uk/programmes/b0081dq5'), RDF::URI('http://xmlns.com/foaf/0.1/primaryTopic'),
|
221
|
+
graph << [RDF::URI('http://www.bbc.co.uk/programmes/b0081dq5'), RDF::URI('http://xmlns.com/foaf/0.1/primaryTopic'),
|
222
|
+
RDF::URI('info:some_uri')]
|
220
223
|
graph << [RDF::URI('info:some_uri'), RDF::URI('http://purl.org/dc/elements/1.1/title'), 'Local Huw Stephens']
|
221
224
|
end
|
222
225
|
|
@@ -228,11 +231,11 @@ EOF
|
|
228
231
|
|
229
232
|
context 'with linked data fragments' do
|
230
233
|
let(:graph_loader) { Ldpath::Loaders::LinkedDataFragment.new('http://example.com/ldf') }
|
231
|
-
let(:context) { { default_loader: graph_loader }}
|
234
|
+
let(:context) { { default_loader: graph_loader } }
|
232
235
|
|
233
236
|
before do
|
234
237
|
stub_request(:get, 'http://example.com/ldf?subject=http://www.bbc.co.uk/programmes/b0081dq5')
|
235
|
-
|
238
|
+
.to_return(status: 200, body: webmock_fixture('bbc_b0081dq5.nt'), headers: { 'Content-Type' => 'application/n-triples' })
|
236
239
|
end
|
237
240
|
|
238
241
|
it "should work" do
|
@@ -244,10 +247,10 @@ EOF
|
|
244
247
|
|
245
248
|
describe "Predicate function" do
|
246
249
|
subject do
|
247
|
-
Ldpath::Program.parse
|
248
|
-
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
249
|
-
predicates = <http://xmlns.com/foaf/0.1/primaryTopic> / fn:predicates() :: xsd:string ;
|
250
|
-
EOF
|
250
|
+
Ldpath::Program.parse <<~EOF
|
251
|
+
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
252
|
+
predicates = <http://xmlns.com/foaf/0.1/primaryTopic> / fn:predicates() :: xsd:string ;
|
253
|
+
EOF
|
251
254
|
end
|
252
255
|
|
253
256
|
before do
|
@@ -279,11 +282,11 @@ EOF
|
|
279
282
|
end
|
280
283
|
|
281
284
|
subject do
|
282
|
-
Ldpath::Program.parse
|
283
|
-
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
284
|
-
title = dcterms:title :: xsd:string ;
|
285
|
-
child_title = dcterms:hasPart / dcterms:title :: xsd:string ;
|
286
|
-
child_title_with_tap = dcterms:hasPart / ?<tap>fn:predicates() / dcterms:title :: xsd:string ;
|
285
|
+
Ldpath::Program.parse <<~EOF
|
286
|
+
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
287
|
+
title = dcterms:title :: xsd:string ;
|
288
|
+
child_title = dcterms:hasPart / dcterms:title :: xsd:string ;
|
289
|
+
child_title_with_tap = dcterms:hasPart / ?<tap>fn:predicates() / dcterms:title :: xsd:string ;
|
287
290
|
EOF
|
288
291
|
end
|
289
292
|
|
@@ -310,11 +313,11 @@ child_title_with_tap = dcterms:hasPart / ?<tap>fn:predicates() / dcterms:title :
|
|
310
313
|
end
|
311
314
|
|
312
315
|
subject do
|
313
|
-
Ldpath::Program.parse
|
314
|
-
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
315
|
-
@prefix dc: <http://purl.org/dc/elements/1.1/> ;
|
316
|
-
title = dcterms:title :: xsd:string ;
|
317
|
-
title_with_loose = ~dc:title :: xsd:string ;
|
316
|
+
Ldpath::Program.parse <<~EOF
|
317
|
+
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
318
|
+
@prefix dc: <http://purl.org/dc/elements/1.1/> ;
|
319
|
+
title = dcterms:title :: xsd:string ;
|
320
|
+
title_with_loose = ~dc:title :: xsd:string ;
|
318
321
|
EOF
|
319
322
|
end
|
320
323
|
|
@@ -367,10 +370,10 @@ title_with_loose = ~dc:title :: xsd:string ;
|
|
367
370
|
describe '#evaluate' do
|
368
371
|
context 'when passing limit_to_context' do
|
369
372
|
subject do
|
370
|
-
Ldpath::Program.parse
|
371
|
-
@prefix madsrdf : <http://www.loc.gov/mads/rdf/v1#> ;
|
372
|
-
@prefix schema: <http://www.w3.org/2000/01/rdf-schema#> ;
|
373
|
-
property = madsrdf:authoritativeLabel :: xsd:string ;
|
373
|
+
Ldpath::Program.parse <<~EOF
|
374
|
+
@prefix madsrdf : <http://www.loc.gov/mads/rdf/v1#> ;
|
375
|
+
@prefix schema: <http://www.w3.org/2000/01/rdf-schema#> ;
|
376
|
+
property = madsrdf:authoritativeLabel :: xsd:string ;
|
374
377
|
EOF
|
375
378
|
end
|
376
379
|
|
@@ -384,7 +387,7 @@ property = madsrdf:authoritativeLabel :: xsd:string ;
|
|
384
387
|
|
385
388
|
before do
|
386
389
|
stub_request(:get, 'http://id.loc.gov/authorities/names/n79021164')
|
387
|
-
|
390
|
+
.to_return(status: 200, body: webmock_fixture('loc_n79021164.nt'), headers: { 'Content-Type' => 'application/n-triples' })
|
388
391
|
end
|
389
392
|
|
390
393
|
context 'as false' do
|
data/spec/ldpath_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
require 'pp'
|
3
5
|
describe Ldpath::Transform do
|
@@ -98,7 +100,7 @@ describe Ldpath::Transform do
|
|
98
100
|
selector = actual.first.selector
|
99
101
|
expect(selector).to be_a_kind_of Ldpath::RecursivePathSelector
|
100
102
|
expect(selector.property.property).to eq RDF::URI.new("info:a")
|
101
|
-
expect(selector.repeat).to eq 0..Ldpath::Transform::
|
103
|
+
expect(selector.repeat).to eq 0..Ldpath::Transform::INFINITY
|
102
104
|
end
|
103
105
|
|
104
106
|
it "is a 1-to-infinity matcher" do
|
@@ -107,7 +109,7 @@ describe Ldpath::Transform do
|
|
107
109
|
selector = actual.first.selector
|
108
110
|
expect(selector).to be_a_kind_of Ldpath::RecursivePathSelector
|
109
111
|
expect(selector.property.property).to eq RDF::URI.new("info:a")
|
110
|
-
expect(selector.repeat).to eq 1..Ldpath::Transform::
|
112
|
+
expect(selector.repeat).to eq 1..Ldpath::Transform::INFINITY
|
111
113
|
end
|
112
114
|
|
113
115
|
it "is a 0 to 5 matcher" do
|
@@ -134,7 +136,7 @@ describe Ldpath::Transform do
|
|
134
136
|
selector = actual.first.selector
|
135
137
|
expect(selector).to be_a_kind_of Ldpath::RecursivePathSelector
|
136
138
|
expect(selector.property.property).to eq RDF::URI.new("info:a")
|
137
|
-
expect(selector.repeat).to eq 2..Ldpath::Transform::
|
139
|
+
expect(selector.repeat).to eq 2..Ldpath::Transform::INFINITY
|
138
140
|
end
|
139
141
|
end
|
140
142
|
|