ldpath 0.0.2 → 0.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: feb1911da55e6e56d33cb8bccea249060b59f7da
4
- data.tar.gz: 87eab8d2813362a18c9ff45707325542f45ec657
3
+ metadata.gz: 76772761e5cb85b3f0d16df78e8673524dd4849b
4
+ data.tar.gz: 292da39f546dd6151e6754a060ffadf9464df44d
5
5
  SHA512:
6
- metadata.gz: 111dbf2d32a03ab3199d622f1ea78c94322a24733e0120c537ed43d2f42c592e650ab72e67f067cf6578d4be2ddcdbfd6756d09369c2e9d8c1fb7757f7624bb2
7
- data.tar.gz: 5dc5e8488936d2d14114522cb1880a05e165edc317b6a433b247dff8e235af989419a7fac28b71a8f5741da7a8d0b2b33c3e6d10179a0a3b830461ff748a970e
6
+ metadata.gz: 536f06a5bb004c85e76ff303cc39cb27204bb853126eb18049e98d9b5bd64e16aa477cc1b1be8314f0ea199fdbd0c186f2b89fb150c3aa45f3e293c339c1c949
7
+ data.tar.gz: a3914cc93b8b07c9086ecaac7d8a12502cbcb5dfd4a02dd916163ccd92bc8e740176a5379ecc3ddb5904eeb01318f80359dc178673f18a4f838d5a7a6eef6447
data/README.md CHANGED
@@ -37,7 +37,7 @@ output = program.evaluate uri, context
37
37
 
38
38
  ## Contributing
39
39
 
