rdf_context 0.5.0 → 0.5.1

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.
@@ -0,0 +1,236 @@
1
+ require File.join(File.dirname(__FILE__), 'abstract_serializer')
2
+
3
+ module RdfContext
4
+ # Serialize RDF graphs in NTriples format
5
+ class XmlSerializer < RecursiveSerializer
6
+ VALID_ATTRIBUTES = [:none, :untyped, :typed]
7
+
8
+ def initialize(graph)
9
+ super
10
+ @force_RDF_about = {}
11
+ end
12
+
13
+ # Serialize the graph
14
+ #
15
+ # @param [IO, StreamIO] stream:: Stream in which to place serialized graph
16
+ # @param [Hash] options:: Options for parser
17
+ # <em>options[:base]</em>:: Base URI of graph, used to shorting URI references
18
+ # <em>options[:max_depth]</em>:: Maximum depth for recursively defining resources, defaults to 3
19
+ # <em>options[:lang]</em>:: Output as root xml:lang attribute, and avoid generation xml:lang where possible
20
+ # <em>options[:attributes]</em>:: How to use XML attributes when serializing, one of :none, :untyped, :typed. The default is none.
21
+ #
22
+ # -- Serialization Examples
23
+ # attributes == :none
24
+ #
25
+ # serialize(io, :attributes => none)
26
+ def serialize(stream, options = {})
27
+ @max_depth = options[:max_depth] || 3
28
+ @base = options[:base]
29
+ @lang = options[:lang]
30
+ @attributes = options[:attributes] || :none
31
+ raise "Invalid attribute option '#{@attributes}', should be one of #{VALID_ATTRIBUTES.to_sentence}" unless VALID_ATTRIBUTES.include?(@attributes.to_sym)
32
+
33
+ doc = Nokogiri::XML::Document.new
34
+
35
+ preprocess
36
+
37
+ predicates = @graph.predicates.uniq
38
+ possible = predicates | @graph.objects.uniq
39
+ namespaces = {}
40
+ required_namespaces = {}
41
+ possible.each do |res|
42
+ next unless res.is_a?(URIRef)
43
+ if !get_qname(res) # Creates Namespace mappings
44
+ [RDF_NS, DC_NS, OWL_NS, LOG_NS, RDF_NS, RDFS_NS, XHV_NS, XML_NS, XSD_NS, XSI_NS].each do |ns|
45
+ # Bind a standard namespace to the graph and try the lookup again
46
+ @graph.bind(ns) if ns.uri == res.base
47
+ required_namespaces[res.base] = true if !get_qname(res) && predicates.include?(res)
48
+ end
49
+ end
50
+ end
51
+ add_namespace(RDF_NS)
52
+ add_namespace(XML_NS) if @base || @lang
53
+
54
+ # See if there's a default namespace, and favor it when generating element names.
55
+ # Lookup an equivalent prefixed namespace for use in generating attributes
56
+ @default_ns = @graph.namespace("")
57
+ if @default_ns
58
+ add_namespace(@default_ns)
59
+ prefix = @graph.prefix(@default_ns.uri)
60
+ @prefixed_default_ns = @graph.namespace(prefix)
61
+ add_namespace(@prefixed_default_ns) if @prefixed_default_ns
62
+ end
63
+
64
+ # Add bindings for predicates not already having bindings
65
+ tmp_ns = "ns0"
66
+ required_namespaces.keys.each do |uri|
67
+ puts "serialize: create temporary namespace for <#{uri}>" if $DEBUG
68
+ add_namespace(Namespace.new(uri, tmp_ns))
69
+ tmp_ns = tmp_ns.succ
70
+ end
71
+
72
+ doc.root = Nokogiri::XML::Element.new("rdf:RDF", doc)
73
+ @namespaces.each_pair do |p, ns|
74
+ if p.to_s.empty?
75
+ doc.root.default_namespace = ns.uri.to_s
76
+ else
77
+ doc.root.add_namespace(p, ns.uri.to_s)
78
+ end
79
+ end
80
+ doc.root["xml:lang"] = @lang if @lang
81
+ doc.root["xml:base"] = @base if @base
82
+
83
+ # Add statements for each subject
84
+ order_subjects.each do |subject|
85
+ #puts "subj: #{subject.inspect}"
86
+ subject(subject, doc.root)
87
+ end
88
+
89
+ doc.write_xml_to(stream, :encoding => "UTF-8", :indent => 2)
90
+ end
91
+
92
+ protected
93
+ def subject(subject, parent_node)
94
+ node = nil
95
+
96
+ if !is_done?(subject)
97
+ subject_done(subject)
98
+ properties = @graph.properties(subject)
99
+ prop_list = sort_properties(properties)
100
+ puts "subject: #{subject.to_n3}, props: #{properties.inspect}" if $DEBUG
101
+
102
+ rdf_type, *rest = properties.fetch(RDF_TYPE.to_s, [])
103
+ properties[RDF_TYPE.to_s] = rest
104
+ if rdf_type.is_a?(URIRef)
105
+ element = get_qname(rdf_type)
106
+ if rdf_type.namespace && @default_ns && rdf_type.namespace.uri == @default_ns.uri
107
+ element = rdf_type.short_name
108
+ end
109
+ end
110
+ element ||= "rdf:Description"
111
+
112
+ node = Nokogiri::XML::Element.new(element, parent_node.document)
113
+
114
+ if subject.is_a?(BNode)
115
+ # Only need nodeID if it's referenced elsewhere
116
+ node["rdf:nodeID"] = subject.to_s if ref_count(subject) > (@depth == 0 ? 0 : 1)
117
+ else
118
+ node["rdf:about"] = relativize(subject)
119
+ end
120
+
121
+ prop_list.each do |prop|
122
+ prop_ref = URIRef.new(prop)
123
+
124
+ properties[prop].each do |object|
125
+ @depth += 1
126
+ predicate(prop_ref, object, node, properties[prop].length == 1)
127
+ @depth -= 1
128
+ end
129
+ end
130
+ elsif @force_RDF_about.include?(subject)
131
+ puts "subject: #{subject.to_n3}, force about" if $DEBUG
132
+ node = Nokogiri::XML::Element.new("rdf:Description", parent_node.document)
133
+ node["rdf:about"] = relativize(subject)
134
+ @force_RDF_about.delete(subject)
135
+ end
136
+
137
+ parent_node.add_child(node) if node
138
+ end
139
+
140
+ # Output a predicate into the specified node.
141
+ #
142
+ # If _is_unique_ is true, this predicate may be able to be serialized as an attribute
143
+ def predicate(prop, object, node, is_unique)
144
+ qname = prop.to_qname(uri_binding)
145
+
146
+ # See if we can serialize as attribute.
147
+ # * untyped attributes that aren't duplicated where xml:lang == @lang
148
+ # * typed attributes that aren't duplicated if @dt_as_attr is true
149
+ # * rdf:type
150
+ as_attr = false
151
+ as_attr ||= true if [:untyped, :typed].include?(@attributes) && prop == RDF_TYPE
152
+
153
+ # Untyped attribute with no lang, or whos lang is the same as the default and RDF_TYPE
154
+ as_attr ||= true if [:untyped, :typed].include?(@attributes) &&
155
+ (object.is_a?(Literal) && object.untyped? && (object.lang.nil? || object.lang == @lang))
156
+
157
+ as_attr ||= true if [:typed].include?(@attributes) && object.is_a?(Literal) && object.typed?
158
+
159
+ as_attr = false unless is_unique
160
+
161
+ # Can't do as an attr if the qname has no prefix and there is no prefixed version
162
+ if @default_ns && prop.namespace.uri == @default_ns.uri
163
+ if as_attr
164
+ if @prefixed_default_ns
165
+ qname = "#{@prefixed_default_ns.prefix}:#{prop.short_name}"
166
+ else
167
+ as_attr = false
168
+ end
169
+ else
170
+ qname = prop.short_name
171
+ end
172
+ end
173
+
174
+ puts "predicate: #{qname}, as_attr: #{as_attr}, object: #{object.inspect}, done: #{is_done?(object)}, sub: #{@subjects.include?(object)}" if $DEBUG
175
+ qname = "rdf:li" if qname.match(/rdf:_\d+/)
176
+ pred_node = Nokogiri::XML::Element.new(qname, node.document)
177
+
178
+ if object.is_a?(Literal) || is_done?(object) || !@subjects.include?(object)
179
+ # Literals or references to objects that aren't subjects, or that have already been serialized
180
+
181
+ args = object.xml_args
182
+ puts "predicate: args=#{args.inspect}" if $DEBUG
183
+ attrs = args.pop
184
+
185
+ if as_attr
186
+ # Serialize as attribute
187
+ pred_node.unlink
188
+ pred_node = nil
189
+ node[qname] = object.is_a?(URIRef) ? relativize(object) : object.to_s
190
+ else
191
+ # Serialize as element
192
+ attrs.each_pair do |a, av|
193
+ next if a == "xml:lang" && av == @lang # Lang already specified, don't repeat
194
+ av = relativize(object) if a == "#{RDF_NS.prefix}:resource"
195
+ puts " elt attr #{a}=#{av}" if $DEBUG
196
+ pred_node[a] = av.to_s
197
+ end
198
+ puts " elt #{'xmllit ' if object.is_a?(Literal) && object.xmlliteral?}content=#{args.first}" if $DEBUG && !args.empty?
199
+ if object.is_a?(Literal) && object.xmlliteral?
200
+ pred_node.add_child(Nokogiri::XML::CharacterData.new(args.first, node.document))
201
+ elsif args.first
202
+ pred_node.content = args.first unless args.empty?
203
+ end
204
+ end
205
+ else
206
+ # Check to see if it can be serialized as a collection
207
+ col = @graph.seq(object)
208
+ conformant_list = col.all? {|item| !item.is_a?(Literal)}
209
+ o_props = @graph.properties(object)
210
+ if conformant_list && o_props[RDF_NS.first.to_s]
211
+ # Serialize list as parseType="Collection"
212
+ pred_node["rdf:parseType"] = "Collection"
213
+ col.each do |item|
214
+ # Mark the BNode subject of each item as being complete, so that it is not serialized
215
+ @graph.triples(Triple.new(nil, RDF_NS.first, item)) do |triple, ctx|
216
+ subject_done(triple.subject)
217
+ end
218
+ @force_RDF_about[item] = true
219
+ subject(item, pred_node)
220
+ end
221
+ else
222
+ if @depth < @max_depth
223
+ @depth += 1
224
+ subject(object, pred_node)
225
+ @depth -= 1
226
+ elsif object.is_a?(BNode)
227
+ pred_node["rdf:nodeID"] = object.identifier
228
+ else
229
+ pred_node["rdf:resource"] = relativize(object)
230
+ end
231
+ end
232
+ end
233
+ node.add_child(pred_node) if pred_node
234
+ end
235
+ end
236
+ end
@@ -29,6 +29,7 @@ module RdfContext
29
29
 
