ldpath 1.1.0 → 1.2.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 +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
|
|