40
- 1. Fork it ( http://github.com/<my-github-username>/ldpath/fork )
40
+ 1. Fork it ( http://github.com/cbeer/ldpath.rb/fork )
41
41
  2. Create your feature branch (`git checkout -b my-new-feature`)
42
42
  3. Commit your changes (`git commit -am 'Add some feature'`)
43
43
  4. Push to the branch (`git push origin my-new-feature`)
data/bin/ldpath ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'open-uri'
5
+ require 'ldpath'
6
+ require 'byebug'
7
+
8
+ begin
9
+ require 'rest-client'
10
+ rescue LoadError
11
+ end
12
+
13
+ options = {}
14
+ OptionParser.new do |opts|
15
+ opts.banner = "Usage: ldpath [options] URI"
16
+
17
+ opts.on("--program=STRING_URI_OR_FILE", "LDPath program to run (- for STDIN)") do |program|
18
+ if File.exists? program or program =~ /^http/
19
+ options[:program] = open(program).read
20
+ elsif program.strip == "-"
21
+ options[:program] = $stdin.read
22
+ else
23
+ options[:program] = program
24
+ end
25
+ end
26
+ end.parse!
27
+
28
+ uri = ARGV.shift
29
+
30
+ puts Ldpath::Program.parse(options[:program]).evaluate(RDF::URI.new(uri)).to_json
data/ldpath.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Chris Beer"]
10
10
  spec.email = ["cabeer@stanford.edu"]
11
11
  spec.summary = %q{Ruby implementation of LDPath}
12
- spec.homepage = "http://github.com/cbeer"
12
+ spec.homepage = "https://github.com/cbeer/ldpath.rb"
13
13
  spec.license = "Apache 2"
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0")
@@ -1,7 +1,7 @@
1
1
  module Ldpath
2
2
  module Functions
3
3
  def concat uri, context, *args
4
- args.join
4
+ args.flatten.compact.join
5
5
  end
6
6
 
7
7
  def first uri, context, *args
@@ -11,29 +11,57 @@ module Ldpath
11
11
  def last uri, context, *args
12
12
  args.flatten.compact.last
13
13
  end
14
+
15
+ def count uri, context, *args
16
+ args.flatten.compact.length
17
+ end
14
18
 
15
19
  def eq uri, context, *args
16
-
20
+ a, b, *rem = args.flatten
21
+ unless rem.empty?
22
+ raise "Too many arguments to fn:eq"
23
+ end
24
+ a == b
17
25
  end
18
26
 
19
27
  def ne uri, context, *args
20
-
28
+ a, b, *rem = args.flatten
29
+ unless rem.empty?
30
+ raise "Too many arguments to fn:ne"
31
+ end
32
+ a != b
21
33
  end
22
34
 
23
35
  def lt uri, context, *args
24
-
36
+ a, b, *rem = args.flatten
37
+ unless rem.empty?
38
+ raise "Too many arguments to fn:lt"
39
+ end
40
+ a < b
25
41
  end
26
42
 
27
43
  def le uri, context, *args
28
-
44
+ a, b, *rem = args.flatten
45
+ unless rem.empty?
46
+ raise "Too many arguments to fn:le"
47
+ end
48
+ a <= b
29
49
  end
30
50
 
31
51
  def gt uri, context, *args
32
-
52
+ a, b, *rem = args.flatten
53
+ unless rem.empty?
54
+ raise "Too many arguments to fn:gt"
55
+ end
56
+ a > b
33
57
  end
34
58
 
35
59
  def ge uri, context, *args
36
-
60
+ a, b, *rem = args.flatten
61
+ unless rem.empty?
62
+ raise "Too many arguments to fn:ge"
63
+ end
64
+ a >= b
37
65
  end
38
66
 
39
67
  # collections
@@ -130,7 +158,6 @@ module Ldpath
130
158
  end
131
159
 
132
160
  def endsWith uri, context, str, suffix
133
-
134
161
  Array(str).map { |x| x.end_with? suffix }
135
162
  end
136
163
 
@@ -141,6 +168,13 @@ module Ldpath
141
168
  def predicates uri, context, *args
142
169
  context.query([uri, nil, nil]).map(&:predicate).uniq
143
170
  end
171
+
172
+ def xpath uri, context, xpath, node
173
+ x = Array(xpath).flatten.first
174
+ Array(node).flatten.compact.map do |n|
175
+ Nokogiri::XML(n).xpath(x, prefixes.map { |k,v| [k, v.to_s] }).map(&:text)
176
+ end
177
+ end
144
178
 
145
179
  end
146
180
  end
data/lib/ldpath/parser.rb CHANGED
@@ -4,15 +4,21 @@ module Ldpath
4
4
  class Parser < Parslet::Parser
5
5
  root :lines
6
6
  rule(:lines) { line.repeat }
7
- rule(:line) { expression >> wsp? >> (newline | eof) }
7
+ rule(:line) { ((wsp >> expression) | expression) >> space_not_newline? >> (newline | eof) }
8
8
 
9
9
  rule(:newline) { (str("\n") >> str("\r").maybe).repeat(1) }
10
10
  rule(:eof) { any.absent? }
11
- rule(:wsp) { (match["\\t "] | multiline_comment).repeat(1) }
11
+
12
+ rule(:space) { match('\s').repeat(1) }
13
+ rule(:spaces?) { space.maybe }
14
+ rule(:space_not_newline) { str("\n").absent? >> space }
15
+ rule(:space_not_newline?) { space_not_newline.maybe }
16
+
17
+ rule(:wsp) { (space | multiline_comment).repeat(1) }
12
18
  rule(:wsp?) { wsp.maybe }
13
19
  rule(:multiline_comment) { (str('/*') >> (str('*/').absent? >> any).repeat >> str('*/') ) }
14
20
 
15
- rule(:expression) { wsp | namespace | mapping | graph }
21
+ rule(:expression) { wsp | namespace | mapping | graph | filter | boost }
16
22
 
17
23
  rule(:int) { match("\\d+") }
18
24
 
@@ -23,6 +29,8 @@ module Ldpath
23
29
  rule(:assign) { str("=") }
24
30
  rule(:k_prefix) { str("@prefix")}
25
31
  rule(:k_graph) { str("@graph")}
32
+ rule(:k_filter) { str("@filter")}
33
+ rule(:k_boost) { str("@boost")}
26
34
 
27
35
  rule(:self_op) { str(".") }
28
36
  rule(:and_op) { str("&") }
@@ -57,9 +65,7 @@ module Ldpath
57
65
  rule(:identifier) { match["a-zA-Z0-9_"] >> (match["a-zA-Z0-9_'\\.-"]).repeat }
58
66
 
59
67
  rule(:strlit) {
60
- wsp? >>
61
- str('"') >> (str("\\") >> str("\"") | (str('"').absent? >> any)).repeat.as(:literal) >> str('"') >>
62
- wsp?
68
+ str('"') >> (str("\\") >> str("\"") | (str('"').absent? >> any)).repeat.as(:literal) >> str('"')
63
69
  }
64
70
 
65
71
  rule(:node) {
@@ -69,24 +75,20 @@ module Ldpath
69
75
  # @prefix id = uri ;
70
76
  rule(:namespace) {
71
77
  (
72
- wsp? >>
73
78
  k_prefix >> wsp? >>
74
79
  identifier.as(:id) >> wsp? >>
75
80
  colon >> wsp? >>
76
- uri.as(:uri) >> wsp? >>
77
- scolon.maybe >> wsp?
81
+ uri.as(:uri) >> space_not_newline? >> scolon.maybe
78
82
  ).as(:namespace)
79
83
  }
80
84
 
81
85
  # @graph uri, uri, uri ;
82
86
  rule(:graph) {
83
87
  k_graph >> wsp? >>
84
- uri_list.as(:graphs) >> wsp? >>
85
- scolon
88
+ uri_list.as(:graphs) >> wsp? >> scolon
86
89
  }
87
90
 
88
91
  rule(:uri_list) {
89
- wsp? >>
90
92
  uri.as(:uri) >>
91
93
  (
92
94
  wsp? >>
@@ -94,22 +96,41 @@ module Ldpath
94
96
  uri_list.as(:rest)
95
97
  ).repeat
96
98
  }
99
+
100
+ # @filter test ;
101
+ rule(:filter) {
102
+ (k_filter >> wsp? >> node_test.as(:test) >> wsp? >> scolon).as(:filter)
103
+ }
104
+
105
+ # @boost selector ;
106
+ rule(:boost) {
107
+ (k_boost >> wsp? >> selector.as(:selector) >> wsp? >> scolon).as(:boost)
108
+ }
97
109
 
98
110
  # id = . ;
99
111
  rule(:mapping) {
100
112
  (
101
- identifier.as(:name) >> wsp? >>
113
+ (uri_in_brackets | prefix_and_localname | identifier).as(:name) >> wsp? >>
102
114
  assign >> wsp? >>
103
- selector.as(:selector) >> wsp? >>
104
- (
105
- dcolon >> wsp? >>
106
- uri.as(:field_type)
107
- ).maybe >> wsp? >>
108
- scolon
115
+ selector.as(:selector) >>
116
+ ( wsp? >>
117
+ dcolon >> wsp? >> field_type
118
+ ).maybe >> wsp? >> scolon
109
119
  ).as(:mapping)
110
120
  }
111
121
 
122
+ rule(:field_type) {
123
+ uri.as(:field_type) >> field_type_options.maybe
124
+ }
125
+
126
+ rule(:field_type_options) {
127
+ str("(") >> wsp? >> (field_type_option >> (wsp? >> comma >> wsp? >> field_type_option).repeat).as(:options) >> wsp? >> str(")")
128
+ }
112
129
 
130
+ rule(:field_type_option) {
131
+ identifier.as(:key) >> wsp? >> assign >> wsp? >> strlit.as(:value)
132
+ }
133
+
113
134
  # selector groups
114
135
  rule(:selector) {
115
136
  (
@@ -128,11 +149,10 @@ module Ldpath
128
149
  }
129
150
 
130
151
  rule(:testing_selector) {
131
- wsp? >>
132
152
  atomic_selector.as(:delegate) >>
133
153
  str("[") >> wsp? >>
134
154
  node_test.as(:test) >> wsp? >>
135
- str("]") >> wsp?
155
+ str("]")
136
156
  }
137
157
 
138
158
  rule(:atomic_selector) {
@@ -163,80 +183,70 @@ module Ldpath
163
183
  ## x / y
164
184
  rule(:path_selector) {
165
185
  (
166
- wsp? >>
167
186
  atomic_or_testing_selector.as(:left) >> wsp? >>
168
187
  p_sep >> wsp? >>
169
- atomic_or_testing_or_path_selector.as(:right) >> wsp?
188
+ atomic_or_testing_or_path_selector.as(:right)
170
189
  ).as(:path)
171
190
  }
172
191
 
173
192
  ## x & y
174
193
  rule(:intersection_selector) {
175
194
  (
176
- wsp? >>
177
195
  atomic_or_testing_or_path_selector.as(:left) >> wsp? >>
178
196
  and_op >> wsp? >>
179
- selector.as(:right) >> wsp?
197
+ selector.as(:right)
180
198
  ).as(:intersection)
181
199
  }
182
200
 
183
201
  ## x | y
184
202
  rule(:union_selector) {
185
203
  (
186
- wsp? >>
187
204
  atomic_or_testing_or_path_selector.as(:left) >> wsp? >>
188
205
  or_op >> wsp? >>
189
- selector.as(:right) >> wsp?
206
+ selector.as(:right)
190
207
  ).as(:union)
191
208
  }
192
209
 
193
210
  # Atomic Selectors
194
211
  rule(:self_selector) {
195
- wsp? >>
196
- self_op.as(:self) >> wsp?
212
+ self_op.as(:self)
197
213
  }
198
214
 
199
215
  # fn:x() or fn:x(1,2,3)
200
216
  rule(:function_selector) {
201
217
  func >> identifier.as(:fname) >> str("()") |
202
- func >> identifier.as(:fname) >> str("(") >> arglist.as(:arglist) >> str(")")
218
+ func >> identifier.as(:fname) >> str("(") >> wsp? >> arglist.as(:arglist) >> wsp? >> str(")")
203
219
  }
204
220
 
205
221
  rule(:arglist) {
206
- wsp? >>
207
222
  selector >>
208
223
  (
209
224
  wsp? >>
210
225
  comma >> wsp? >>
211
226
  selector
212
- ).repeat >>
213
- wsp?
227
+ ).repeat
214
228
  }
215
229
 
216
230
  # xyz
217
231
  rule(:loose_property_selector) {
218
- wsp? >>
219
232
  loose >>
220
233
  wsp? >>
221
- uri.as(:loose_property) >> wsp?
234
+ uri.as(:loose_property)
222
235
  }
223
236
 
224
237
  # xyz
225
238
  rule(:property_selector) {
226
- wsp? >>
227
- uri.as(:property) >> wsp?
239
+ uri.as(:property)
228
240
  }
229
241
 
230
242
  # *
231
243
  rule(:wildcard_selector) {
232
- wsp? >>
233
- star.as(:wildcard) >> wsp?
244
+ star.as(:wildcard)
234
245
  }
235
246
 
236
247
  # ^xyz
237
248
  rule(:reverse_property_selector) {
238
- wsp? >>
239
- inverse >> uri.as(:reverse_property) >> wsp?
249
+ inverse >> uri.as(:reverse_property)
240
250
  }
241
251
 
242
252
  rule(:string_constant_selector) {
@@ -246,7 +256,6 @@ module Ldpath
246
256
  # (x)*
247
257
  rule(:recursive_path_selector) {
248
258
  (
249
- wsp? >>
250
259
  str("(") >> wsp? >>
251
260
  selector.as(:delegate) >> wsp? >>
252
261
  str(")") >>
@@ -254,23 +263,21 @@ module Ldpath
254
263
  star |
255
264
  plus |
256
265
  (str("{") >> wsp? >> int.as(:min).maybe >> wsp? >>str(",") >> wsp? >> int.as(:max).maybe >> wsp? >>str("}") ).as(:range)
257
- ).as(:repeat) >> wsp?
266
+ ).as(:repeat)
258
267
  ).as(:recursive)
259
268
  }
260
269
 
261
270
  rule(:grouped_selector) {
262
- wsp? >>
263
271
  str("(") >> wsp? >>
264
272
  selector >> wsp? >>
265
- str(")") >> wsp?
273
+ str(")")
266
274
  }
267
275
 
268
276
  rule(:tap_selector) {
269
- wsp? >>
270
277
  tap >>
271
- str("<") >>
272
- identifier.as(:identifier) >>
273
- str(">") >>
278
+ str("<") >> wsp? >>
279
+ identifier.as(:identifier) >> wsp? >>
280
+ str(">") >> wsp? >>
274
281
  (atomic_selector).as(:tap)
275
282
  }
276
283
 
@@ -294,78 +301,67 @@ module Ldpath
294
301
  }
295
302
 
296
303
  rule(:grouped_test) {
297
- wsp? >>
298
304
  str("(") >> wsp? >>
299
305
  node_test >> wsp? >>
300
- str(")") >> wsp?
306
+ str(")")
301
307
  }
302
308
 
303
309
  rule(:not_test) {
304
310
  (
305
- wsp? >>
306
- not_op >> node_test.as(:delegate) >>
307
- wsp?
311
+ not_op >> node_test.as(:delegate)
308
312
  ).as(:not)
309
313
  }
310
314
 
311
315
  rule(:and_test) {
312
316
  (
313
- wsp? >>
314
317
  atomic_node_test.as(:left) >> wsp? >>
315
318
  and_op >> wsp? >>
316
- node_test.as(:right) >> wsp?
319
+ node_test.as(:right)
317
320
  ).as(:and)
318
321
  }
319
322
 
320
323
  rule(:or_test) {
321
324
  (
322
- wsp? >>
323
325
  atomic_node_test.as(:left) >> wsp? >>
324
326
  or_op >> wsp? >>
325
- node_test.as(:right) >> wsp?
327
+ node_test.as(:right)
326
328
  ).as(:or)
327
329
  }
328
330
 
329
331
  # @en
330
332
  rule(:literal_language_test) {
331
- wsp? >>
332
- lang >> identifier.as(:lang) >>
333
- wsp?
333
+ lang >> identifier.as(:lang)
334
334
  }
335
335
 
336
336
  # ^^xyz
337
337
  rule(:literal_type_test) {
338
- wsp? >>
339
- type >> uri.as(:type) >>
340
- wsp?
338
+ type >> uri.as(:type)
341
339
  }
342
340
 
343
341
  rule(:is_a_test) {
344
342
  (
345
- wsp? >>
346
343
  is_a >> wsp? >>
347
- node.as(:right) >>
348
- wsp?
344
+ node.as(:right)
349
345
  ).as(:is_a)
350
346
  }
351
347
 
352
348
  rule(:path_equality_test) {
353
349
  (
354
- wsp? >>
355
350
  selector >> wsp? >>
356
351
  is >> wsp? >>
357
- node.as(:right) >> wsp?
352
+ node.as(:right)
358
353
  ).as(:is)
359
354
  }
360
355
 
361
356
  rule(:function_test) {
362
- wsp? >>
363
357
  (
364
358
  func >> identifier.as(:fname) >> str("()") |
365
359
  func >> identifier.as(:fname) >> str("(") >>
360
+ wsp? >>
366
361
  arglist.as(:arglist) >>
362
+ wsp? >>
367
363
  str(")")
368
- ) >> wsp?
364
+ )
369
365
  }
370
366
 
371
367
  rule(:path_test) {
@@ -8,7 +8,7 @@ module Ldpath
8
8
  parsed = parser.parse(program)
9
9
  ast = transform.apply parsed, transform_context
10
10
 
11
- Ldpath::Program.new ast.compact
11
+ Ldpath::Program.new ast.compact, transform_context
12
12
  end
13
13
 
14
14
  private
@@ -21,16 +21,19 @@ module Ldpath
21
21
  end
22
22
  end
23
23
 
24
- attr_reader :mappings, :cache, :loaded
25
- def initialize mappings, cache = RDF::Util::Cache.new
24
+ attr_reader :mappings, :cache, :loaded, :prefixes, :filters
25
+ def initialize mappings, options = {}
26
+
26
27
  @mappings ||= mappings
27
- @cache = cache
28
+ @cache = options[:cache] || RDF::Util::Cache.new
29
+ @prefixes = options[:prefixes] || {}
30
+ @filters = options[:filters] || []
28
31
  @loaded = {}
29
32
  end
30
33
 
31
34
  def loading uri, context
32
- if uri.to_s =~ /^http/ and !loaded[uri]
33
- context << load_graph(uri)
35
+ if uri.to_s =~ /^http/ and !loaded[uri.to_s]
36
+ context << load_graph(uri.to_s)
34
37
  end
35
38
  end
36
39
 
@@ -50,6 +53,10 @@ module Ldpath
50
53
  h = {}
51
54
  context ||= load_graph(uri.to_s)
52
55
 
56
+ unless filters.empty?
57
+ return h unless filters.all? { |f| f.evaluate(self, uri, context) }
58
+ end
59
+
53
60
  mappings.each do |m|
54
61
  h[m.name] ||= []
55
62
  h[m.name] += case m.selector
@@ -37,7 +37,7 @@ module Ldpath
37
37
  i
38
38
  end
39
39
  end
40
- program.func_call fname, uri, context, args
40
+ program.func_call fname, uri, context, *args
41
41
  end.flatten.compact
42
42
  end
43
43
  end
@@ -21,6 +21,7 @@ module Ldpath
21
21
 
22
22
  def apply obj, context = nil
23
23
  context ||= { }
24
+ context[:filters] ||= []
24
25
  context[:prefixes] ||= {}.merge(self.class.default_prefixes)
25
26
  super obj, context
26
27
  end
@@ -38,6 +39,17 @@ module Ldpath
38
39
  rule(prefix: simple(:prefix), localName: simple(:localName)) do
39
40
  (prefixes[prefix.to_s] || RDF::Vocabulary.new(prefix.to_s))[localName]
40
41
  end
42
+
43
+ rule(filter: subtree(:filter)) do
44
+ filters << filter[:test]
45
+ nil
46
+ end
47
+
48
+ rule(boost: subtree(:boost)) do
49
+ # no-op
50
+ nil
51
+ end
52
+
41
53
 
42
54
  # Mappings
43
55
 
@@ -1,3 +1,3 @@
1
1
  module Ldpath
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -19,11 +19,9 @@
19
19
 
20
20
  @graph test:context, foo:ctx, test:bar ;
21
21
 
22
- /*
23
22
  @filter test:type is foo:bar | test:p1 & is-a test:Case ;
24
23
 
25
24
  @boost foo:boost / ^test:boost ;
26
- */
27
25
 
28
26
  path = test:p1 / test:p2 :: test:type ;
29
27
  lang_test = test:p1[@en] :: test:type ;
@@ -34,8 +32,7 @@ group = (test:p1 / test:p2) :: test:type ;
34
32
 
35
33
  inverse = ^test:incoming :: test:type ;
36
34
 
37
- config = test:foo :: test:type ;
38
- /*
35
+ config = test:foo :: test:type(c1="true", c2="false", c3="1.234") ;
36
+
39
37
  foo:bar = test:foo :: test:type ;
40
- <http://test/> = test:test :: test:type ;
41
- */
38
+ <http://test/> = test:test :: test:type ;
@@ -64,6 +64,11 @@ describe Ldpath::Parser do
64
64
  subject.expression.parse "@graph test:context, foo:ctx, test:bar ;"
65
65
  end
66
66
 
67
+
68
+ it "may be a filter" do
69
+ subject.expression.parse "@filter is-a test:Context ;"
70
+ end
71
+
67
72
  it "may be a mapping" do
68
73
  subject.expression.parse "id = . ;"
69
74
  end
@@ -133,7 +138,7 @@ describe Ldpath::Parser do
133
138
  end
134
139
 
135
140
  it "should parse path mappings" do
136
- subject.parse("xyz = info:a / info:b :: a:b;\n")
141
+ subject.mapping.parse("xyz = info:a / info:b :: a:b;")
137
142
  end
138
143
 
139
144
  it "recursive_path_selector" do
@@ -163,7 +168,7 @@ describe Ldpath::Parser do
163
168
  end
164
169
 
165
170
  it "should parse the namespaces.ldpath" do
166
- subject.parse File.read(File.expand_path(File.join(__FILE__, "..", "fixtures", "namespaces.ldpath")))
171
+ subject.parse_with_debug File.read(File.expand_path(File.join(__FILE__, "..", "fixtures", "namespaces.ldpath")))
167
172
  end
168
173
  end
169
174
  end
@@ -72,33 +72,114 @@ EOF
72
72
  end
73
73
 
74
74
  describe "functions" do
75
-
76
- subject do
77
- Ldpath::Program.parse <<-EOF
75
+ let(:program) do
76
+ Ldpath::Program.parse <<-EOF
78
77
  @prefix dcterms : <http://purl.org/dc/terms/> ;
79
78
  ab = fn:concat("a", "b") ;
80
79
  title = fn:concat(dcterms:title, dcterms:description) ;
80
+ title_mix = fn:concat("!", dcterms:title) ;
81
+ title_missing = fn:concat("z", dcterms:genre) ;
81
82
  first_a = fn:first("a", "b") ;
83
+ first_b = fn:first(dcterms:genre, "b") ;
84
+ last_a = fn:last("a", dcterms:genre) ;
82
85
  last_b = fn:last("a", "b") ;
86
+ count_5 = fn:count("a", "b", "c", "d", "e");
87
+ count_3 = fn:count(dcterms:hasPart);
88
+ count_still_3 = fn:count(dcterms:hasPart, dcterms:genre);
89
+ eq_true = fn:eq("a", "a");
90
+ eq_false = fn:eq("a", "b");
91
+ eq_node_true = fn:eq(dcterms:description, "Description");
92
+ xpath_test = fn:xpath("//title", "<root><title>xyz</title></root>");
83
93
  EOF
94
+ end
95
+
96
+ let(:object) { RDF::URI.new("info:a") }
97
+
98
+ let(:graph) do
99
+ graph = RDF::Graph.new
100
+ graph << [object, RDF::DC.title, "Hello, world!"]
101
+ graph << [object, RDF::DC.description, "Description"]
102
+ graph << [object, RDF::DC.hasPart, "a"]
103
+ graph << [object, RDF::DC.hasPart, "b"]
104
+ graph << [object, RDF::DC.hasPart, "c"]
105
+
106
+ graph
107
+ end
108
+
109
+ subject do
110
+ program.evaluate object, graph
111
+ end
112
+
113
+ describe "concat" do
114
+ it "should concatenate simple string arguments" do
115
+ expect(subject).to include "ab" => ["ab"]
84
116
  end
85
117
 
86
- let(:object) { RDF::URI.new("info:a") }
87
-
88
- let(:graph) do
89
- graph = RDF::Graph.new
90
- graph << [object, RDF::DC.title, "Hello, world!"]
91
- graph << [object, RDF::DC.description, "Description"]
118
+ it "should concatenate node values" do
119
+ expect(subject).to include "title" => ["Hello, world!Description"]
120
+ end
92
121
 
93
- graph
122
+ it "should allow a mixture of string and node values" do
123
+ expect(subject).to include "title_mix" => ["!Hello, world!"]
124
+ end
125
+
126
+ it "should ignore missing node values" do
127
+ expect(subject).to include "title_missing" => ["z"]
128
+ end
129
+ end
130
+
131
+ describe "first" do
132
+ it "should take the first value" do
133
+ expect(subject).to include "first_a" => ["a"]
134
+ end
135
+
136
+ it "should skip missing values" do
137
+ expect(subject).to include "first_b" => ["b"]
138
+ end
139
+ end
140
+
141
+ describe "last" do
142
+ it "should take the last value" do
143
+ expect(subject).to include "last_b" => ["b"]
144
+ end
145
+
146
+ it "should skip missing values" do
147
+ expect(subject).to include "last_a" => ["a"]
148
+ end
149
+ end
150
+
151
+ describe "count" do
152
+ it "should return the number of arguments" do
153
+ expect(subject).to include "count_5" => [5]
154
+ end
155
+
156
+ it "should count the number of values for nodes" do
157
+ expect(subject).to include "count_3" => [3]
158
+ end
159
+
160
+ it "should skip missing nodes" do
161
+ expect(subject).to include "count_still_3" => [3]
162
+ end
163
+ end
164
+
165
+ describe "eq" do
166
+ it "checks if the arguments match" do
167
+ expect(subject).to include "eq_true" => [true]
168
+ end
169
+
170
+ it "checks if the arguments fail to match" do
171
+ expect(subject).to include "eq_false" => [false]
172
+ end
173
+
174
+ it "checks node values" do
175
+ expect(subject).to include "eq_node_true" => [true]
176
+ end
177
+ end
178
+
179
+ describe "xpath" do
180
+ it "evaluates xpath queries against the string contents" do
181
+ expect(subject).to include "xpath_test" => ["xyz"]
94
182
  end
95
-
96
- it "should work" do
97
- result = subject.evaluate object, graph
98
- expect(result["ab"]).to match_array "ab"
99
- expect(result["title"]).to match_array "Hello, world!Description"
100
- expect(result["first_a"]).to match_array "a"
101
- expect(result["last_b"]).to match_array "b"
102
183
  end
103
184
  end
104
185
 
@@ -192,4 +273,42 @@ title_with_loose = ~dc:title :: xsd:string ;
192
273
  expect(result["title_with_loose"]).to eq result["title"]
193
274
  end
194
275
  end
276
+
277
+ describe "filter" do
278
+
279
+ subject do
280
+ Ldpath::Program.parse <<-EOF
281
+ @prefix dcterms : <http://purl.org/dc/terms/> ;
282
+ @prefix dc: <http://purl.org/dc/elements/1.1/> ;
283
+ @filter is-a dcterms:Agent ;
284
+ title = dcterms:title :: xsd:string ;
285
+ EOF
286
+ end
287
+
288
+ let(:object) { RDF::URI.new("info:a") }
289
+ let(:other_object) { RDF::URI.new("info:b") }
290
+
291
+
292
+ let(:graph) do
293
+ graph = RDF::Graph.new
294
+
295
+ graph << [object, RDF.type, RDF::DC.Agent]
296
+ graph << [object, RDF::DC.title, "Title"]
297
+ graph << [other_object, RDF::DC.title, "Other Title"]
298
+
299
+ graph
300
+ end
301
+
302
+ it "should work" do
303
+ result = subject.evaluate object, graph
304
+ expect(result["title"]).to eq ["Title"]
305
+ end
306
+
307
+ it "filters objects that don't match" do
308
+ result = subject.evaluate other_object, graph
309
+ expect(result).to be_empty
310
+ end
311
+
312
+
313
+ end
195
314
  end
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.2
4
+ version: 0.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: 2015-04-02 00:00:00.000000000 Z
11
+ date: 2015-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet
@@ -97,7 +97,8 @@ dependencies:
97
97
  description:
98
98
  email:
99
99
  - cabeer@stanford.edu
100
- executables: []
100
+ executables:
101
+ - ldpath
101
102
  extensions: []
102
103
  extra_rdoc_files: []
103
104
  files:
@@ -108,6 +109,7 @@ files:
108
109
  - LICENSE.txt
109
110
  - README.md
110
111
  - Rakefile
112
+ - bin/ldpath
111
113
  - ldpath.gemspec
112
114
  - lib/ldpath.rb
113
115
  - lib/ldpath/field_mapping.rb
@@ -126,7 +128,7 @@ files:
126
128
  - spec/ldpath_spec.rb
127
129
  - spec/ldpath_transform_spec.rb
128
130
  - spec/spec_helper.rb
129
- homepage: http://github.com/cbeer
131
+ homepage: https://github.com/cbeer/ldpath.rb
130
132
  licenses:
131
133
  - Apache 2
132
134
  metadata: {}
@@ -146,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
148
  version: '0'
147
149
  requirements: []
148
150
  rubyforge_project:
149
- rubygems_version: 2.4.5
151
+ rubygems_version: 2.4.6
150
152
  signing_key:
151
153
  specification_version: 4
152
154
  summary: Ruby implementation of LDPath