30
30
  def destroy(configuration = {}); end
31
31
  def open(configuration = {}); end
32
+ def close(commit_pending_transactions = false); end
32
33
  def commit; end
33
34
  def rollback; end
34
35
 
@@ -252,7 +252,7 @@ module RdfContext
252
252
  end
253
253
 
254
254
  def size(context = nil)
255
- context = nil if context == @identifier || (context.respond_to?(:identifier) && context.identifier == @identifier)
255
+ context = nil if (context.respond_to?(:identifier) ? context.identifier : context) == @identifier
256
256
 
257
257
  triples(Triple.new(nil, nil, nil), context).length
258
258
  end
@@ -102,7 +102,7 @@ class String
102
102
  (?:\\[\\bfnrt"/]) # Escaped control characters, " and /
103
103
  |(?:\\U00\h{6}) # 6 byte escaped Unicode
104
104
  |(?:\\u\h{4}) # 4 byte escaped Unicode
105
- )xn
105
+ )x
106
106
  else
107
107
  UNESCAPE_RE = %r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n
108
108
  end
@@ -72,6 +72,10 @@ module RdfContext
72
72
  self.to_s == other.to_s
73
73
  end
74
74
  alias_method :==, :eql?
75
+
76
+ def <=>(other)
77
+ self.to_s <=> other.to_s
78
+ end
75
79
 
