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 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