ldpath 1.0.1 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e53eb301f84470c0c8d0456bf6df5a22353ebae4
4
- data.tar.gz: 01a7107da855d02ba8b986a46307b9f6ecf15592
3
+ metadata.gz: 2392ccdedd0caa14ab3a6a9be74043156d66cda1
4
+ data.tar.gz: 25c171de64758510a076c32ee3fce37434707deb
5
5
  SHA512:
6
- metadata.gz: b7696726fe30696485975e88d86a694f497b9c9bf734c969734d934ceccd4c5b87db30e0ebfc495aa32a4b51d8b271b8f6d06f7f99bf92ce9a44ce58770c2fcb
7
- data.tar.gz: 405272b9be017a205da44e17e545aaf918184f5cc7dc42b9696ec197a5c23a3513eba089a3a3e5939623a067af32e245ca4e8e98edd1df9209956b005d0daea6
6
+ metadata.gz: 7fb33a6e0fe7af743f164ea41cee703c8a36f95ea216258297afd256b62e90da5d0b82c8c3aaf98eac4892118d6665abd647d68ff2f471874eb57cb108b0b924
7
+ data.tar.gz: 9b2f191ee2bdf62d775d3110d07752914a00b4b4aa48d9886b16d6d84acd6c702e25367760f61a87b5776b7d1766ee9446334e4a871d82b8ddddab995e2a52a3
@@ -3,4 +3,6 @@ rvm:
3
3
  - 2.4.5
4
4
  - 2.5.3
5
5
  before_install:
6
- - gem update --system
6
+ # cause ruby 2.5 doesn't come with bundler 2.x, which our
7
+ # gemspec now asks for.
8
+ - gem install bundler
@@ -1,3 +1,8 @@
1
+ ### 1.1.0 (2020-01-21)
2
+
3
+ * replace linkeddata dependency with rdf and nokogiri
4
+ * update dependency on bundler to ~> 2.0
5
+
1
6
  ### 1.0.1 (2019-04-23)
2
7
 
3
8
  * remove version restriction for linkeddata dependency
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.
@@ -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 "linkeddata"
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", "~> 1.5"
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"
@@ -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,5 @@
1
+ class Ldpath::Loaders
2
+ require 'ldpath/loaders/direct'
3
+ require 'ldpath/loaders/graph'
4
+ require 'ldpath/loaders/linked_data_fragment'
5
+ end
@@ -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,9 @@
1
+ class Ldpath::Loaders::Graph
2
+ def initialize(graph:)
3
+ @graph = graph
4
+ end
5
+
6
+ def load(uri)
7
+ @graph
8
+ end
9
+ 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
@@ -26,11 +26,14 @@ module Ldpath
26
26
  end
27
27
  end
28
28
 
29
- attr_reader :mappings, :prefixes, :filters
30
- def initialize(mappings, options = {})
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
- @prefixes = options[:prefixes] || {}
33
- @filters = options[:filters] || []
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
@@ -22,13 +22,7 @@ module Ldpath
22
22
 
23
23
  def load_graph(uri)
24
24
  cache[uri] ||= begin
25
- Ldpath.logger.debug "[#{object_id}] Loading #{uri.inspect}"
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
 
@@ -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
 
@@ -1,3 +1,3 @@
1
1
  module Ldpath
2
- VERSION = '1.0.1'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
@@ -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
- 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' })
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
- it "should work" do
200
- result = subject.evaluate RDF::URI.new("http://www.bbc.co.uk/programmes/b0081dq5")
201
- expect(result["title"]).to match_array "Huw Stephens"
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.1
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: 2019-04-23 00:00:00.000000000 Z
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: linkeddata
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: '1.5'
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: '1.5'
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