76
80
  # Needed for uniq
77
81
  def hash; to_s.hash; end
@@ -88,8 +92,7 @@ module RdfContext
88
92
  # Output URI as QName using URI binding
89
93
  def to_qname(uri_binding = {})
90
94
  ns = namespace(uri_binding)
91
- sn = self.to_s.sub(ns.uri.to_s, "")
92
- "#{ns.prefix}:#{sn}"
95
+ "#{ns.prefix}:#{short_name}"
93
96
  end
94
97
 
95
98
  def namespace(uri_binding = {})
data/spec/bnode_spec.rb CHANGED
@@ -47,7 +47,7 @@ describe "Blank nodes" do
47
47
  describe "which has a blank identifier" do
48
48
  subject { BNode.new("", @context) }
49
49
  it "should not be the same as an anonymous identifier" do should_not == BNode.new end
50
- it "should be the same as another blank identifier" do should == BNode.new("", @context) end
50
+ it "should not be the same as another blank identifier" do should_not == BNode.new("", @context) end
51
51
  end
52
52
 
53
53
  describe "which are anonymous" do
data/spec/graph_spec.rb CHANGED
@@ -299,6 +299,62 @@ HERE
299
299
  subject.size.should == 0
300
300
  end
301
301
 
302
+ describe "properties" do
303
+ subject { Graph.new }
304
+
305
+ it "should get asserted properties" do
306
+ subject.add_triple(@ex.a, @ex.b, @ex.c)
307
+ subject.properties(@ex.a).should be_a(Hash)
308
+ subject.properties(@ex.a).size.should == 1
309
+ subject.properties(@ex.a).has_key?(@ex.b.to_s).should be_true
310
+ subject.properties(@ex.a)[@ex.b.to_s].should == [@ex.c]
311
+ end
312
+
313
+ it "should get asserted properties with 2 properties" do
314
+ subject.add_triple(@ex.a, @ex.b, @ex.c)
315
+ subject.add_triple(@ex.a, @ex.b, @ex.d)
316
+ subject.properties(@ex.a).should be_a(Hash)
317
+ subject.properties(@ex.a).size.should == 1
318
+ subject.properties(@ex.a).has_key?(@ex.b.to_s).should be_true
319
+ subject.properties(@ex.a)[@ex.b.to_s].should include(@ex.c, @ex.d)
320
+ end
321
+
322
+ it "should get asserted properties with 3 properties" do
323
+ subject.add_triple(@ex.a, @ex.b, @ex.c)
324
+ subject.add_triple(@ex.a, @ex.b, @ex.d)
325
+ subject.add_triple(@ex.a, @ex.b, @ex.e)
326
+ subject.properties(@ex.a).should be_a(Hash)
327
+ subject.properties(@ex.a).size.should == 1
328
+ subject.properties(@ex.a).has_key?(@ex.b.to_s).should be_true
329
+ subject.properties(@ex.a)[@ex.b.to_s].should include(@ex.c, @ex.d, @ex.e)
330
+ end
331
+
332
+ it "should get asserted type with single type" do
333
+ subject.add_triple(@ex.a, RDF_TYPE, @ex.Audio)
334
+ subject.properties(@ex.a)[RDF_TYPE.to_s].should == [@ex.Audio]
335
+ subject.type_of(@ex.a).should == [@ex.Audio]
336
+ end
337
+
338
+ it "should get nil with no type" do
339
+ subject.add_triple(@ex.a, @ex.b, @ex.c)
340
+ subject.properties(@ex.a)[RDF_TYPE.to_s].should == nil
341
+ subject.type_of(@ex.a).should == []
342
+ end
343
+
344
+ it "should sync properties to graph" do
345
+ props = subject.properties(@ex.a)
346
+ props.should be_a(Hash)
347
+ props[RDF_TYPE.to_s] = @ex.Audio
348
+ props[DC_NS.title.to_s] = "title"
349
+ props[@ex.b.to_s] = [@ex.c, @ex.d]
350
+ subject.sync_properties(@ex.a)
351
+ subject.contains?(Triple.new(@ex.a, RDF_TYPE, @ex.Audio)).should be_true
352
+ subject.contains?(Triple.new(@ex.a, DC_NS.title, "title")).should be_true
353
+ subject.contains?(Triple.new(@ex.a, @ex.b, @ex.c)).should be_true
354
+ subject.contains?(Triple.new(@ex.a, @ex.b, @ex.d)).should be_true
355
+ end
356
+ end
357
+
302
358
  describe "find triples" do
