rdf-turtle 3.1.2 → 3.1.3

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
  SHA256:
3
- metadata.gz: cab6a95280c9ece9d97ed7bde134044c247d0990cd9451772b3726a85c1dafce
4
- data.tar.gz: 56c87a3f41a22ffae491aed4197261e204332541855777f1822bd24d965047f0
3
+ metadata.gz: 105a5880b1227824c5a05c14639512dad99a1501eb8e4a2590f8c02ac716aa32
4
+ data.tar.gz: 76b28dd1fb554b09fd0bd34ecea9e62cdd510748ac8efc5eee9a2368b6c18fa3
5
5
  SHA512:
6
- metadata.gz: c5ce46d746a7ed5ac19c3b8fde60934485781149302d6b02e64d1b45dd70a6402c46ba8ca9e7eb06c3d96030c93c26646751bc92155dc239dbc41179d9c72c49
7
- data.tar.gz: ad9a7a6ea210992f5a0ddbd037ded7b7f0a0129e4fc4a5610ad03f313381354207394840c9c729c70192906dfac58294c216a62382316b909f79a34c3db9d172
6
+ metadata.gz: 0f0ff42a2229ef95aa8b0473f39f5341ee9dc6d05a9006eca3a0b7653b661e75481a859f7d0cb3cba2fd6a58e0d1108ec9212185bec63b979cd6f071d08c0006
7
+ data.tar.gz: e866f62804abda425c13145304443fd385632c9f1a97666614b339bf4a2678149c2966e79d5dfd7629f326fa4c515aac756b808870eb3d64e13b3e5798b0fab8
data/README.md CHANGED
@@ -3,8 +3,9 @@
3
3
  [Turtle][] reader/writer for [RDF.rb][RDF.rb] .
4
4
 
