ldpath 0.0.1 → 0.0.2

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