ldpath 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -1
- data/CHANGELOG.md +5 -0
- data/README.md +8 -2
- data/ldpath.gemspec +3 -2
- data/lib/ldpath.rb +7 -1
- data/lib/ldpath/loaders.rb +5 -0
- data/lib/ldpath/loaders/direct.rb +11 -0
- data/lib/ldpath/loaders/graph.rb +9 -0
- data/lib/ldpath/loaders/linked_data_fragment.rb +25 -0
- data/lib/ldpath/program.rb +14 -4
- data/lib/ldpath/result.rb +1 -7
- data/lib/ldpath/tests.rb +5 -2
- data/lib/ldpath/version.rb +1 -1
- data/spec/ldpath_program_spec.rb +53 -13
- metadata +27 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2392ccdedd0caa14ab3a6a9be74043156d66cda1
|
4
|
+
data.tar.gz: 25c171de64758510a076c32ee3fce37434707deb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fb33a6e0fe7af743f164ea41cee703c8a36f95ea216258297afd256b62e90da5d0b82c8c3aaf98eac4892118d6665abd647d68ff2f471874eb57cb108b0b924
|
7
|
+
data.tar.gz: 9b2f191ee2bdf62d775d3110d07752914a00b4b4aa48d9886b16d6d84acd6c702e25367760f61a87b5776b7d1766ee9446334e4a871d82b8ddddab995e2a52a3
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -8,6 +8,8 @@ This is a ruby implementation of [LDPath](http://marmotta.apache.org/ldpath/lang
|
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
11
|
+
### Required gem installation
|
12
|
+
|
11
13
|
Add this line to your application's Gemfile:
|
12
14
|
|
13
15
|
gem 'ldpath'
|
@@ -20,6 +22,10 @@ Or install it yourself as:
|
|
20
22
|
|
21
23
|
$ gem install ldpath
|
22
24
|
|
25
|
+
### Additional gem installations
|
26
|
+
|
27
|
+
To support RDF serializations, you will need to either install the [linkeddata gem](https://github.com/ruby-rdf/linkeddata) which installs a large set of RDF serializations or, in order to have a smaller dependency footprint, install gems for only the serializations your plan to use in your app. The list of serializations are in the [README](https://github.com/ruby-rdf/linkeddata/blob/develop/README.md#features) for the linkeddata gem.
|
28
|
+
|
23
29
|
## Usage
|
24
30
|
|
25
31
|
```ruby
|
@@ -35,10 +41,10 @@ uri = RDF::URI.new "info:a"
|
|
35
41
|
context = RDF::Graph.new << [uri, RDF::Vocab::DC.title, "Some Title"]
|
36
42
|
|
37
43
|
program = Ldpath::Program.parse my_program
|
38
|
-
output = program.evaluate uri, context
|
44
|
+
output = program.evaluate uri, context: context
|
39
45
|
# => { ... }
|
40
46
|
```
|
41
|
-
|
47
|
+
|
42
48
|
## Compatibility
|
43
49
|
|
44
50
|
* Ruby 2.5 or the latest 2.4 version is recommended. Later versions may also work.
|
data/ldpath.gemspec
CHANGED
@@ -18,10 +18,11 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
20
|
spec.add_dependency "parslet"
|
21
|
-
spec.add_dependency "
|
21
|
+
spec.add_dependency "rdf", '~> 3.0'
|
22
|
+
spec.add_dependency "nokogiri", "~> 1.8"
|
22
23
|
|
23
24
|
# spec.add_development_dependency "bixby", "~> 1.0.0"
|
24
|
-
spec.add_development_dependency "bundler", "~>
|
25
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
25
26
|
spec.add_development_dependency "byebug"
|
26
27
|
spec.add_development_dependency "rake"
|
27
28
|
spec.add_development_dependency "rspec"
|
data/lib/ldpath.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
require "ldpath/version"
|
2
|
-
require 'linkeddata'
|
3
2
|
require 'logger'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'rdf'
|
5
|
+
# require rdf/ntriples may not be necessary, may only really be necessary
|
6
|
+
# for ldpath_program_spec.rb tests, but I'm not certain, and I don't think it hurts
|
7
|
+
# to do it here.
|
8
|
+
require 'rdf/ntriples'
|
4
9
|
|
5
10
|
module Ldpath
|
6
11
|
require 'ldpath/field_mapping'
|
@@ -11,6 +16,7 @@ module Ldpath
|
|
11
16
|
require 'ldpath/functions'
|
12
17
|
require 'ldpath/program'
|
13
18
|
require 'ldpath/result'
|
19
|
+
require 'ldpath/loaders'
|
14
20
|
|
15
21
|
class << self
|
16
22
|
attr_writer :logger
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Ldpath::Loaders::Direct
|
2
|
+
def load(uri)
|
3
|
+
Ldpath.logger.debug "Loading #{uri.inspect}"
|
4
|
+
|
5
|
+
reader_types = RDF::Format.reader_types.reject { |t| t.to_s =~ /html/ }.map do |t|
|
6
|
+
t.to_s =~ %r{text/(?:plain|html)} ? "#{t};q=0.5" : t
|
7
|
+
end
|
8
|
+
|
9
|
+
RDF::Graph.load(uri, headers: { 'Accept' => reader_types.join(", ") })
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
class Ldpath::Loaders::LinkedDataFragment
|
4
|
+
NEXT_PAGE = RDF::URI('http://www.w3.org/ns/hydra/core#nextPage')
|
5
|
+
|
6
|
+
def initialize(endpoint)
|
7
|
+
@endpoint = endpoint
|
8
|
+
end
|
9
|
+
|
10
|
+
def load(uri)
|
11
|
+
Ldpath.logger.debug "Loading LDF data for #{uri.inspect}"
|
12
|
+
|
13
|
+
graph = RDF::Graph.new
|
14
|
+
request_uri = RDF::URI("#{@endpoint}?subject=#{CGI::escape(uri)}")
|
15
|
+
|
16
|
+
while request_uri
|
17
|
+
Ldpath.logger.debug " -- querying #{request_uri}"
|
18
|
+
request_graph = RDF::Graph.load(request_uri)
|
19
|
+
graph.insert_statements(request_graph)
|
20
|
+
request_uri = request_graph.first_object([request_uri, NEXT_PAGE, nil])
|
21
|
+
end
|
22
|
+
|
23
|
+
graph
|
24
|
+
end
|
25
|
+
end
|
data/lib/ldpath/program.rb
CHANGED
@@ -26,11 +26,14 @@ module Ldpath
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
attr_reader :mappings, :prefixes, :filters
|
30
|
-
def initialize(mappings,
|
29
|
+
attr_reader :mappings, :prefixes, :filters, :default_loader, :loaders
|
30
|
+
def initialize(mappings, default_loader: Ldpath::Loaders::Direct.new, prefixes: {}, filters: [], loaders: {})
|
31
31
|
@mappings ||= mappings
|
32
|
-
@
|
33
|
-
@
|
32
|
+
@default_loader = default_loader
|
33
|
+
@loaders = loaders
|
34
|
+
@prefixes = prefixes
|
35
|
+
@filters = filters
|
36
|
+
|
34
37
|
end
|
35
38
|
|
36
39
|
def evaluate(uri, context: nil, limit_to_context: false)
|
@@ -41,5 +44,12 @@ module Ldpath
|
|
41
44
|
|
42
45
|
result.to_hash
|
43
46
|
end
|
47
|
+
|
48
|
+
def load(uri)
|
49
|
+
loader = loaders.find { |k, v| uri =~ k }&.last
|
50
|
+
loader ||= default_loader
|
51
|
+
|
52
|
+
loader.load(uri)
|
53
|
+
end
|
44
54
|
end
|
45
55
|
end
|
data/lib/ldpath/result.rb
CHANGED
@@ -22,13 +22,7 @@ module Ldpath
|
|
22
22
|
|
23
23
|
def load_graph(uri)
|
24
24
|
cache[uri] ||= begin
|
25
|
-
|
26
|
-
|
27
|
-
reader_types = RDF::Format.reader_types.reject { |t| t.to_s =~ /html/ }.map do |t|
|
28
|
-
t.to_s =~ %r{text/(?:plain|html)} ? "#{t};q=0.5" : t
|
29
|
-
end
|
30
|
-
|
31
|
-
RDF::Graph.load(uri, headers: { 'Accept' => reader_types.join(", ") }).tap { loaded[uri] = true }
|
25
|
+
program.load(uri).tap { loaded[uri] = true }
|
32
26
|
end
|
33
27
|
end
|
34
28
|
|
data/lib/ldpath/tests.rb
CHANGED
@@ -8,11 +8,14 @@ module Ldpath
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def evaluate(program, uris, context)
|
11
|
+
return to_enum(:evaluate, program, uris, context) unless block_given?
|
12
|
+
|
11
13
|
entries = delegate.evaluate program, uris, context
|
12
14
|
entries.select do |uri|
|
13
|
-
enum_wrap(test.evaluate(program, uri, context)).any? do |x|
|
15
|
+
result = enum_wrap(test.evaluate(program, uri, context)).any? do |x|
|
14
16
|
x
|
15
17
|
end
|
18
|
+
yield uri if result
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -26,7 +29,7 @@ module Ldpath
|
|
26
29
|
def evaluate(_program, uri, _context)
|
27
30
|
return unless uri.literal?
|
28
31
|
|
29
|
-
uri if (lang == "none" && !uri.has_language?) || uri.language == lang
|
32
|
+
uri if (lang.to_s == "none" && !uri.has_language?) || uri.language.to_s == lang.to_s
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
data/lib/ldpath/version.rb
CHANGED
data/spec/ldpath_program_spec.rb
CHANGED
@@ -7,11 +7,13 @@ describe Ldpath::Program do
|
|
7
7
|
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
8
8
|
title = dcterms:title :: xsd:string ;
|
9
9
|
parent_title = dcterms:isPartOf / dcterms:title :: xsd:string ;
|
10
|
+
parent_title_en = dcterms:isPartOf / dcterms:title[@en] :: xsd:string ;
|
10
11
|
titles = dcterms:title | (dcterms:isPartOf / dcterms:title) | (^dcterms:isPartOf / dcterms:title) :: xsd:string ;
|
11
12
|
no_titles = dcterms:title & (dcterms:isPartOf / dcterms:title) & (^dcterms:isPartOf / dcterms:title) :: xsd:string ;
|
12
13
|
self = . :: xsd:string ;
|
13
14
|
wildcard = * ::xsd:string ;
|
14
15
|
child_title = ^dcterms:isPartOf / dcterms:title :: xsd:string ;
|
16
|
+
child_description_en = ^dcterms:isPartOf / dcterms:description[@en] :: xsd:string ;
|
15
17
|
recursive = (dcterms:isPartOf)* ;
|
16
18
|
en_description = dcterms:description[@en] ;
|
17
19
|
conditional = dcterms:isPartOf[dcterms:title] ;
|
@@ -46,16 +48,18 @@ EOF
|
|
46
48
|
graph << [parent, RDF::Vocab::DC.title, "Parent title"]
|
47
49
|
graph << [child, RDF::Vocab::DC.isPartOf, object]
|
48
50
|
graph << [child, RDF::Vocab::DC.title, "Child title"]
|
51
|
+
graph << [parent, RDF::Vocab::DC.title, RDF::Literal.new("Parent English!", language: "en")]
|
52
|
+
graph << [parent, RDF::Vocab::DC.title, RDF::Literal.new("Parent French!", language: "fr")]
|
49
53
|
graph << [parent, RDF::Vocab::DC.isPartOf, grandparent]
|
50
54
|
|
51
55
|
result = subject.evaluate object, context: graph
|
52
|
-
|
53
56
|
expect(result["title"]).to match_array "Hello, world!"
|
54
|
-
expect(result["parent_title"]).to match_array "Parent title"
|
57
|
+
expect(result["parent_title"]).to match_array ["Parent title", "Parent English!", "Parent French!"]
|
58
|
+
expect(result["parent_title_en"]).to match_array "Parent English!"
|
55
59
|
expect(result["self"]).to match_array(object)
|
56
60
|
expect(result["wildcard"]).to include "Hello, world!", parent
|
57
61
|
expect(result["child_title"]).to match_array "Child title"
|
58
|
-
expect(result["titles"]).to match_array ["Hello, world!", "Parent title", "Child title"]
|
62
|
+
expect(result["titles"]).to match_array ["Hello, world!", "Parent title", "Child title", "Parent English!", "Parent French!"]
|
59
63
|
expect(result["no_titles"]).to be_empty
|
60
64
|
expect(result["recursive"]).to match_array [parent, grandparent]
|
61
65
|
expect(result["en_description"].first.to_s).to eq "English!"
|
@@ -185,20 +189,56 @@ EOF
|
|
185
189
|
|
186
190
|
describe "Data loading" do
|
187
191
|
subject do
|
188
|
-
Ldpath::Program.parse <<-EOF
|
189
|
-
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
190
|
-
title = foaf:primaryTopic / dc:title :: xsd:string ;
|
191
|
-
EOF
|
192
|
+
Ldpath::Program.parse <<-EOF, context
|
193
|
+
@prefix dcterms : <http://purl.org/dc/terms/> ;
|
194
|
+
title = foaf:primaryTopic / dc:title :: xsd:string ;
|
195
|
+
EOF
|
192
196
|
end
|
197
|
+
let(:context) { {} }
|
193
198
|
|
194
|
-
|
195
|
-
|
196
|
-
|
199
|
+
context 'with direct loading' do
|
200
|
+
let(:context) { { default_loader: Ldpath::Loaders::Direct.new }}
|
201
|
+
|
202
|
+
before do
|
203
|
+
stub_request(:get, 'http://www.bbc.co.uk/programmes/b0081dq5')
|
204
|
+
.to_return(status: 200, body: webmock_fixture('bbc_b0081dq5.nt'), headers: { 'Content-Type' => 'application/n-triples' })
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should work" do
|
208
|
+
result = subject.evaluate RDF::URI.new("http://www.bbc.co.uk/programmes/b0081dq5")
|
209
|
+
expect(result["title"]).to match_array "Huw Stephens"
|
210
|
+
end
|
197
211
|
end
|
198
212
|
|
199
|
-
|
200
|
-
|
201
|
-
|
213
|
+
context 'with an existing graph' do
|
214
|
+
let(:graph) { RDF::Graph.new }
|
215
|
+
let(:graph_loader) { Ldpath::Loaders::Graph.new graph: graph }
|
216
|
+
let(:context) { { default_loader: graph_loader }}
|
217
|
+
|
218
|
+
before do
|
219
|
+
graph << [RDF::URI('http://www.bbc.co.uk/programmes/b0081dq5'), RDF::URI('http://xmlns.com/foaf/0.1/primaryTopic'), RDF::URI('info:some_uri')]
|
220
|
+
graph << [RDF::URI('info:some_uri'), RDF::URI('http://purl.org/dc/elements/1.1/title'), 'Local Huw Stephens']
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should work" do
|
224
|
+
result = subject.evaluate RDF::URI.new("http://www.bbc.co.uk/programmes/b0081dq5")
|
225
|
+
expect(result["title"]).to match_array "Local Huw Stephens"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context 'with linked data fragments' do
|
230
|
+
let(:graph_loader) { Ldpath::Loaders::LinkedDataFragment.new('http://example.com/ldf') }
|
231
|
+
let(:context) { { default_loader: graph_loader }}
|
232
|
+
|
233
|
+
before do
|
234
|
+
stub_request(:get, 'http://example.com/ldf?subject=http://www.bbc.co.uk/programmes/b0081dq5')
|
235
|
+
.to_return(status: 200, body: webmock_fixture('bbc_b0081dq5.nt'), headers: { 'Content-Type' => 'application/n-triples' })
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should work" do
|
239
|
+
result = subject.evaluate RDF::URI.new("http://www.bbc.co.uk/programmes/b0081dq5")
|
240
|
+
expect(result["title"]).to match_array "Huw Stephens"
|
241
|
+
end
|
202
242
|
end
|
203
243
|
end
|
204
244
|
|
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: 1.0
|
4
|
+
version: 1.1.0
|
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: 2020-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parslet
|
@@ -25,33 +25,47 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: rdf
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
33
|
+
version: '3.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nokogiri
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.8'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.8'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: bundler
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
61
|
+
version: '2.0'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '2.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: byebug
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -176,6 +190,10 @@ files:
|
|
176
190
|
- lib/ldpath.rb
|
177
191
|
- lib/ldpath/field_mapping.rb
|
178
192
|
- lib/ldpath/functions.rb
|
193
|
+
- lib/ldpath/loaders.rb
|
194
|
+
- lib/ldpath/loaders/direct.rb
|
195
|
+
- lib/ldpath/loaders/graph.rb
|
196
|
+
- lib/ldpath/loaders/linked_data_fragment.rb
|
179
197
|
- lib/ldpath/parser.rb
|
180
198
|
- lib/ldpath/program.rb
|
181
199
|
- lib/ldpath/result.rb
|