303
359
  it "should find subjects" do
304
360
  subject.triples(Triple.new(@ex.john, nil, nil)).size.should == 2
@@ -331,12 +387,13 @@ HERE
331
387
  it "should output RDF/XML" do
332
388
  rdfxml = <<-HERE
333
389
  <?xml version="1.0" encoding="UTF-8"?>
334
- <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:xhv="http://www.w3.org/1999/xhtml/vocab#">
390
+ <rdf:RDF xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:ex="http://example.org/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
335
391
  <rdf:Description rdf:about="http://example.org/john">
336
- <foaf:knows rdf:resource="http://example.org/jane"/>
337
- <foaf:knows rdf:resource="http://example.org/rick"/>
338
- </rdf:Description>
339
- <rdf:Description rdf:about="http://example.org/jane">
392
+ <foaf:knows>
393
+ <rdf:Description rdf:about="http://example.org/jane">
394
+ <foaf:knows rdf:resource="http://example.org/rick"/>
395
+ </rdf:Description>
396
+ </foaf:knows>
340
397
  <foaf:knows rdf:resource="http://example.org/rick"/>
341
398
  </rdf:Description>
342
399
  </rdf:RDF>
@@ -362,7 +419,7 @@ HERE
362
419
  end
363
420
 
364
421
  describe "rdf:first/rdf:rest sequences" do
