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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 154cc858a4b03022c48012acdb9e897c105a7c3f
4
- data.tar.gz: 5c99156666f615486d5b8134bcd869e0f9b44590
3
+ metadata.gz: feb1911da55e6e56d33cb8bccea249060b59f7da
4
+ data.tar.gz: 87eab8d2813362a18c9ff45707325542f45ec657
5
5
  SHA512:
6
- metadata.gz: 6a9879ef3a8345d8c0a5c82ab79b048c9143cd1da9c33b5d53e8940d54187666723c9c67f5114efa9d7e2485aa4c28e8d63c2d43919571f8f955169485106fb2
7
- data.tar.gz: 81f9a84ff7d8a761327c833b8acd6a1ff96403c3e512c02fa6c060755817aab69d9382bcaa3782048a2d1d6c7c983528a155b2554a961c71fe4bb711d0fb7d6b
6
+ metadata.gz: 111dbf2d32a03ab3199d622f1ea78c94322a24733e0120c537ed43d2f42c592e650ab72e67f067cf6578d4be2ddcdbfd6756d09369c2e9d8c1fb7757f7624bb2
7
+ data.tar.gz: 5dc5e8488936d2d14114522cb1880a05e165edc317b6a433b247dff8e235af989419a7fac28b71a8f5741da7a8d0b2b33c3e6d10179a0a3b830461ff748a970e
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in ldpath.gemspec
4
4
  gemspec
5
+
data/ldpath.gemspec CHANGED
@@ -23,4 +23,5 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "bundler", "~> 1.5"
24
24
  spec.add_development_dependency "rake"
25
25
  spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "rdf-reasoner"
26
27
  end
@@ -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
 
@@ -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 !context.has_subject?(uri)
32
- @cache[uri] ||= RDF::Graph.load(uri)
33
- context << @cache[uri]
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 ||= RDF::Graph.load uri.to_s
51
+ context ||= load_graph(uri.to_s)
40
52
 
41
53
  mappings.each do |m|
42
- h[m.name] = case m.selector
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
@@ -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, *arguments
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
@@ -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
 
@@ -1,3 +1,3 @@
1
1
  module Ldpath
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
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
@@ -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
@@ -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
- title = fn:concat("a", "b") ;
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["title"]).to match_array "ab"
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
@@ -1,2 +1,7 @@
1
1
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
2
  require 'ldpath'
3
+
4
+ require 'rdf/reasoner'
5
+
6
+ RDF::Reasoner.apply(:rdfs)
7
+ RDF::Reasoner.apply(:owl)
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.1
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: 2014-07-21 00:00:00.000000000 Z
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.2.2
149
+ rubygems_version: 2.4.5
136
150
  signing_key:
137
151
  specification_version: 4
138
152
  summary: Ruby implementation of LDPath