5
5
  [![Gem Version](https://badge.fury.io/rb/rdf-turtle.png)](https://badge.fury.io/rb/rdf-turtle)
6
- [![Build Status](https://travis-ci.org/ruby-rdf/rdf-turtle.png?branch=master)](https://travis-ci.org/ruby-rdf/rdf-turtle)
7
- [![Coverage Status](https://coveralls.io/repos/ruby-rdf/rdf-turtle/badge.svg)](https://coveralls.io/r/ruby-rdf/rdf-turtle)
6
+ [![Build Status](https://github.com/ruby-rdf/rdf-turtle/workflows/CI/badge.svg?branch=develop)](https://github.com/ruby-rdf/rdf-turtle/actions?query=workflow%3ACI)
7
+ [![Coverage Status](https://coveralls.io/repos/ruby-rdf/rdf-turtle/badge.svg)](https://coveralls.io/github/ruby-rdf/rdf-turtle)
8
+ [![Gitter chat](https://badges.gitter.im/ruby-rdf/rdf.png)](https://gitter.im/ruby-rdf/rdf)
8
9
 
9
10
  ## Description
10
11
  This is a [Ruby][] implementation of a [Turtle][] parser for [RDF.rb][].
@@ -65,19 +66,29 @@ By default, the Turtle reader will reject a document containing a subject resour
65
66
  end
66
67
  # => RDF::ReaderError
67
68
 
68
- Readers support a `rdfstar` option with either `:PG` (Property Graph) or `:SA` (Separate Assertions) modes. In `:PG` mode, statements that are used in the subject or object positions are also implicitly added to the graph:
69
+ Readers support a boolean valued `rdfstar` option; only one statement is asserted, although the reified statement is contained within the graph.
69
70
 
70
71
  graph = RDF::Graph.new do |graph|
71
- RDF::Turtle::Reader.new(ttl, rdfstar: :PG) {|reader| graph << reader}
72
+ RDF::Turtle::Reader.new(ttl, rdfstar: true) {|reader| graph << reader}
72
73
  end
73
- graph.count #=> 2
74
+ graph.count #=> 1
75
+
76
+ ### Reading a Graph containing statement annotations
74
77
 
75
- When using the `:SA` mode, only one statement is asserted, although the reified statement is contained within the graph.
78
+ Annotations are introduced using the `{| ... |}` syntax, which is treated like a `blankNodePropertyList`,
79
+ where the subject is the the triple ending with that annotation.
76
80
 
81
+ ttl = %(
82
+ @prefix foaf: <http://xmlns.com/foaf/0.1/> .
83
+ @prefix ex: <http://example.com/> .
84
+ <bob> foaf:age 23 {| ex:certainty 9.0e-1 |} .
85
+ )
77
86
  graph = RDF::Graph.new do |graph|
78
- RDF::Turtle::Reader.new(ttl, rdfstar: :SA) {|reader| graph << reader}
87
+ RDF::Turtle::Reader.new(ttl) {|reader| graph << reader}
79
88
  end
80
- graph.count #=> 1
89
+ # => RDF::ReaderError
90
+
91
+ Note that this requires the `rdfstar` option to be se.
81
92
 
82
93
  ## Documentation
83
94
  Full documentation available on [Rubydoc.info][Turtle doc]
@@ -159,7 +170,9 @@ This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange develo
159
170
  list in the the `README`. Alphabetical order applies.
160
171
  * Do note that in order for us to merge any non-trivial changes (as a rule
161
172
  of thumb, additions larger than about 15 lines of code), we need an
162
- explicit [public domain dedication][PDD] on record from you.
173
+ explicit [public domain dedication][PDD] on record from you,
174
+ which you will be asked to agree to on the first commit to a repo within the organization.
175
+ Note that the agreement applies to all repos in the [Ruby RDF](https://github.com/ruby-rdf/) organization.
163
176
 
164
177
  ## License
165
178
  This is free and unencumbered public domain software. For more information,
@@ -171,13 +184,13 @@ A copy of the [Turtle EBNF][] and derived parser files are included in the repos
171
184
  [RDF]: https://www.w3.org/RDF/
172
185
  [YARD]: https://yardoc.org/
173
186
  [YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
174
- [PDD]: https://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html
187
+ [PDD]: https://unlicense.org/#unlicensing-contributions
175
188
  [RDF.rb]: https://rubydoc.info/github/ruby-rdf/rdf
176
189
  [EBNF]: https://rubygems.org/gems/ebnf
177
190
  [Backports]: https://rubygems.org/gems/backports
178
191
  [N-Triples]: https://www.w3.org/TR/rdf-testcases/#ntriples
179
192
  [Turtle]: https://www.w3.org/TR/2012/WD-turtle-20120710/
180
- [RDF*]: https://lists.w3.org/Archives/Public/public-rdf-star/
193
+ [RDF*]: https://w3c.github.io/rdf-star/rdf-star-cg-spec.html
181
194
  [Turtle doc]: https://rubydoc.info/github/ruby-rdf/rdf-turtle/master/file/README.md
182
195
  [Turtle EBNF]: https://dvcs.w3.org/hg/rdf/file/default/rdf-turtle/turtle.bnf
183
196
  [Freebase Dumps]: https://developers.google.com/freebase/data
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.2
1
+ 3.1.3
@@ -25,7 +25,14 @@ module RDF::Turtle
25
25
  terminal(:STRING_LITERAL_SINGLE_QUOTE, STRING_LITERAL_SINGLE_QUOTE, unescape: true)
26
26
 
27
27
  # String terminals
28
- terminal(nil, %r([\(\),.;\[\]Aa]|\^\^|true|false|<<|>>))
28
+ terminal(nil, %r(
29
+ [\(\),.;\[\]Aa]
30
+ | \^\^
31
+ | \{\|
32
+ | \|\}
33
+ | true|false
34
+ | <<|>>
35
+ )x)
29
36
 
30
37
  terminal(:PREFIX, PREFIX)
31
38
  terminal(:BASE, BASE)
@@ -92,11 +99,11 @@ module RDF::Turtle
92
99
  @prod_stack = []
93
100
 
94
101
  @options[:base_uri] = RDF::URI(base_uri || "")
95
- log_debug("base IRI") {base_uri.inspect}
102
+ debug("base IRI") {base_uri.inspect}
96
103
 
97
- log_debug("validate") {validate?.inspect}
98
- log_debug("canonicalize") {canonicalize?.inspect}
99
- log_debug("intern") {intern?.inspect}
104
+ debug("validate") {validate?.inspect}
105
+ debug("canonicalize") {canonicalize?.inspect}
106
+ debug("intern") {intern?.inspect}
100
107
 
101
108
  @lexer = EBNF::LL1::Lexer.new(input, self.class.patterns, **@options)
102
109
 
@@ -185,7 +192,7 @@ module RDF::Turtle
185
192
 
186
193
  # Create a literal
187
194
  def literal(value, **options)
188
- log_debug("literal", depth: @options[:depth]) do
195
+ debug("literal", depth: @options[:depth]) do
189
196
  "value: #{value.inspect}, " +
190
197
  "options: #{options.inspect}, " +
191
198
  "validate: #{validate?.inspect}, " +
@@ -221,7 +228,7 @@ module RDF::Turtle
221
228
  ''
222
229
  end
223
230
  suffix = suffix.to_s.sub(/^\#/, "") if base.index("#")
224
- log_debug("pname", depth: options[:depth]) {"base: '#{base}', suffix: '#{suffix}'"}
231
+ debug("pname", depth: options[:depth]) {"base: '#{base}', suffix: '#{suffix}'"}
225
232
  process_iri(base + suffix.to_s)
226
233
  end
227
234
 
@@ -283,7 +290,7 @@ module RDF::Turtle
283
290
  terminated = token.value == '@prefix'
284
291
  error("Expected PNAME_NS", production: :prefix, token: pfx) unless pfx === :PNAME_NS
285
292
  error("Expected IRIREF", production: :prefix, token: iri) unless iri === :IRIREF
286
- log_debug("prefixID", depth: options[:depth]) {"Defined prefix #{pfx.inspect} mapping to #{iri.inspect}"}
293
+ debug("prefixID", depth: options[:depth]) {"Defined prefix #{pfx.inspect} mapping to #{iri.inspect}"}
287
294
  prefix(pfx.value[0..-2], process_iri(iri))
288
295
  error("prefixId", "#{token} should be downcased") if token.value.start_with?('@') && token.value != '@prefix'
289
296
 
@@ -340,6 +347,10 @@ module RDF::Turtle
340
347
  last_object = nil
341
348
  while object = prod(:_objectList_2) {read_object(subject, predicate)}
342
349
  last_object = object
350
+
351
+ # If object is followed by an annotation, read that and also emit an embedded triple.
352
+ read_annotation(subject, predicate, object)
353
+
343
354
  break unless @lexer.first === ','
344
355
  @lexer.shift while @lexer.first === ','
345
356
  end
@@ -362,7 +373,7 @@ module RDF::Turtle
362
373
  read_iri ||
363
374
  read_BlankNode ||
364
375
  read_collection ||
365
- read_rdfstar ||
376
+ read_embTriple ||
366
377
  error( "Expected subject", production: :subject, token: @lexer.first)
367
378
  end
368
379
  end
@@ -375,7 +386,7 @@ module RDF::Turtle
375
386
  read_collection ||
376
387
  read_blankNodePropertyList ||
377
388
  read_literal ||
378
- read_rdfstar
389
+ read_embTriple
379
390
 
380
391
  add_statement(:object, RDF::Statement(subject, predicate, object)) if subject && predicate
381
392
  object
@@ -385,33 +396,69 @@ module RDF::Turtle
385
396
 
386
397
  # Read an RDF* reified statement
387
398
  # @return [RDF::Statement]
388
- def read_rdfstar
399
+ def read_embTriple
389
400
  return unless @options[:rdfstar]
390
401
  if @lexer.first.value == '<<'
391
- prod(:rdfstar) do
402
+ prod(:embTriple) do
392
403
  @lexer.shift # eat <<
393
- subject = read_subject || error("Failed to parse subject", production: :rdfstar, token: @lexer.first)
394
- predicate = read_verb || error("Failed to parse predicate", production: :rdfstar, token: @lexer.first)
395
- object = read_object || error("Failed to parse object", production: :rdfstar, token: @lexer.first)
404
+ subject = read_embSubject || error("Failed to parse subject", production: :embTriple, token: @lexer.first)
405
+ predicate = read_verb || error("Failed to parse predicate", production: :embTriple, token: @lexer.first)
406
+ object = read_embObject || error("Failed to parse object", production: :embTriple, token: @lexer.first)
396
407
  unless @lexer.first.value == '>>'
397
- error("Failed to end of embedded triple", production: :rdfstar, token: @lexer.first)
408
+ error("Failed to end of embedded triple", production: :embTriple, token: @lexer.first)
398
409
  end
399
410
  @lexer.shift
400
411
  statement = RDF::Statement(subject, predicate, object)
401
- # Emit the statement if in Property Graph mode
402
- add_statement(:rdfstar, statement) if @options[:rdfstar] == :PG
403
412
  statement
404
413
  end
405
414
  end
406
415
  end
407
416
 
417
+ # @return [RDF::Resource]
418
+ def read_embSubject
419
+ prod(:embSubject) do
420
+ read_iri ||
421
+ read_BlankNode ||
422
+ read_embTriple ||
423
+ error( "Expected embedded subject", production: :embSubject, token: @lexer.first)
424
+ end
425
+ end
426
+
427
+ # @return [RDF::Term]
428
+ def read_embObject(subject = nil, predicate = nil)
429
+ prod(:embObject) do
430
+ read_iri ||
431
+ read_BlankNode ||
432
+ read_literal ||
433
+ read_embTriple
434
+ end
435
+ end
436
+
437
+ # Read an annotation on a triple
438
+ def read_annotation(subject, predicate, object)
439
+ error("Unexpected end of file", production: :annotation) unless token = @lexer.first
440
+ if token === '{|'
441
+ prod(:annotation, %(|})) do
442
+ @lexer.shift
443
+
444
+ # Statement becomes subject for predicateObjectList
445
+ statement = RDF::Statement(subject, predicate, object)
446
+ read_predicateObjectList(statement) ||
447
+ error("Expected predicateObjectList", production: :annotation, token: @lexer.first)
448
+ error("annotation", "Expected closing '|}'") unless @lexer.first === '|}'
449
+ @lexer.shift
450
+ end
451
+ end
452
+
453
+ end
454
+
408
455
  # @return [RDF::Literal]
409
456
  def read_literal
410
457
  error("Unexpected end of file", production: :literal) unless token = @lexer.first
411
458
  case token.type || token.value
412
459
  when :INTEGER then prod(:literal) {literal(@lexer.shift.value, datatype: RDF::XSD.integer)}
413
460
  when :DECIMAL
414
- prod(:litearl) do
461
+ prod(:literal) do
415
462
  value = @lexer.shift.value
416
463
  value = "0#{value}" if value.start_with?(".")
417
464
  literal(value, datatype: RDF::XSD.decimal)
@@ -455,7 +502,7 @@ module RDF::Turtle
455
502
  if token === '['
456
503
  prod(:blankNodePropertyList, %{]}) do
457
504
  @lexer.shift
458
- log_info("blankNodePropertyList", depth: options[:depth]) {"token: #{token.inspect}"}
505
+ progress("blankNodePropertyList", depth: options[:depth]) {"token: #{token.inspect}"}
459
506
  node = bnode
460
507
  read_predicateObjectList(node)
461
508
  error("blankNodePropertyList", "Expected closing ']'") unless @lexer.first === ']'
@@ -471,7 +518,7 @@ module RDF::Turtle
471
518
  prod(:collection, %{)}) do
472
519
  @lexer.shift
473
520
  token = @lexer.first
474
- log_info("collection", depth: options[:depth]) {"token: #{token.inspect}"}
521
+ progress("collection", depth: options[:depth]) {"token: #{token.inspect}"}
475
522
  objects = []
476
523
  while object = read_object
477
524
  objects << object
@@ -508,7 +555,7 @@ module RDF::Turtle
508
555
  def prod(production, recover_to = [])
509
556
  @prod_stack << {prod: production, recover_to: recover_to}
510
557
  @options[:depth] += 1
511
- log_recover("#{production}(start)", depth: options[:depth]) {"token: #{@lexer.first.inspect}"}
558
+ recover("#{production}(start)", depth: options[:depth], token: @lexer.first)
512
559
  yield
513
560
  rescue EBNF::LL1::Lexer::Error, SyntaxError, Recovery => e
514
561
  # Lexer encountered an illegal token or the parser encountered
@@ -528,13 +575,13 @@ module RDF::Turtle
528
575
  end
529
576
  end
530
577
  raise EOFError, "End of input found when recovering" if @lexer.first.nil?
531
- log_debug("recovery", "current token: #{@lexer.first.inspect}", depth: options[:depth])
578
+ debug("recovery", "current token: #{@lexer.first.inspect}", depth: options[:depth])
532
579
 
533
580
  unless e.is_a?(Recovery)
534
581
  # Get the list of follows for this sequence, this production and the stacked productions.
535
- log_debug("recovery", "stack follows:", depth: options[:depth])
582
+ debug("recovery", "stack follows:", depth: options[:depth])
536
583
  @prod_stack.reverse.each do |prod|
537
- log_debug("recovery", level: 4, depth: options[:depth]) {" #{prod[:prod]}: #{prod[:recover_to].inspect}"}
584
+ debug("recovery", level: 4, depth: options[:depth]) {" #{prod[:prod]}: #{prod[:recover_to].inspect}"}
538
585
  end
539
586
  end
540
587
 
@@ -544,9 +591,9 @@ module RDF::Turtle
544
591
  # Skip tokens until one is found in follows
545
592
  while (token = (@lexer.first rescue @lexer.recover)) && follows.none? {|t| token === t}
546
593
  skipped = @lexer.shift
547
- log_debug("recovery", depth: options[:depth]) {"skip #{skipped.inspect}"}
594
+ debug("recovery", depth: options[:depth]) {"skip #{skipped.inspect}"}
548
595
  end
549
- log_debug("recovery", depth: options[:depth]) {"found #{token.inspect} in follows"}
596
+ debug("recovery", depth: options[:depth]) {"found #{token.inspect} in follows"}
550
597
 
551
598
  # Re-raise the error unless token is a follows of this production
552
599
  raise Recovery unless Array(recover_to).any? {|t| token === t}
@@ -554,11 +601,35 @@ module RDF::Turtle
554
601
  # Skip that token to get something reasonable to start the next production with
555
602
  @lexer.shift
556
603
  ensure
557
- log_info("#{production}(finish)", depth: options[:depth])
604
+ progress("#{production}(finish)", depth: options[:depth])
558
605
  @options[:depth] -= 1
559
606
  @prod_stack.pop
560
607
  end
561
608
 
609
+ def progress(*args, &block)
610
+ lineno = (options[:token].lineno if options[:token].respond_to?(:lineno)) || (@lexer && @lexer.lineno)
611
+ opts = args.last.is_a?(Hash) ? args.pop : {}
612
+ opts[:level] ||= 1
613
+ opts[:lineno] ||= lineno
614
+ log_info(*args, **opts, &block)
615
+ end
616
+
617
+ def recover(*args, &block)
618
+ lineno = (options[:token].lineno if options[:token].respond_to?(:lineno)) || (@lexer && @lexer.lineno)
619
+ opts = args.last.is_a?(Hash) ? args.pop : {}
620
+ opts[:level] ||= 1
621
+ opts[:lineno] ||= lineno
622
+ log_recover(*args, **opts, &block)
623
+ end
624
+
625
+ def debug(*args, &block)
626
+ lineno = (options[:token].lineno if options[:token].respond_to?(:lineno)) || (@lexer && @lexer.lineno)
627
+ opts = args.last.is_a?(Hash) ? args.pop : {}
628
+ opts[:level] ||= 0
629
+ opts[:lineno] ||= lineno
630
+ log_debug(*args, **opts, &block)
631
+ end
632
+
562
633
  ##
563
634
  # Error information, used as level `0` debug messages.
564
635
  #
@@ -314,12 +314,12 @@ module RDF::Turtle
314
314
  end
315
315
 
316
316
  ##
317
- # Returns an embedded triples
317
+ # Returns an embedded triple.
318
318
  #
319
319
  # @param [RDF::Statement] statement
320
320
  # @param [Hash{Symbol => Object}] options
321
321
  # @return [String]
322
- def format_rdfstar(statement, **options)
322
+ def format_embTriple(statement, **options)
323
323
  log_debug("rdfstar") {"#{statement.to_ntriples}"}
324
324
  "<<%s %s %s>>" % statement.to_a.map { |value| format_term(value, **options) }
325
325
  end
@@ -374,16 +374,16 @@ module RDF::Turtle
374
374
  # Mark as seen lists that are part of another list
375
375
  @lists.values.map(&:statements).
376
376
  flatten.each do |st|
377
- seen[st.object] = true if @lists.has_key?(st.object)
377
+ seen[st.object] = true if @lists.key?(st.object)
378
378
  end
379
379
 
380
- # List elements which are bnodes should not be targets for top-level serialization
381
- list_elements = @lists.values.map(&:to_a).flatten.select(&:node?).compact
380
+ # List elements which are bnodes should not be targets for top-level serialization
381
+ list_elements = @lists.values.map(&:to_a).flatten.select(&:node?).compact
382
382
 
383
- # Sort subjects by resources over bnodes, ref_counts and the subject URI itself
383
+ # Sort subjects by resources and statements over bnodes, ref_counts and the subject URI itself
384
384
  recursable = (@subjects.keys - list_elements).
385
385
  select {|s| !seen.include?(s)}.
386
- map {|r| [r.node? ? 1 : 0, ref_count(r), r]}.
386
+ map {|r| [r.node? ? 2 : (r.statement? ? 1 : 0), ref_count(r), r]}.
387
387
  sort
388
388
 
389
389
  subjects + recursable.map{|r| r.last}
@@ -469,7 +469,7 @@ module RDF::Turtle
469
469
  # Can subject be represented as a blankNodePropertyList?
470
470
  def blankNodePropertyList?(resource, position)
471
471
  !resource.statement? && resource.node? &&
472
- !is_valid_list?(resource) &&
472
+ !collection?(resource) &&
473
473
  (!is_done?(resource) || position == :subject) &&
474
474
  ref_count(resource) == (position == :object ? 1 : 0)
475
475
  end
@@ -507,35 +507,33 @@ module RDF::Turtle
507
507
  private
508
508
 
509
509
  # Checks if l is a valid RDF list, i.e. no nodes have other properties.
510
- def is_valid_list?(l)
511
- #log_debug("is_valid_list?") {l.inspect}
512
- return @lists[l] && @lists[l].valid?
513
- end
514
-
515
- def do_list(l, position)
516
- list = @lists[l]
517
- log_debug("do_list") {list.inspect}
518
- subject_done(RDF.nil)
519
- index = 0
520
- list.each_statement do |st|
521
- next unless st.predicate == RDF.first
522
- log_debug {" list this: #{st.subject} first: #{st.object}[#{position}]"}
523
- @output.write(" ") if index > 0
524
- path(st.object, position)
525
- subject_done(st.subject)
526
- position = :object
527
- index += 1
528
- end
510
+ def collection?(l)
511
+ #log_debug("collection?") {l.inspect}
512
+ return @lists.key?(l)
529
513
  end
530
514
 
531
515
  def collection(node, position)
532
- return false if !is_valid_list?(node)
516
+ return false if !collection?(node)
533
517
  return false if position == :subject && ref_count(node) > 0
534
518
  return false if position == :object && prop_count(node) > 0
535
519
  #log_debug("collection") {"#{node.to_ntriples}, #{position}"}
536
520
 
537
521
  @output.write("(")
538
- log_depth {do_list(node, position)}
522
+ log_depth do
523
+ list = @lists[node]
524
+ log_debug("collection") {list.inspect}
525
+ subject_done(RDF.nil)
526
+ index = 0
527
+ list.each_statement do |st|
528
+ next unless st.predicate == RDF.first
529
+ log_debug {" list this: #{st.subject} first: #{st.object}[#{position}]"}
530
+ @output.write(" ") if index > 0
531
+ path(st.object, position)
532
+ subject_done(st.subject)
533
+ position = :object
534
+ index += 1
535
+ end
536
+ end
539
537
  @output.write(')')
540
538
  end
541
539
 
@@ -568,7 +566,7 @@ module RDF::Turtle
568
566
  log_debug("path") do
569
567
  "#{resource.to_ntriples}, " +
570
568
  "pos: #{position}, " +
571
- "()?: #{is_valid_list?(resource)}, " +
569
+ "()?: #{collection?(resource)}, " +
572
570
  "[]?: #{blankNodePropertyList?(resource, position)}, " +
573
571
  "rc: #{ref_count(resource)}"
574
572
  end
@@ -588,7 +586,7 @@ module RDF::Turtle
588
586
  end
589
587
 
590
588
  # Render an objectList having a common subject and predicate
591
- def objectList(objects)
589
+ def objectList(subject, predicate, objects)
592
590
  log_debug("objectList") {objects.inspect}
593
591
  return if objects.empty?
594
592
 
@@ -599,6 +597,15 @@ module RDF::Turtle
599
597
  @output.write ",\n#{indent(4)}"
600
598
  end
601
599
  path(obj, :object)
600
+
601
+ # If subject, predicate, and object are embedded, write those bits out too.
602
+ emb = RDF::Statement(subject, predicate, obj)
603
+ if !@graph.query({subject: emb}).empty?
604
+ @output.write ' {| '
605
+ predicateObjectList(emb, true)
606
+ @output.write ' |}'
607
+ subject_done(emb)
608
+ end
602
609
  end
603
610
  end
604
611
 
@@ -611,17 +618,18 @@ module RDF::Turtle
611
618
  end
612
619
 
613
620
  prop_list = sort_properties(properties)
614
- prop_list -= [RDF.first.to_s, RDF.rest.to_s] if @lists.include?(subject)
621
+ prop_list -= [RDF.first.to_s, RDF.rest.to_s] if @lists.key?(subject)
615
622
  log_debug("predicateObjectList") {prop_list.inspect}
616
623
  return 0 if prop_list.empty?
617
624
 
618
625
  @output.write("\n#{indent(2)}") if properties.keys.length > 1 && from_bpl
619
626
  prop_list.each_with_index do |prop, i|
620
627
  begin
628
+ pred = RDF::URI.intern(prop)
621
629
  @output.write(";\n#{indent(2)}") if i > 0
622
- predicate(RDF::URI.intern(prop))
630
+ predicate(pred)
623
631
  @output.write(" ")
624
- objectList(properties[prop])
632
+ objectList(subject, pred, properties[prop])
625
633
  end
626
634
  end
627
635
  properties.keys.length
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdf-turtle
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.2
4
+ version: 3.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregg Kellogg
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-23 00:00:00.000000000 Z
11
+ date: 2020-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdf
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '3.1'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 3.1.2
22
+ version: 3.1.8
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,79 +29,79 @@ dependencies:
29
29
  version: '3.1'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 3.1.2
32
+ version: 3.1.8
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: ebnf
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '2.0'
39
+ version: '2.1'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '2.0'
46
+ version: '2.1'
47
47
  - !ruby/object:Gem::Dependency
48
- name: rspec
48
+ name: erubis
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '3.9'
53
+ version: '2.7'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '3.9'
60
+ version: '2.7'
61
61
  - !ruby/object:Gem::Dependency
62
- name: rspec-its
62
+ name: htmlentities
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: '1.3'
67
+ version: '4.3'
68
68
  type: :development
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: '1.3'
74
+ version: '4.3'
75
75
  - !ruby/object:Gem::Dependency
76
- name: rdf-isomorphic
76
+ name: rspec
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '3.1'
81
+ version: '3.10'
82
82
  type: :development
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '3.1'
88
+ version: '3.10'
89
89
  - !ruby/object:Gem::Dependency
90
- name: json-ld
90
+ name: rspec-its
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '3.1'
95
+ version: '1.3'
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '3.1'
102
+ version: '1.3'
103
103
  - !ruby/object:Gem::Dependency
104
- name: rdf-spec
104
+ name: rdf-isomorphic
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - "~>"
@@ -115,7 +115,7 @@ dependencies:
115
115
  - !ruby/object:Gem::Version
116
116
  version: '3.1'
117
117
  - !ruby/object:Gem::Dependency
118
- name: rdf-vocab
118
+ name: json-ld
119
119
  requirement: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - "~>"
@@ -129,33 +129,33 @@ dependencies:
129
129
  - !ruby/object:Gem::Version
130
130
  version: '3.1'
131
131
  - !ruby/object:Gem::Dependency
132
- name: rake
132
+ name: rdf-spec
133
133
  requirement: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: '13.0'
137
+ version: '3.1'
138
138
  type: :development
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: '13.0'
144
+ version: '3.1'
145
145
  - !ruby/object:Gem::Dependency
146
- name: yard
146
+ name: rdf-vocab
147
147
  requirement: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - "~>"
150
150
  - !ruby/object:Gem::Version
151
- version: 0.9.20
151
+ version: '3.1'
152
152
  type: :development
153
153
  prerelease: false
154
154
  version_requirements: !ruby/object:Gem::Requirement
155
155
  requirements:
156
156
  - - "~>"
157
157
  - !ruby/object:Gem::Version
158
- version: 0.9.20
158
+ version: '3.1'
159
159
  description: RDF::Turtle is an Turtle reader/writer for the RDF.rb library suite.
160
160
  email: public-rdf-ruby@w3.org
161
161
  executables: []
@@ -179,7 +179,7 @@ homepage: https://github.com/ruby-rdf/rdf-turtle
179
179
  licenses:
180
180
  - Unlicense
181
181
  metadata: {}
182
- post_install_message:
182
+ post_install_message:
183
183
  rdoc_options: []
184
184
  require_paths:
185
185
  - lib
@@ -194,8 +194,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
194
  - !ruby/object:Gem::Version
195
195
  version: '0'
196
196
  requirements: []
197
- rubygems_version: 3.1.3
198
- signing_key:
197
+ rubygems_version: 3.2.3
198
+ signing_key:
199
199
  specification_version: 4
200
200
  summary: Turtle reader/writer for Ruby.
201
201
  test_files: []