365
- subject {
422
+ it "should return object list" do
366
423
  a, b = BNode.new("a"), BNode.new("b"), BNode.new("c")
367
424
  g = Graph.new(:store => ListStore.new)
368
425
  g.add_triple(@ex.List, RDF_NS.first, @ex.john)
@@ -372,11 +429,21 @@ HERE
372
429
  g.add_triple(b, RDF_NS.first, @ex.rick)
373
430
  g.add_triple(b, RDF_NS.rest, RDF_NS.nil)
374
431
  g.bind(@ex)
375
- g
376
- }
432
+
433
+ #puts g.seq(@ex.List).inspect
434
+ g.seq(@ex.List).should == [@ex.john, @ex.jane, @ex.rick]
435
+ end
377
436
 
378
- it "should return object list" do
379
- subject.seq(@ex.List).should == [@ex.john, @ex.jane, @ex.rick]
437
+ it "should generate a list of resources" do
438
+ g = Graph.new(:store => ListStore.new)
439
+ g.add_seq(@ex.List, RDF_NS.first, [@ex.john, @ex.jane, @ex.rick])
440
+ g.seq(@ex.List).should == [@ex.john, @ex.jane, @ex.rick]
441
+ end
442
+
443
+ it "should generate an empty list" do
444
+ g = Graph.new(:store => ListStore.new)
445
+ g.add_seq(@ex.List, RDF_NS.first, [])
446
+ g.seq(@ex.List).should == []
380
447
  end
381
448
  end
382
449
  end
data/spec/rdf_helper.rb CHANGED
@@ -105,7 +105,10 @@ module RdfHelper
105
105
 
106
106
  return unless output
107
107
 
108
- if self.compare == :array
108
+ case self.compare
109
+ when :none
110
+ # Don't check output, just parse to graph
111
+ when :array
109
112
  @parser.graph.should be_equivalent_graph(self.output, self)
110
113
  else
111
114
  output_parser = Parser.new
