ldpath 0.0.1 → 0.0.2
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/Gemfile +1 -0
- data/ldpath.gemspec +1 -0
- data/lib/ldpath/functions.rb +4 -2
- data/lib/ldpath/parser.rb +23 -1
- data/lib/ldpath/program.rb +26 -9
- data/lib/ldpath/selectors.rb +39 -3
- data/lib/ldpath/transform.rb +12 -0
- data/lib/ldpath/version.rb +1 -1
- data/lib/ldpath.rb +15 -0
- data/spec/ldpath_parser_spec.rb +8 -0
- data/spec/ldpath_program_spec.rb +84 -4
- data/spec/ldpath_transform_spec.rb +9 -0
- data/spec/spec_helper.rb +5 -0
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: feb1911da55e6e56d33cb8bccea249060b59f7da
|
4
|
+
data.tar.gz: 87eab8d2813362a18c9ff45707325542f45ec657
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 111dbf2d32a03ab3199d622f1ea78c94322a24733e0120c537ed43d2f42c592e650ab72e67f067cf6578d4be2ddcdbfd6756d09369c2e9d8c1fb7757f7624bb2
|
7
|
+
data.tar.gz: 5dc5e8488936d2d14114522cb1880a05e165edc317b6a433b247dff8e235af989419a7fac28b71a8f5741da7a8d0b2b33c3e6d10179a0a3b830461ff748a970e
|
data/Gemfile
CHANGED
data/ldpath.gemspec
CHANGED
data/lib/ldpath/functions.rb
CHANGED
@@ -126,7 +126,6 @@ module Ldpath
|
|
126
126
|
end
|
127
127
|
|
128
128
|
def startsWith uri, context, str, suffix
|
129
|
-
|
130
129
|
Array(str).map { |x| x.start_with? suffix }
|
131
130
|
end
|
132
131
|
|
@@ -136,9 +135,12 @@ module Ldpath
|
|
136
135
|
end
|
137
136
|
|
138
137
|
def isEmpty uri, context, str
|
139
|
-
|
140
138
|
Array(str).map(&:empty?)
|
141
139
|
end
|
140
|
+
|
141
|
+
def predicates uri, context, *args
|
142
|
+
context.query([uri, nil, nil]).map(&:predicate).uniq
|
143
|
+
end
|
142
144
|
|
143
145
|
end
|
144
146
|
end
|
data/lib/ldpath/parser.rb
CHANGED
@@ -32,11 +32,13 @@ module Ldpath
|
|
32
32
|
rule(:star) { str("*") }
|
33
33
|
rule(:not_op) { str("!") }
|
34
34
|
rule(:inverse) { str("^") }
|
35
|
+
rule(:tap) { str("?") }
|
35
36
|
rule(:is) { str "is" }
|
36
37
|
rule(:is_a) { str "is-a" }
|
37
38
|
rule(:func) { str "fn:"}
|
38
39
|
rule(:type) { str "^^" }
|
39
40
|
rule(:lang) { str "@" }
|
41
|
+
rule(:loose) { str("~") }
|
40
42
|
|
41
43
|
# todo: fixme
|
42
44
|
rule(:uri) do
|
@@ -138,14 +140,17 @@ module Ldpath
|
|
138
140
|
self_selector |
|
139
141
|
function_selector |
|
140
142
|
property_selector |
|
143
|
+
loose_property_selector |
|
141
144
|
wildcard_selector |
|
142
145
|
reverse_property_selector |
|
143
146
|
string_constant_selector |
|
144
147
|
recursive_path_selector |
|
145
|
-
grouped_selector
|
148
|
+
grouped_selector |
|
149
|
+
tap_selector
|
146
150
|
)
|
147
151
|
}
|
148
152
|
|
153
|
+
|
149
154
|
rule(:atomic_or_testing_selector) {
|
150
155
|
(testing_selector | atomic_selector)
|
151
156
|
}
|
@@ -207,6 +212,14 @@ module Ldpath
|
|
207
212
|
).repeat >>
|
208
213
|
wsp?
|
209
214
|
}
|
215
|
+
|
216
|
+
# xyz
|
217
|
+
rule(:loose_property_selector) {
|
218
|
+
wsp? >>
|
219
|
+
loose >>
|
220
|
+
wsp? >>
|
221
|
+
uri.as(:loose_property) >> wsp?
|
222
|
+
}
|
210
223
|
|
211
224
|
# xyz
|
212
225
|
rule(:property_selector) {
|
@@ -251,6 +264,15 @@ module Ldpath
|
|
251
264
|
selector >> wsp? >>
|
252
265
|
str(")") >> wsp?
|
253
266
|
}
|
267
|
+
|
268
|
+
rule(:tap_selector) {
|
269
|
+
wsp? >>
|
270
|
+
tap >>
|
271
|
+
str("<") >>
|
272
|
+
identifier.as(:identifier) >>
|
273
|
+
str(">") >>
|
274
|
+
(atomic_selector).as(:tap)
|
275
|
+
}
|
254
276
|
|
255
277
|
# Testing Selectors
|
256
278
|
|
data/lib/ldpath/program.rb
CHANGED
@@ -21,25 +21,38 @@ module Ldpath
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
attr_reader :mappings
|
25
|
-
def initialize mappings
|
24
|
+
attr_reader :mappings, :cache, :loaded
|
25
|
+
def initialize mappings, cache = RDF::Util::Cache.new
|
26
26
|
@mappings ||= mappings
|
27
|
-
@cache =
|
27
|
+
@cache = cache
|
28
|
+
@loaded = {}
|
28
29
|
end
|
29
30
|
|
30
31
|
def loading uri, context
|
31
|
-
if uri.to_s =~ /^http/ and !
|
32
|
-
|
33
|
-
|
32
|
+
if uri.to_s =~ /^http/ and !loaded[uri]
|
33
|
+
context << load_graph(uri)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_graph uri
|
38
|
+
cache[uri] ||= begin
|
39
|
+
Ldpath.logger.debug "[#{self.object_id}] Loading #{uri.inspect}"
|
40
|
+
|
41
|
+
reader_types = RDF::Format.reader_types.reject { |t| t.to_s =~ /html/ }.map do |t|
|
42
|
+
t.to_s =~ /text\/(?:plain|html)/ ? "#{t};q=0.5" : t
|
43
|
+
end
|
44
|
+
|
45
|
+
RDF::Graph.load(uri, headers: { 'Accept' => reader_types.join(", ") }).tap { loaded[uri] = true }
|
34
46
|
end
|
35
47
|
end
|
36
48
|
|
37
49
|
def evaluate uri, context = nil
|
38
50
|
h = {}
|
39
|
-
context ||=
|
51
|
+
context ||= load_graph(uri.to_s)
|
40
52
|
|
41
53
|
mappings.each do |m|
|
42
|
-
h[m.name]
|
54
|
+
h[m.name] ||= []
|
55
|
+
h[m.name] += case m.selector
|
43
56
|
when Selector
|
44
57
|
m.selector.evaluate(self, uri, context).map do |x|
|
45
58
|
next x unless m.field_type
|
@@ -50,7 +63,11 @@ module Ldpath
|
|
50
63
|
end
|
51
64
|
end
|
52
65
|
|
53
|
-
h
|
66
|
+
h.merge(meta)
|
67
|
+
end
|
68
|
+
|
69
|
+
def meta
|
70
|
+
@meta ||= {}
|
54
71
|
end
|
55
72
|
|
56
73
|
def func_call fname, uri, context, *arguments
|
data/lib/ldpath/selectors.rb
CHANGED
@@ -21,9 +21,9 @@ module Ldpath
|
|
21
21
|
class FunctionSelector < Selector
|
22
22
|
attr_reader :fname, :arguments
|
23
23
|
|
24
|
-
def initialize fname, arguments
|
24
|
+
def initialize fname, arguments = []
|
25
25
|
@fname = fname
|
26
|
-
@arguments = arguments
|
26
|
+
@arguments = Array(arguments)
|
27
27
|
end
|
28
28
|
|
29
29
|
def evaluate program, uris, context
|
@@ -37,7 +37,7 @@ module Ldpath
|
|
37
37
|
i
|
38
38
|
end
|
39
39
|
end
|
40
|
-
program.func_call fname, uri, context,
|
40
|
+
program.func_call fname, uri, context, args
|
41
41
|
end.flatten.compact
|
42
42
|
end
|
43
43
|
end
|
@@ -53,6 +53,21 @@ module Ldpath
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
class LoosePropertySelector < Selector
|
57
|
+
attr_reader :property
|
58
|
+
def initialize property
|
59
|
+
@property = property
|
60
|
+
end
|
61
|
+
|
62
|
+
def evaluate_one uri, context
|
63
|
+
return PropertySelector.new(property).evaluate_one(uri_context) unless defined? RDF::Reasoner
|
64
|
+
|
65
|
+
context.query([uri, nil, nil]).select do |result|
|
66
|
+
result.predicate.entail(:subPropertyOf).include? property
|
67
|
+
end.map(&:object)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
56
71
|
class WildcardSelector < Selector
|
57
72
|
def evaluate_one uri, context
|
58
73
|
context.query([uri, nil, nil]).map(&:object)
|
@@ -121,4 +136,25 @@ module Ldpath
|
|
121
136
|
end
|
122
137
|
end
|
123
138
|
|
139
|
+
class TapSelector < Selector
|
140
|
+
attr_reader :identifier, :tap
|
141
|
+
def initialize identifier, tap
|
142
|
+
@identifier = identifier
|
143
|
+
@tap = tap
|
144
|
+
end
|
145
|
+
|
146
|
+
def evaluate program, uris, context
|
147
|
+
program.meta[identifier] = tap.evaluate(program, uris, context).map { |x| RDF::Literal.new(x.to_s).canonicalize.object }
|
148
|
+
|
149
|
+
Array(uris).map do |uri|
|
150
|
+
loading program, uri, context
|
151
|
+
evaluate_one uri, context
|
152
|
+
end.flatten.compact
|
153
|
+
end
|
154
|
+
|
155
|
+
def evaluate_one uri, context
|
156
|
+
uri
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
124
160
|
end
|
data/lib/ldpath/transform.rb
CHANGED
@@ -53,6 +53,10 @@ module Ldpath
|
|
53
53
|
SelfSelector.new
|
54
54
|
end
|
55
55
|
|
56
|
+
rule(fname: simple(:fname)) do
|
57
|
+
FunctionSelector.new fname.to_s
|
58
|
+
end
|
59
|
+
|
56
60
|
rule(fname: simple(:fname), arglist: subtree(:arglist)) do
|
57
61
|
FunctionSelector.new fname.to_s, arglist
|
58
62
|
end
|
@@ -60,6 +64,10 @@ module Ldpath
|
|
60
64
|
rule(property: simple(:property)) do
|
61
65
|
PropertySelector.new property
|
62
66
|
end
|
67
|
+
|
68
|
+
rule(loose_property: simple(:property)) do
|
69
|
+
LoosePropertySelector.new property
|
70
|
+
end
|
63
71
|
|
64
72
|
rule(wildcard: simple(:wilcard)) do
|
65
73
|
WildcardSelector.new
|
@@ -85,6 +93,10 @@ module Ldpath
|
|
85
93
|
|
86
94
|
RecursivePathSelector.new properties[:delegate], repeat
|
87
95
|
end
|
96
|
+
|
97
|
+
rule(identifier: simple(:identifier), tap: subtree(:tap)) do
|
98
|
+
TapSelector.new identifier.to_s, tap
|
99
|
+
end
|
88
100
|
|
89
101
|
### Test Selectors
|
90
102
|
|
data/lib/ldpath/version.rb
CHANGED
data/lib/ldpath.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "ldpath/version"
|
2
2
|
require 'linkeddata'
|
3
|
+
require 'logger'
|
3
4
|
|
4
5
|
module Ldpath
|
5
6
|
require 'ldpath/field_mapping'
|
@@ -14,5 +15,19 @@ module Ldpath
|
|
14
15
|
def evaluate program, uri, context
|
15
16
|
Ldpath::Program.parse(program).evaluate(uri, context)
|
16
17
|
end
|
18
|
+
|
19
|
+
def logger
|
20
|
+
@logger ||= begin
|
21
|
+
if defined? Rails
|
22
|
+
Rails.logger
|
23
|
+
else
|
24
|
+
Logger.new(STDERR)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def logger= logger
|
30
|
+
@logger = logger
|
31
|
+
end
|
17
32
|
end
|
18
33
|
end
|
data/spec/ldpath_parser_spec.rb
CHANGED
@@ -143,6 +143,14 @@ describe Ldpath::Parser do
|
|
143
143
|
it "function_selector" do
|
144
144
|
subject.selector.parse('fn:concat(foaf:givename," ",foaf:surname)')
|
145
145
|
end
|
146
|
+
|
147
|
+
it "tap_selector" do
|
148
|
+
subject.selector.parse('?<a><info:a>')
|
149
|
+
end
|
150
|
+
|
151
|
+
it "loose_selector" do
|
152
|
+
subject.selector.parse('~<info:a>')
|
153
|
+
end
|
146
154
|
end
|
147
155
|
|
148
156
|
describe "integration tests" do
|
data/spec/ldpath_program_spec.rb
CHANGED
@@ -76,7 +76,8 @@ EOF
|
|
76
76
|
subject do
|
77
77
|
Ldpath::Program.parse <<-EOF
|
78
78
|
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
79
|
-
|
79
|
+
ab = fn:concat("a", "b") ;
|
80
|
+
title = fn:concat(dcterms:title, dcterms:description) ;
|
80
81
|
first_a = fn:first("a", "b") ;
|
81
82
|
last_b = fn:last("a", "b") ;
|
82
83
|
EOF
|
@@ -85,15 +86,19 @@ EOF
|
|
85
86
|
let(:object) { RDF::URI.new("info:a") }
|
86
87
|
|
87
88
|
let(:graph) do
|
88
|
-
RDF::Graph.new
|
89
|
+
graph = RDF::Graph.new
|
90
|
+
graph << [object, RDF::DC.title, "Hello, world!"]
|
91
|
+
graph << [object, RDF::DC.description, "Description"]
|
92
|
+
|
93
|
+
graph
|
89
94
|
end
|
90
95
|
|
91
96
|
it "should work" do
|
92
97
|
result = subject.evaluate object, graph
|
93
|
-
expect(result["
|
98
|
+
expect(result["ab"]).to match_array "ab"
|
99
|
+
expect(result["title"]).to match_array "Hello, world!Description"
|
94
100
|
expect(result["first_a"]).to match_array "a"
|
95
101
|
expect(result["last_b"]).to match_array "b"
|
96
|
-
|
97
102
|
end
|
98
103
|
end
|
99
104
|
|
@@ -112,4 +117,79 @@ EOF
|
|
112
117
|
expect(result["title"]).to match_array "Huw Stephens"
|
113
118
|
end
|
114
119
|
end
|
120
|
+
|
121
|
+
describe "Predicate function" do
|
122
|
+
subject do
|
123
|
+
Ldpath::Program.parse <<-EOF
|
124
|
+
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
125
|
+
predicates = <http://xmlns.com/foaf/0.1/primaryTopic> / fn:predicates() :: xsd:string ;
|
126
|
+
EOF
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should work" do
|
130
|
+
result = subject.evaluate RDF::URI.new("http://www.bbc.co.uk/programmes/b0081dq5.rdf")
|
131
|
+
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"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "tap selector" do
|
136
|
+
let(:object) { RDF::URI.new("info:a") }
|
137
|
+
let(:child) { RDF::URI.new("info:b") }
|
138
|
+
let(:grandchild) { RDF::URI.new("info:c") }
|
139
|
+
|
140
|
+
let(:graph) do
|
141
|
+
graph = RDF::Graph.new
|
142
|
+
|
143
|
+
graph << [object, RDF::DC.title, "Object"]
|
144
|
+
graph << [child, RDF::DC.title, "Child"]
|
145
|
+
graph << [object, RDF::DC.hasPart, child]
|
146
|
+
|
147
|
+
graph
|
148
|
+
end
|
149
|
+
|
150
|
+
subject do
|
151
|
+
Ldpath::Program.parse <<-EOF
|
152
|
+
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
153
|
+
title = dcterms:title :: xsd:string ;
|
154
|
+
child_title = dcterms:hasPart / dcterms:title :: xsd:string ;
|
155
|
+
child_title_with_tap = dcterms:hasPart / ?<tap>fn:predicates() / dcterms:title :: xsd:string ;
|
156
|
+
EOF
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should work" do
|
160
|
+
result = subject.evaluate object, graph
|
161
|
+
expect(result["child_title_with_tap"]).to eq result["child_title"]
|
162
|
+
expect(result["tap"]).to eq ["http://purl.org/dc/terms/title"]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "loose selector" do
|
167
|
+
let(:object) { RDF::URI.new("info:a") }
|
168
|
+
let(:child) { RDF::URI.new("info:b") }
|
169
|
+
let(:grandchild) { RDF::URI.new("info:c") }
|
170
|
+
|
171
|
+
let(:graph) do
|
172
|
+
graph = RDF::Graph.new
|
173
|
+
|
174
|
+
graph << [object, RDF::DC.title, "Object"]
|
175
|
+
graph << [child, RDF::DC.title, "Child"]
|
176
|
+
graph << [object, RDF::DC.hasPart, child]
|
177
|
+
|
178
|
+
graph
|
179
|
+
end
|
180
|
+
|
181
|
+
subject do
|
182
|
+
Ldpath::Program.parse <<-EOF
|
183
|
+
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
184
|
+
@prefix dc: <http://purl.org/dc/elements/1.1/> ;
|
185
|
+
title = dcterms:title :: xsd:string ;
|
186
|
+
title_with_loose = ~dc:title :: xsd:string ;
|
187
|
+
EOF
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should work" do
|
191
|
+
result = subject.evaluate object, graph
|
192
|
+
expect(result["title_with_loose"]).to eq result["title"]
|
193
|
+
end
|
194
|
+
end
|
115
195
|
end
|
@@ -38,6 +38,15 @@ describe Ldpath::Transform do
|
|
38
38
|
subject.apply parser.parse("xyz = (info:a){2,} ;\n")
|
39
39
|
end
|
40
40
|
|
41
|
+
it "should transform tap selectors" do
|
42
|
+
subject.apply parser.parse("xyz = ?<x>info:a ;\n")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should transform loose property selectors" do
|
46
|
+
subject.apply parser.parse("xyz = ~info:a ;\n")
|
47
|
+
end
|
48
|
+
|
49
|
+
|
41
50
|
it "should transform namespaces" do
|
42
51
|
subject.apply parser.parse("@prefix foaf: <http://xmlns.com/foaf/0.1/>")
|
43
52
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ldpath
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Beer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parslet
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rdf-reasoner
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
description:
|
84
98
|
email:
|
85
99
|
- cabeer@stanford.edu
|
@@ -132,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
146
|
version: '0'
|
133
147
|
requirements: []
|
134
148
|
rubyforge_project:
|
135
|
-
rubygems_version: 2.
|
149
|
+
rubygems_version: 2.4.5
|
136
150
|
signing_key:
|
137
151
|
specification_version: 4
|
138
152
|
summary: Ruby implementation of LDPath
|