@@ -0,0 +1,227 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ include RdfContext
3
+
4
+ describe "Turtle Serializer" do
5
+ describe "simple tests" do
6
+ it "should use full URIs without base" do
7
+ input = %(<http://a/b> <http://a/c> <http://a/d> .)
8
+ serialize(input, nil, %r(^<http://a/b> <http://a/c> <http://a/d> \.$))
9
+ end
10
+
11
+ it "should use relative URIs with base" do
12
+ input = %(<http://a/b> <http://a/c> <http://a/d> .)
13
+ serialize(input, "http://a/",
14
+ %r(^@base <http://a/> \.$),
15
+ %r(^<b> <c> <d> \.$)
16
+ )
17
+ end
18
+
19
+ it "should use qname URIs with prefix" do
20
+ input = %(@prefix a: <http://a/> . <http://a/b> <http://a/c> <http://a/d> .)
21
+ serialize(input, nil,
22
+ %r(^@prefix a: <http://a/> \.$),
23
+ %r(^a:b a:c a:d \.$)
24
+ )
25
+ end
26
+
27
+ it "should use qname URIs with empty prefix" do
28
+ input = %(@prefix : <http://a/> . <http://a/b> <http://a/c> <http://a/d> .)
29
+ serialize(input, nil,
30
+ %r(^@prefix : <http://a/> \.$),
31
+ %r(^:b :c :d \.$)
32
+ )
33
+ end
34
+
35
+ it "should order properties" do
36
+ input = %(
37
+ @prefix : <http://a/> .
38
+ @prefix dc: <http://purl.org/dc/elements/1.1/> .
39
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
40
+ :b :c :d .
41
+ :b dc:title "title" .
42
+ :b a :class .
43
+ :b rdfs:label "label" .
44
+ )
45
+ serialize(input, nil,
46
+ %r(^:b a :class;$),
47
+ %r(^\s+rdfs:label "label";$),
48
+ %r(^\s+dc:title \"title\";$),
49
+ %r(^\s+:c :d \.$),
50
+ %r(a :class.*label.*title.*:c :d)m
51
+ )
52
+ end
53
+
54
+ it "should generate object list" do
55
+ input = %(@prefix : <http://a/> . :b :c :d, :e .)
56
+ serialize(input, nil,
57
+ %r(^@prefix : <http://a/> \.$),
58
+ %r(^:b :c :d,$),
59
+ %r(^\s+:e \.$)
60
+ )
61
+ end
62
+
63
+ it "should generate property list" do
64
+ input = %(@prefix : <http://a/> . :b :c :d; :e :f .)
65
+ serialize(input, nil,
66
+ %r(^@prefix : <http://a/> \.$),
67
+ %r(^:b :c :d;$),
68
+ %r(^\s+:e :f \.$)
69
+ )
70
+ end
71
+ end
72
+
73
+ describe "anons" do
74
+ it "should generate bare anon" do
75
+ input = %(@prefix : <http://a/> . [:a :b] .)
76
+ serialize(input, nil,
77
+ %r(^\s*\[ :a :b\] \.$)
78
+ )
79
+ end
80
+
81
+ it "should generate anon as subject" do
82
+ input = %(@prefix : <http://a/> . [:a :b] :c :d .)
83
+ serialize(input, nil,
84
+ %r(^\s*\[ :a :b;$),
85
+ %r(^\s+:c :d\] \.$)
86
+ )
87
+ end
88
+
89
+ it "should generate anon as object" do
90
+ input = %(@prefix : <http://a/> . :a :b [:c :d] .)
91
+ serialize(input, nil,
92
+ %r(^\s*\:a :b \[ :c :d\] \.$)
93
+ )
94
+ end
95
+ end
96
+
97
+ describe "lists" do
98
+ it "should generate bare list" do
99
+ input = %(@prefix : <http://a/> . (:a :b) .)
100
+ serialize(input, nil,
101
+ %r(^\(:a :b\) \.$)
102
+ )
103
+ end
104
+
105
+ it "should generate literal list" do
106
+ input = %(@prefix : <http://a/> . :a :b ( "apple" "banana" ) .)
107
+ serialize(input, nil,
108
+ %r(^:a :b \("apple" "banana"\) \.$)
109
+ )
110
+ end
111
+
112
+ it "should generate empty list" do
113
+ input = %(@prefix : <http://a/> . :a :b () .)
114
+ serialize(input, nil,
115
+ %r(^:a :b \(\) \.$)
116
+ )
117
+ end
118
+
119
+ it "should generate empty list(2)" do
120
+ input = %(@prefix : <http://a/> . :emptyList = () .)
121
+ serialize(input, nil,
122
+ %r(^:emptyList <.*sameAs> \(\) \.$)
123
+ )
124
+ end
125
+
126
+ it "should generate empty list as subject" do
127
+ input = %(@prefix : <http://a/> . () :a :b .)
128
+ serialize(input, nil,
129
+ %r(^\(\) :a :b \.$)
130
+ )
131
+ end
132
+
133
+ it "should generate list as subject" do
134
+ input = %(@prefix : <http://a/> . (:a) :b :c .)
135
+ serialize(input, nil,
136
+ %r(^\(:a\) :b :c \.$)
137
+ )
138
+ end
139
+
140
+ it "should generate list of empties" do
141
+ input = %(@prefix : <http://a/> . :listOf2Empties = (() ()) .)
142
+ serialize(input, nil,
143
+ %r(^:listOf2Empties <.*sameAs> \(\(\) \(\)\) \.$)
144
+ )
145
+ end
146
+
147
+ it "should generate list anon" do
148
+ input = %(@prefix : <http://a/> . :twoAnons = ([a :mother] [a :father]) .)
149
+ serialize(input, nil,
150
+ %r(^:twoAnons <.*sameAs> \(\[\s*a :mother\] \[\s*a :father\]\) \.$)
151
+ )
152
+ end
153
+
154
+ it "should generate owl:unionOf list" do
155
+ input = %(
156
+ @prefix : <http://a/> .
157
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
158
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
159
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
160
+ :a rdfs:domain [
161
+ a owl:Class;
162
+ owl:unionOf [
163
+ a owl:Class;
164
+ rdf:first :b;
165
+ rdf:rest [
166
+ a owl:Class;
167
+ rdf:first :c;
168
+ rdf:rest rdf:nil
169
+ ]
170
+ ]
171
+ ] .
172
+ )
173
+ serialize(input, nil,
174
+ %r(:a rdfs:domain \[\s*a owl:Class;\s+owl:unionOf\s+\(:b\s+:c\)\]\s*\.$)m
175
+ )
176
+ end
177
+ end
178
+
179
+ # W3C Turtle Test suite from http://www.w3.org/2000/10/swap/test/regression.n3
180
+ describe "w3c turtle tests" do
181
+ require 'rdf_helper'
182
+
183
+ def self.positive_tests
184
+ RdfHelper::TestCase.test_cases(TURTLE_TEST, TURTLE_DIR) rescue []
185
+ end
186
+
187
+ positive_tests.each do |t|
188
+ #puts t.inspect
189
+ #next unless t.name == "test-04"
190
+
191
+ specify "#{t.name}: " + (t.description || "#{t.inputDocument}") do
192
+ # Skip tests for very long files, too long
193
+ if %w(test-14 test-15 test-16 rdfq-results).include?(t.name)
194
+ pending("Skip very long input file")
195
+ elsif !defined?(::Encoding) && %w(test-18).include?(t.name)
196
+ pending("Not supported in Ruby 1.8")
197
+ elsif %w(test-29).include?(t.name)
198
+ pending("Silly test")
199
+ else
200
+ begin
201
+ t.run_test do |rdf_string, parser|
202
+ parser.parse(rdf_string, t.about.uri.to_s, :strict => true, :debug => [])
203
+ parser.graph.serialize(:format => :ttl, :base => t.about.uri.to_s)
204
+ t.compare = :none
205
+ end
206
+ #rescue #Spec::Expectations::ExpectationNotMetError => e
207
+ # pending() { raise }
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
213
+
214
+ # Serialize ntstr to a string and compare against regexps
215
+ def serialize(ntstr, base = nil, *regexps)
216
+ g = Graph.new
217
+ g.parse(ntstr, base)
218
+ result = g.serialize(:format => :ttl, :base => base)
219
+ puts result if $verbose
220
+
221
+ regexps.each do |re|
222
+ result.should =~ re
223
+ end
224
+
225
+ result
226
+ end
227
+ end