rdf-turtle 1.99.0 → 2.0.0.beta1
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 +4 -4
- data/README.md +4 -4
- data/VERSION +1 -1
- data/lib/rdf/turtle.rb +0 -3
- data/lib/rdf/turtle/format.rb +4 -15
- data/lib/rdf/turtle/freebase_reader.rb +1 -1
- data/lib/rdf/turtle/reader.rb +47 -142
- data/lib/rdf/turtle/writer.rb +68 -73
- metadata +63 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e71bbbae04dd8cd11ad1a9b33b8306c93c005a0
|
4
|
+
data.tar.gz: 215ea0878f18271c5dfaebf2979f63a0f7234e86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc1436d3c37d6b7d8d80a50dfd8197383959558b383b59ce2603d3c3cf7703851ae2f45ce8e6a5cd17ded2bd901bab79cc3a61e8e4672e1cd1e7c13aefe96862
|
7
|
+
data.tar.gz: 8c349965005898fcc0c9b5ea6d95ef83673127667d834493077b2fdf3514ab730acc92ef0297fa984d0861b87e66d351f2534b604e76c98cc40ccf8f2ed45824
|
data/README.md
CHANGED
@@ -17,7 +17,7 @@ Install with `gem install rdf-turtle`
|
|
17
17
|
|
18
18
|
* 100% free and unencumbered [public domain](http://unlicense.org/) software.
|
19
19
|
* Implements a complete parser for [Turtle][].
|
20
|
-
* Compatible with Ruby >=
|
20
|
+
* Compatible with Ruby >= 2.0.
|
21
21
|
* Optional streaming writer, to serialize large graphs
|
22
22
|
|
23
23
|
## Usage
|
@@ -86,9 +86,9 @@ This version uses a hand-written parser using the Lexer from the [EBNF][] gem in
|
|
86
86
|
|
87
87
|
## Dependencies
|
88
88
|
|
89
|
-
* [Ruby](http://ruby-lang.org/) (>=
|
90
|
-
* [RDF.rb](http://rubygems.org/gems/rdf) (~>
|
91
|
-
* [EBNF][] (~> 0
|
89
|
+
* [Ruby](http://ruby-lang.org/) (>= 2.0)
|
90
|
+
* [RDF.rb](http://rubygems.org/gems/rdf) (~> 2.0)
|
91
|
+
* [EBNF][] (~> 1.0)
|
92
92
|
|
93
93
|
## Installation
|
94
94
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0.beta1
|
data/lib/rdf/turtle.rb
CHANGED
data/lib/rdf/turtle/format.rb
CHANGED
@@ -54,21 +54,10 @@ module RDF::Turtle
|
|
54
54
|
sample.match(%r("@(context|subject|iri)")) # JSON-LD
|
55
55
|
)
|
56
56
|
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# Alias for TTL format
|
60
|
-
#
|
61
|
-
# This allows the following:
|
62
|
-
#
|
63
|
-
# @example Obtaining an TTL format class
|
64
|
-
# RDF::Format.for(:ttl) # RDF::Turtle::TTL
|
65
|
-
# RDF::Format.for(:ttl).reader # RDF::Turtle::Reader
|
66
|
-
# RDF::Format.for(:ttl).writer # RDF::Turtle::Writer
|
67
|
-
class TTL < Format
|
68
|
-
content_encoding 'utf-8'
|
69
|
-
content_type 'text/turtle'
|
70
57
|
|
71
|
-
|
72
|
-
|
58
|
+
# List of symbols used to lookup this format
|
59
|
+
def self.symbols
|
60
|
+
[:turtle, :ttl]
|
61
|
+
end
|
73
62
|
end
|
74
63
|
end
|
@@ -24,7 +24,7 @@ module RDF::Turtle
|
|
24
24
|
predicate = read_pname(intern: true) || fail_predicate
|
25
25
|
object = read_pname || read_uriref || read_boolean || read_numeric || read_literal || fail_object
|
26
26
|
if validate? && !read_eos
|
27
|
-
|
27
|
+
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
28
28
|
end
|
29
29
|
return [subject, predicate, object]
|
30
30
|
end
|
data/lib/rdf/turtle/reader.rb
CHANGED
@@ -8,6 +8,7 @@ module RDF::Turtle
|
|
8
8
|
format Format
|
9
9
|
include EBNF::LL1::Parser
|
10
10
|
include RDF::Turtle::Terminals
|
11
|
+
include RDF::Util::Logger
|
11
12
|
|
12
13
|
# Terminals passed to lexer. Order matters!
|
13
14
|
terminal(:ANON, ANON)
|
@@ -31,14 +32,17 @@ module RDF::Turtle
|
|
31
32
|
terminal(:LANGTAG, LANGTAG)
|
32
33
|
|
33
34
|
##
|
34
|
-
#
|
35
|
-
# @
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
# Reader options
|
36
|
+
# @see http://www.rubydoc.info/github/ruby-rdf/rdf/RDF/Reader#options-class_method
|
37
|
+
def self.options
|
38
|
+
super + [
|
39
|
+
RDF::CLI::Option.new(
|
40
|
+
symbol: :freebase,
|
41
|
+
datatype: TrueClass,
|
42
|
+
on: ["--freebase"],
|
43
|
+
description: "Use optimized Freebase reader.") {true},
|
44
|
+
]
|
45
|
+
end
|
42
46
|
|
43
47
|
##
|
44
48
|
# Redirect for Freebase Reader
|
@@ -73,18 +77,8 @@ module RDF::Turtle
|
|
73
77
|
# @option options [Boolean] :validate (false)
|
74
78
|
# whether to validate the parsed statements and values. If not validating,
|
75
79
|
# the parser will attempt to recover from errors.
|
76
|
-
# @option options [
|
77
|
-
#
|
78
|
-
# @option options [Array] :warnings
|
79
|
-
# array for placing warnings found when parsing
|
80
|
-
# @option options [Boolean] :progress
|
81
|
-
# Show progress of parser productions
|
82
|
-
# @option options [Boolean, Integer, Array] :debug
|
83
|
-
# Detailed debug output. If set to an Integer, output is restricted
|
84
|
-
# to messages of that priority: `0` for errors, `1` for warnings,
|
85
|
-
# `2` for processor tracing, and anything else for various levels
|
86
|
-
# of debug. If set to an Array, information is collected in the array
|
87
|
-
# instead of being output to `$stderr`.
|
80
|
+
# @option options [Logger, #write, #<<] :logger
|
81
|
+
# Record error/info/debug output
|
88
82
|
# @option options [Boolean] :freebase (false)
|
89
83
|
# Use optimized Freebase reader
|
90
84
|
# @return [RDF::Turtle::Reader]
|
@@ -94,25 +88,17 @@ module RDF::Turtle
|
|
94
88
|
anon_base: "b0",
|
95
89
|
validate: false,
|
96
90
|
whitespace: WS,
|
91
|
+
log_depth: 0,
|
97
92
|
}.merge(options)
|
98
93
|
@options = {prefixes: {nil => ""}}.merge(@options) unless @options[:validate]
|
99
|
-
@errors = @options[:errors] || []
|
100
|
-
@warnings = @options[:warnings] || []
|
101
|
-
@depth = 0
|
102
94
|
@prod_stack = []
|
103
95
|
|
104
|
-
@options[:debug] ||= case
|
105
|
-
when RDF::Turtle.debug? then true
|
106
|
-
when @options[:progress] then 2
|
107
|
-
when @options[:validate] then 1
|
108
|
-
end
|
109
|
-
|
110
96
|
@options[:base_uri] = RDF::URI(base_uri || "")
|
111
|
-
|
97
|
+
log_debug("base IRI") {base_uri.inspect}
|
112
98
|
|
113
|
-
|
114
|
-
|
115
|
-
|
99
|
+
log_debug("validate") {validate?.inspect}
|
100
|
+
log_debug("canonicalize") {canonicalize?.inspect}
|
101
|
+
log_debug("intern") {intern?.inspect}
|
116
102
|
|
117
103
|
@lexer = EBNF::LL1::Lexer.new(input, self.class.patterns, @options)
|
118
104
|
|
@@ -137,7 +123,7 @@ module RDF::Turtle
|
|
137
123
|
# @return [void]
|
138
124
|
def each_statement(&block)
|
139
125
|
if block_given?
|
140
|
-
|
126
|
+
log_recover
|
141
127
|
@callback = block
|
142
128
|
|
143
129
|
begin
|
@@ -148,14 +134,8 @@ module RDF::Turtle
|
|
148
134
|
# Terminate loop if EOF found while recovering
|
149
135
|
end
|
150
136
|
|
151
|
-
if validate?
|
152
|
-
|
153
|
-
$stderr.puts "Warnings: #{warnings.join("\n")}"
|
154
|
-
end
|
155
|
-
if !errors.empty?
|
156
|
-
$stderr.puts "Errors: #{errors.join("\n")}" unless @options[:errors]
|
157
|
-
raise RDF::ReaderError, "Errors found during processing"
|
158
|
-
end
|
137
|
+
if validate? && log_statistics[:error]
|
138
|
+
raise RDF::ReaderError, "Errors found during processing"
|
159
139
|
end
|
160
140
|
end
|
161
141
|
enum_for(:each_statement)
|
@@ -207,7 +187,7 @@ module RDF::Turtle
|
|
207
187
|
|
208
188
|
# Create a literal
|
209
189
|
def literal(value, options = {})
|
210
|
-
|
190
|
+
log_debug("literal") do
|
211
191
|
"value: #{value.inspect}, " +
|
212
192
|
"options: #{options.inspect}, " +
|
213
193
|
"validate: #{validate?.inspect}, " +
|
@@ -241,7 +221,7 @@ module RDF::Turtle
|
|
241
221
|
base = ''
|
242
222
|
end
|
243
223
|
suffix = suffix.to_s.sub(/^\#/, "") if base.index("#")
|
244
|
-
|
224
|
+
log_debug("pname") {"base: '#{base}', suffix: '#{suffix}'"}
|
245
225
|
process_iri(base + suffix.to_s)
|
246
226
|
end
|
247
227
|
|
@@ -262,7 +242,7 @@ module RDF::Turtle
|
|
262
242
|
read_directive || error("Failed to parse directive", production: :directive, token: token)
|
263
243
|
else
|
264
244
|
read_triples || error("Expected token", production: :statement, token: token)
|
265
|
-
if
|
245
|
+
if !log_recovering? || @lexer.first === '.'
|
266
246
|
# If recovering, we will have eaten the closing '.'
|
267
247
|
token = @lexer.shift
|
268
248
|
unless token && token.value == '.'
|
@@ -303,7 +283,7 @@ module RDF::Turtle
|
|
303
283
|
terminated = token.value == '@prefix'
|
304
284
|
error("Expected PNAME_NS", production: :prefix, token: pfx) unless pfx === :PNAME_NS
|
305
285
|
error("Expected IRIREF", production: :prefix, token: iri) unless iri === :IRIREF
|
306
|
-
|
286
|
+
log_debug("prefixID") {"Defined prefix #{pfx.inspect} mapping to #{iri.inspect}"}
|
307
287
|
prefix(pfx.value[0..-2], process_iri(iri))
|
308
288
|
error("prefixId", "#{token} should be downcased") if token.value.start_with?('@') && token.value != '@prefix'
|
309
289
|
|
@@ -451,7 +431,7 @@ module RDF::Turtle
|
|
451
431
|
if token === '['
|
452
432
|
prod(:blankNodePropertyList, %{]}) do
|
453
433
|
@lexer.shift
|
454
|
-
|
434
|
+
log_info("blankNodePropertyList") {"token: #{token.inspect}"}
|
455
435
|
node = bnode
|
456
436
|
read_predicateObjectList(node)
|
457
437
|
error("blankNodePropertyList", "Expected closing ']'") unless @lexer.first === ']'
|
@@ -467,12 +447,12 @@ module RDF::Turtle
|
|
467
447
|
prod(:collection, %{)}) do
|
468
448
|
@lexer.shift
|
469
449
|
token = @lexer.first
|
470
|
-
|
450
|
+
log_info("collection") {"token: #{token.inspect}"}
|
471
451
|
objects = []
|
472
452
|
while object = read_object
|
473
453
|
objects << object
|
474
454
|
end
|
475
|
-
list = RDF::List.new(
|
455
|
+
list = RDF::List.new(values: objects)
|
476
456
|
list.each_statement do |statement|
|
477
457
|
add_statement("collection", statement)
|
478
458
|
end
|
@@ -503,9 +483,8 @@ module RDF::Turtle
|
|
503
483
|
|
504
484
|
def prod(production, recover_to = [])
|
505
485
|
@prod_stack << {prod: production, recover_to: recover_to}
|
506
|
-
@
|
507
|
-
|
508
|
-
progress("#{production}(start)") {"token: #{@lexer.first.inspect}"}
|
486
|
+
@options[:log_depth] += 1
|
487
|
+
log_recover("#{production}(start)") {"token: #{@lexer.first.inspect}"}
|
509
488
|
yield
|
510
489
|
rescue EBNF::LL1::Lexer::Error, SyntaxError, Recovery => e
|
511
490
|
# Lexer encountered an illegal token or the parser encountered
|
@@ -525,13 +504,13 @@ module RDF::Turtle
|
|
525
504
|
end
|
526
505
|
end
|
527
506
|
raise EOFError, "End of input found when recovering" if @lexer.first.nil?
|
528
|
-
|
507
|
+
log_debug("recovery", "current token: #{@lexer.first.inspect}")
|
529
508
|
|
530
509
|
unless e.is_a?(Recovery)
|
531
510
|
# Get the list of follows for this sequence, this production and the stacked productions.
|
532
|
-
|
511
|
+
log_debug("recovery", "stack follows:")
|
533
512
|
@prod_stack.reverse.each do |prod|
|
534
|
-
|
513
|
+
log_debug("recovery", level: 4) {" #{prod[:prod]}: #{prod[:recover_to].inspect}"}
|
535
514
|
end
|
536
515
|
end
|
537
516
|
|
@@ -541,9 +520,9 @@ module RDF::Turtle
|
|
541
520
|
# Skip tokens until one is found in follows
|
542
521
|
while (token = (@lexer.first rescue @lexer.recover)) && follows.none? {|t| token === t}
|
543
522
|
skipped = @lexer.shift
|
544
|
-
|
523
|
+
log_debug("recovery") {"skip #{skipped.inspect}"}
|
545
524
|
end
|
546
|
-
|
525
|
+
log_debug("recovery") {"found #{token.inspect} in follows"}
|
547
526
|
|
548
527
|
# Re-raise the error unless token is a follows of this production
|
549
528
|
raise Recovery unless Array(recover_to).any? {|t| token === t}
|
@@ -551,34 +530,15 @@ module RDF::Turtle
|
|
551
530
|
# Skip that token to get something reasonable to start the next production with
|
552
531
|
@lexer.shift
|
553
532
|
ensure
|
554
|
-
|
555
|
-
@
|
533
|
+
log_info("#{production}(finish)")
|
534
|
+
@options[:log_depth] -= 1
|
556
535
|
@prod_stack.pop
|
557
536
|
end
|
558
537
|
|
559
|
-
##
|
560
|
-
# Warning information, used as level `1` debug messages.
|
561
|
-
#
|
562
|
-
# @param [String] node Relevant location associated with message
|
563
|
-
# @param [String] message Error string
|
564
|
-
# @param [Hash] options
|
565
|
-
# @option options [URI, #to_s] :production
|
566
|
-
# @option options [Token] :token
|
567
|
-
# @see {#debug}
|
568
|
-
def warn(node, message, options = {})
|
569
|
-
m = "WARNING "
|
570
|
-
m += "[line: #{@lineno}] " if @lineno
|
571
|
-
m += message
|
572
|
-
m += " (found #{options[:token].inspect})" if options[:token]
|
573
|
-
m += ", production = #{options[:production].inspect}" if options[:production]
|
574
|
-
@warnings << m unless @recovering
|
575
|
-
debug(node, m, options.merge(level: 1))
|
576
|
-
end
|
577
|
-
|
578
538
|
##
|
579
539
|
# Error information, used as level `0` debug messages.
|
580
540
|
#
|
581
|
-
# @overload
|
541
|
+
# @overload error(node, message, options)
|
582
542
|
# @param [String] node Relevant location associated with message
|
583
543
|
# @param [String] message Error string
|
584
544
|
# @param [Hash] options
|
@@ -586,70 +546,15 @@ module RDF::Turtle
|
|
586
546
|
# @option options [Token] :token
|
587
547
|
# @see {#debug}
|
588
548
|
def error(*args)
|
589
|
-
|
590
|
-
|
549
|
+
ctx = ""
|
550
|
+
ctx += "(found #{options[:token].inspect})" if options[:token]
|
551
|
+
ctx += ", production = #{options[:production].inspect}" if options[:production]
|
591
552
|
lineno = @lineno || (options[:token].lineno if options[:token].respond_to?(:lineno))
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
m += ", production = #{options[:production].inspect}" if options[:production]
|
598
|
-
@recovering = true
|
599
|
-
@errors << m
|
600
|
-
debug(m, options.merge(level: 0))
|
601
|
-
raise SyntaxError.new(m, lineno: lineno, token: options[:token], production: options[:production])
|
602
|
-
end
|
603
|
-
|
604
|
-
##
|
605
|
-
# Progress output when debugging.
|
606
|
-
#
|
607
|
-
# The call is ignored, unless `@options[:debug]` is set, in which
|
608
|
-
# case it records tracing information as indicated. Additionally,
|
609
|
-
# if `@options[:debug]` is an Integer, the call is aborted if the
|
610
|
-
# `:level` option is less than than `:level`.
|
611
|
-
#
|
612
|
-
# @overload debug(node, message, options)
|
613
|
-
# @param [Array<String>] args Relevant location associated with message
|
614
|
-
# @param [Hash] options
|
615
|
-
# @option options [Integer] :depth
|
616
|
-
# Recursion depth for indenting output
|
617
|
-
# @option options [Integer] :level
|
618
|
-
# Level assigned to message, by convention, level `0` is for
|
619
|
-
# errors, level `1` is for warnings, level `2` is for parser
|
620
|
-
# progress information, and anything higher is for various levels
|
621
|
-
# of debug information.
|
622
|
-
#
|
623
|
-
# @yieldparam [:trace] trace
|
624
|
-
# @yieldparam [Integer] level
|
625
|
-
# @yieldparam [Integer] lineno
|
626
|
-
# @yieldparam [Integer] depth Recursive depth of productions
|
627
|
-
# @yieldparam [Array<String>] args
|
628
|
-
# @yieldreturn [String] added to message
|
629
|
-
def debug(*args)
|
630
|
-
return unless @options[:debug]
|
631
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
632
|
-
debug_level = options.fetch(:level, 3)
|
633
|
-
return if @options[:debug].is_a?(Integer) && debug_level > @options[:debug]
|
634
|
-
|
635
|
-
depth = options[:depth] || @depth
|
636
|
-
args << yield if block_given?
|
637
|
-
|
638
|
-
message = "#{args.join(': ')}"
|
639
|
-
d_str = depth > 100 ? ' ' * 100 + '+' : ' ' * depth
|
640
|
-
str = "[#{lineno}](#{debug_level})#{d_str}#{message}"
|
641
|
-
case @options[:debug]
|
642
|
-
when Array
|
643
|
-
@options[:debug] << str
|
644
|
-
when TrueClass
|
645
|
-
$stderr.puts str
|
646
|
-
when Integer
|
647
|
-
case debug_level
|
648
|
-
when 0 then return if @options[:errors]
|
649
|
-
when 1 then return if @options[:warnings]
|
650
|
-
end
|
651
|
-
$stderr.puts(str) if debug_level <= @options[:debug]
|
652
|
-
end
|
553
|
+
log_error(*args, ctx,
|
554
|
+
lineno: lineno,
|
555
|
+
token: options[:token],
|
556
|
+
production: options[:production],
|
557
|
+
exception: SyntaxError)
|
653
558
|
end
|
654
559
|
|
655
560
|
# Used for internal error recovery
|
data/lib/rdf/turtle/writer.rb
CHANGED
@@ -57,11 +57,40 @@ module RDF::Turtle
|
|
57
57
|
# @author [Gregg Kellogg](http://greggkellogg.net/)
|
58
58
|
class Writer < RDF::Writer
|
59
59
|
include StreamingWriter
|
60
|
+
include RDF::Util::Logger
|
60
61
|
format RDF::Turtle::Format
|
61
62
|
|
62
63
|
# @return [Graph] Graph of statements serialized
|
63
64
|
attr_accessor :graph
|
64
|
-
|
65
|
+
|
66
|
+
##
|
67
|
+
# Writer options
|
68
|
+
# @see http://www.rubydoc.info/github/ruby-rdf/rdf/RDF/Writer#options-class_method
|
69
|
+
def self.options
|
70
|
+
super + [
|
71
|
+
RDF::CLI::Option.new(
|
72
|
+
symbol: :max_depth,
|
73
|
+
datatype: Integer,
|
74
|
+
on: ["--max-depth DEPTH"],
|
75
|
+
description: "Maximum depth for recursively defining resources, defaults to 3.") {true},
|
76
|
+
RDF::CLI::Option.new(
|
77
|
+
symbol: :stream,
|
78
|
+
datatype: TrueClass,
|
79
|
+
on: ["--stream"],
|
80
|
+
description: "Do not attempt to optimize graph presentation, suitable for streaming large graphs.") {true},
|
81
|
+
RDF::CLI::Option.new(
|
82
|
+
symbol: :default_namespace,
|
83
|
+
datatype: RDF::URI,
|
84
|
+
on: ["--default-namespace URI", :REQUIRED],
|
85
|
+
description: "URI to use as default namespace, same as prefixes.") {|arg| RDF::URI(arg)},
|
86
|
+
RDF::CLI::Option.new(
|
87
|
+
symbol: :literal_shorthand,
|
88
|
+
datatype: FalseClass,
|
89
|
+
on: ["--no-literal-shorthand"],
|
90
|
+
description: "Do not ttempt to use Literal shorthands fo numbers and boolean values.") {false},
|
91
|
+
]
|
92
|
+
end
|
93
|
+
|
65
94
|
##
|
66
95
|
# Initializes the Turtle writer instance.
|
67
96
|
#
|
@@ -88,19 +117,19 @@ module RDF::Turtle
|
|
88
117
|
# @option options [Boolean] :unique_bnodes (false)
|
89
118
|
# Use unique node identifiers, defaults to using the identifier which the node was originall initialized with (if any).
|
90
119
|
# @option options [Boolean] :literal_shorthand (true)
|
91
|
-
# Attempt to use Literal shorthands
|
120
|
+
# Attempt to use Literal shorthands for numbers and boolean values
|
92
121
|
# @yield [writer] `self`
|
93
122
|
# @yieldparam [RDF::Writer] writer
|
94
123
|
# @yieldreturn [void]
|
95
124
|
# @yield [writer]
|
96
125
|
# @yieldparam [RDF::Writer] writer
|
97
126
|
def initialize(output = $stdout, options = {}, &block)
|
98
|
-
reset
|
99
127
|
@graph = RDF::Graph.new
|
100
128
|
@uri_to_pname = {}
|
101
129
|
@uri_to_prefix = {}
|
102
130
|
options = {literal_shorthand: true}.merge(options)
|
103
131
|
super do
|
132
|
+
reset
|
104
133
|
if block_given?
|
105
134
|
case block.arity
|
106
135
|
when 0 then instance_eval(&block)
|
@@ -110,20 +139,6 @@ module RDF::Turtle
|
|
110
139
|
end
|
111
140
|
end
|
112
141
|
|
113
|
-
##
|
114
|
-
# Adds a statement to be serialized
|
115
|
-
# @param [RDF::Statement] statement
|
116
|
-
# @return [void]
|
117
|
-
def write_statement(statement)
|
118
|
-
case
|
119
|
-
when @options[:stream]
|
120
|
-
stream_statement(statement)
|
121
|
-
else
|
122
|
-
# Add to local graph and output in epilogue
|
123
|
-
@graph.insert(statement)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
142
|
##
|
128
143
|
# Adds a triple to be serialized
|
129
144
|
# @param [RDF::Resource] subject
|
@@ -131,7 +146,12 @@ module RDF::Turtle
|
|
131
146
|
# @param [RDF::Value] object
|
132
147
|
# @return [void]
|
133
148
|
def write_triple(subject, predicate, object)
|
134
|
-
|
149
|
+
statement = RDF::Statement.new(subject, predicate, object)
|
150
|
+
if @options[:stream]
|
151
|
+
stream_statement(statement)
|
152
|
+
else
|
153
|
+
@graph.insert(statement)
|
154
|
+
end
|
135
155
|
end
|
136
156
|
|
137
157
|
##
|
@@ -159,7 +179,7 @@ module RDF::Turtle
|
|
159
179
|
|
160
180
|
self.reset
|
161
181
|
|
162
|
-
|
182
|
+
log_debug("\nserialize") {"graph: #{@graph.size}"}
|
163
183
|
|
164
184
|
preprocess
|
165
185
|
start_document
|
@@ -170,6 +190,7 @@ module RDF::Turtle
|
|
170
190
|
end
|
171
191
|
end
|
172
192
|
end
|
193
|
+
super
|
173
194
|
end
|
174
195
|
|
175
196
|
# Return a QName for the URI, or nil. Adds namespace of QName to defined prefixes
|
@@ -193,14 +214,14 @@ module RDF::Turtle
|
|
193
214
|
prefix = @uri_to_prefix[u]
|
194
215
|
unless u.to_s.empty?
|
195
216
|
prefix(prefix, u) unless u.to_s.empty?
|
196
|
-
|
217
|
+
log_debug("get_pname") {"add prefix #{prefix.inspect} => #{u}"}
|
197
218
|
uri.sub(u.to_s, "#{prefix}:")
|
198
219
|
end
|
199
220
|
when @options[:standard_prefixes] && vocab = RDF::Vocabulary.each.to_a.detect {|v| uri.index(v.to_uri.to_s) == 0}
|
200
221
|
prefix = vocab.__name__.to_s.split('::').last.downcase
|
201
222
|
@uri_to_prefix[vocab.to_uri.to_s] = prefix
|
202
223
|
prefix(prefix, vocab.to_uri) # Define for output
|
203
|
-
|
224
|
+
log_debug("get_pname") {"add standard prefix #{prefix.inspect} => #{vocab.to_uri}"}
|
204
225
|
uri.sub(vocab.to_uri.to_s, "#{prefix}:")
|
205
226
|
else
|
206
227
|
nil
|
@@ -233,7 +254,7 @@ module RDF::Turtle
|
|
233
254
|
prop_list << prop.to_s
|
234
255
|
end
|
235
256
|
|
236
|
-
|
257
|
+
log_debug("sort_properties") {prop_list.join(', ')}
|
237
258
|
prop_list
|
238
259
|
end
|
239
260
|
|
@@ -244,7 +265,6 @@ module RDF::Turtle
|
|
244
265
|
# @param [Hash{Symbol => Object}] options
|
245
266
|
# @return [String]
|
246
267
|
def format_literal(literal, options = {})
|
247
|
-
literal = literal.dup.canonicalize! if @options[:canonicalize]
|
248
268
|
case literal
|
249
269
|
when RDF::Literal
|
250
270
|
case @options[:literal_shorthand] && literal.valid? ? literal.datatype : false
|
@@ -271,7 +291,7 @@ module RDF::Turtle
|
|
271
291
|
# @return [String]
|
272
292
|
def format_uri(uri, options = {})
|
273
293
|
md = uri.relativize(base_uri)
|
274
|
-
|
294
|
+
log_debug("relativize") {"#{uri.to_ntriples} => #{md.inspect}"} if md != uri.to_s
|
275
295
|
md != uri.to_s ? "<#{md}>" : (get_pname(uri) || "<#{uri}>")
|
276
296
|
end
|
277
297
|
|
@@ -290,7 +310,7 @@ module RDF::Turtle
|
|
290
310
|
def start_document
|
291
311
|
@output.write("#{indent}@base <#{base_uri}> .\n") unless base_uri.to_s.empty?
|
292
312
|
|
293
|
-
|
313
|
+
log_debug("start_document") {prefixes.inspect}
|
294
314
|
prefixes.keys.sort_by(&:to_s).each do |prefix|
|
295
315
|
@output.write("#{indent}@prefix #{prefix}: <#{prefixes[prefix]}> .\n")
|
296
316
|
end
|
@@ -322,7 +342,7 @@ module RDF::Turtle
|
|
322
342
|
# Add distinguished classes
|
323
343
|
top_classes.each do |class_uri|
|
324
344
|
graph.query(predicate: RDF.type, object: class_uri).map {|st| st.subject}.sort.uniq.each do |subject|
|
325
|
-
|
345
|
+
log_debug("order_subjects") {subject.to_ntriples}
|
326
346
|
subjects << subject
|
327
347
|
seen[subject] = true
|
328
348
|
end
|
@@ -359,7 +379,7 @@ module RDF::Turtle
|
|
359
379
|
# prefixes.
|
360
380
|
# @param [Statement] statement
|
361
381
|
def preprocess_statement(statement)
|
362
|
-
#
|
382
|
+
#log_debug("preprocess") {statement.to_ntriples}
|
363
383
|
bump_reference(statement.object)
|
364
384
|
@subjects[statement.subject] = true
|
365
385
|
|
@@ -374,12 +394,11 @@ module RDF::Turtle
|
|
374
394
|
# @param [Integer] modifier Increase depth by specified amount
|
375
395
|
# @return [String] A number of spaces, depending on current depth
|
376
396
|
def indent(modifier = 0)
|
377
|
-
" " * (@
|
397
|
+
" " * (@options.fetch(:log_depth, log_depth) * 2 + modifier)
|
378
398
|
end
|
379
399
|
|
380
400
|
# Reset internal helper instance variables
|
381
401
|
def reset
|
382
|
-
@depth = 0
|
383
402
|
@lists = {}
|
384
403
|
@references = {}
|
385
404
|
@serialized = {}
|
@@ -400,41 +419,21 @@ module RDF::Turtle
|
|
400
419
|
end
|
401
420
|
end
|
402
421
|
|
403
|
-
##
|
404
|
-
# Add debug event to debug array, if specified
|
405
|
-
#
|
406
|
-
# @overload debug(message)
|
407
|
-
# @param [String] message ("")
|
408
|
-
# @yieldreturn [String] added to message
|
409
|
-
def debug(*args)
|
410
|
-
return unless @options[:debug] || RDF::Turtle.debug?
|
411
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
412
|
-
depth = options[:depth] || @depth
|
413
|
-
d_str = depth > 100 ? ' ' * 100 + '+' : ' ' * depth
|
414
|
-
message = args.pop
|
415
|
-
message = message.call if message.is_a?(Proc)
|
416
|
-
args << message if message
|
417
|
-
args << yield if block_given?
|
418
|
-
message = "#{d_str}#{args.join(': ')}"
|
419
|
-
@options[:debug] << message if @options[:debug].is_a?(Array)
|
420
|
-
$stderr.puts(message) if RDF::Turtle.debug?
|
421
|
-
end
|
422
|
-
|
423
422
|
private
|
424
423
|
|
425
424
|
# Checks if l is a valid RDF list, i.e. no nodes have other properties.
|
426
425
|
def is_valid_list?(l)
|
427
|
-
#
|
428
|
-
return RDF::List.new(l, @graph).valid?
|
426
|
+
#log_debug("is_valid_list?") {l.inspect}
|
427
|
+
return RDF::List.new(subject: l, graph: @graph).valid?
|
429
428
|
end
|
430
429
|
|
431
430
|
def do_list(l)
|
432
|
-
list = RDF::List.new(l, @graph)
|
433
|
-
|
431
|
+
list = RDF::List.new(subject: l, graph: @graph)
|
432
|
+
log_debug("do_list") {list.inspect}
|
434
433
|
position = :subject
|
435
434
|
list.each_statement do |st|
|
436
435
|
next unless st.predicate == RDF.first
|
437
|
-
|
436
|
+
log_debug {" list this: #{st.subject} first: #{st.object}[#{position}]"}
|
438
437
|
path(st.object, position)
|
439
438
|
subject_done(st.subject)
|
440
439
|
position = :object
|
@@ -443,12 +442,10 @@ module RDF::Turtle
|
|
443
442
|
|
444
443
|
def collection(node, position)
|
445
444
|
return false if !is_valid_list?(node)
|
446
|
-
#
|
445
|
+
#log_debug("collection") {"#{node.to_ntriples}, #{position}"}
|
447
446
|
|
448
447
|
@output.write(position == :subject ? "(" : " (")
|
449
|
-
|
450
|
-
do_list(node)
|
451
|
-
@depth -= 2
|
448
|
+
log_depth {do_list(node)}
|
452
449
|
@output.write(')')
|
453
450
|
end
|
454
451
|
|
@@ -463,20 +460,20 @@ module RDF::Turtle
|
|
463
460
|
def p_squared(resource, position)
|
464
461
|
return false unless p_squared?(resource, position)
|
465
462
|
|
466
|
-
#
|
463
|
+
#log_debug("p_squared") {"#{resource.to_ntriples}, #{position}"}
|
467
464
|
subject_done(resource)
|
468
465
|
@output.write(position == :subject ? '[' : ' [')
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
466
|
+
log_depth do
|
467
|
+
num_props = predicateObjectList(resource, true)
|
468
|
+
@output.write(num_props > 1 ? "\n#{indent} ]" : "]")
|
469
|
+
end
|
473
470
|
|
474
471
|
true
|
475
472
|
end
|
476
473
|
|
477
474
|
# Default singular resource representation.
|
478
475
|
def p_default(resource, position)
|
479
|
-
#
|
476
|
+
#log_debug("p_default") {"#{resource.to_ntriples}, #{position}"}
|
480
477
|
l = (position == :subject ? "" : " ") + format_term(resource, options)
|
481
478
|
@output.write(l)
|
482
479
|
end
|
@@ -484,7 +481,7 @@ module RDF::Turtle
|
|
484
481
|
# Represent a resource in subject, predicate or object position.
|
485
482
|
# Use either collection, blankNodePropertyList or singular resource notation.
|
486
483
|
def path(resource, position)
|
487
|
-
|
484
|
+
log_debug("path") do
|
488
485
|
"#{resource.to_ntriples}, " +
|
489
486
|
"pos: #{position}, " +
|
490
487
|
"()?: #{is_valid_list?(resource)}, " +
|
@@ -495,7 +492,7 @@ module RDF::Turtle
|
|
495
492
|
end
|
496
493
|
|
497
494
|
def predicate(resource)
|
498
|
-
|
495
|
+
log_debug("predicate") {resource.to_ntriples}
|
499
496
|
if resource == RDF.type
|
500
497
|
@output.write(" a")
|
501
498
|
else
|
@@ -505,7 +502,7 @@ module RDF::Turtle
|
|
505
502
|
|
506
503
|
# Render an objectList having a common subject and predicate
|
507
504
|
def objectList(objects)
|
508
|
-
|
505
|
+
log_debug("objectList") {objects.inspect}
|
509
506
|
return if objects.empty?
|
510
507
|
|
511
508
|
objects.each_with_index do |obj, i|
|
@@ -527,7 +524,7 @@ module RDF::Turtle
|
|
527
524
|
end
|
528
525
|
|
529
526
|
prop_list = sort_properties(properties) - [RDF.first.to_s, RDF.rest.to_s]
|
530
|
-
|
527
|
+
log_debug("predicateObjectList") {prop_list.inspect}
|
531
528
|
return 0 if prop_list.empty?
|
532
529
|
|
533
530
|
@output.write("\n#{indent(2)}") if properties.keys.length > 1 && from_bpl
|
@@ -550,11 +547,9 @@ module RDF::Turtle
|
|
550
547
|
def blankNodePropertyList(subject)
|
551
548
|
return false unless blankNodePropertyList?(subject)
|
552
549
|
|
553
|
-
|
550
|
+
log_debug("blankNodePropertyList") {subject.to_ntriples}
|
554
551
|
@output.write("\n#{indent} [")
|
555
|
-
|
556
|
-
num_props = predicateObjectList(subject, true)
|
557
|
-
@depth -= 1
|
552
|
+
num_props = log_depth {predicateObjectList(subject, true)}
|
558
553
|
@output.write(num_props > 1 ? "\n#{indent} ] ." : "] .")
|
559
554
|
true
|
560
555
|
end
|
@@ -569,7 +564,7 @@ module RDF::Turtle
|
|
569
564
|
end
|
570
565
|
|
571
566
|
def statement(subject)
|
572
|
-
|
567
|
+
log_debug("statement") {"#{subject.to_ntriples}, bnodePL?: #{blankNodePropertyList?(subject)}"}
|
573
568
|
subject_done(subject)
|
574
569
|
blankNodePropertyList(subject) || triples(subject)
|
575
570
|
@output.puts
|
metadata
CHANGED
@@ -1,29 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rdf-turtle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gregg Kellogg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rdf
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.0.0.beta
|
20
|
+
- - "<"
|
18
21
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
22
|
+
version: '3'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- - "
|
27
|
+
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
29
|
+
version: 2.0.0.beta
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: ebnf
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -31,6 +37,9 @@ dependencies:
|
|
31
37
|
- - "~>"
|
32
38
|
- !ruby/object:Gem::Version
|
33
39
|
version: '1.0'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.0.1.beta
|
34
43
|
type: :runtime
|
35
44
|
prerelease: false
|
36
45
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -38,6 +47,9 @@ dependencies:
|
|
38
47
|
- - "~>"
|
39
48
|
- !ruby/object:Gem::Version
|
40
49
|
version: '1.0'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.0.1.beta
|
41
53
|
- !ruby/object:Gem::Dependency
|
42
54
|
name: rspec
|
43
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,58 +82,82 @@ dependencies:
|
|
70
82
|
name: rdf-isomorphic
|
71
83
|
requirement: !ruby/object:Gem::Requirement
|
72
84
|
requirements:
|
73
|
-
- - "
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 2.0.0.beta
|
88
|
+
- - "<"
|
74
89
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
90
|
+
version: '3'
|
76
91
|
type: :development
|
77
92
|
prerelease: false
|
78
93
|
version_requirements: !ruby/object:Gem::Requirement
|
79
94
|
requirements:
|
80
|
-
- - "
|
95
|
+
- - ">="
|
81
96
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
97
|
+
version: 2.0.0.beta
|
98
|
+
- - "<"
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '3'
|
83
101
|
- !ruby/object:Gem::Dependency
|
84
102
|
name: json-ld
|
85
103
|
requirement: !ruby/object:Gem::Requirement
|
86
104
|
requirements:
|
87
|
-
- - "
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: 2.0.0.beta
|
108
|
+
- - "<"
|
88
109
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
110
|
+
version: '3'
|
90
111
|
type: :development
|
91
112
|
prerelease: false
|
92
113
|
version_requirements: !ruby/object:Gem::Requirement
|
93
114
|
requirements:
|
94
|
-
- - "
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 2.0.0.beta
|
118
|
+
- - "<"
|
95
119
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
120
|
+
version: '3'
|
97
121
|
- !ruby/object:Gem::Dependency
|
98
122
|
name: rdf-spec
|
99
123
|
requirement: !ruby/object:Gem::Requirement
|
100
124
|
requirements:
|
101
|
-
- - "
|
125
|
+
- - ">="
|
102
126
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
127
|
+
version: 2.0.0.beta
|
128
|
+
- - "<"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '3'
|
104
131
|
type: :development
|
105
132
|
prerelease: false
|
106
133
|
version_requirements: !ruby/object:Gem::Requirement
|
107
134
|
requirements:
|
108
|
-
- - "
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: 2.0.0.beta
|
138
|
+
- - "<"
|
109
139
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
140
|
+
version: '3'
|
111
141
|
- !ruby/object:Gem::Dependency
|
112
142
|
name: rdf-vocab
|
113
143
|
requirement: !ruby/object:Gem::Requirement
|
114
144
|
requirements:
|
115
|
-
- - "
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: 2.0.0.beta
|
148
|
+
- - "<"
|
116
149
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
150
|
+
version: '3'
|
118
151
|
type: :development
|
119
152
|
prerelease: false
|
120
153
|
version_requirements: !ruby/object:Gem::Requirement
|
121
154
|
requirements:
|
122
|
-
- - "
|
155
|
+
- - ">="
|
123
156
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
157
|
+
version: 2.0.0.beta
|
158
|
+
- - "<"
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '3'
|
125
161
|
- !ruby/object:Gem::Dependency
|
126
162
|
name: rake
|
127
163
|
requirement: !ruby/object:Gem::Requirement
|
@@ -157,7 +193,7 @@ files:
|
|
157
193
|
- lib/rdf/turtle/writer.rb
|
158
194
|
homepage: http://ruby-rdf.github.com/rdf-turtle
|
159
195
|
licenses:
|
160
|
-
-
|
196
|
+
- Unlicense
|
161
197
|
metadata: {}
|
162
198
|
post_install_message:
|
163
199
|
rdoc_options: []
|
@@ -167,17 +203,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
167
203
|
requirements:
|
168
204
|
- - ">="
|
169
205
|
- !ruby/object:Gem::Version
|
170
|
-
version:
|
206
|
+
version: '2.0'
|
171
207
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
208
|
requirements:
|
173
|
-
- - "
|
209
|
+
- - ">"
|
174
210
|
- !ruby/object:Gem::Version
|
175
|
-
version:
|
211
|
+
version: 1.3.1
|
176
212
|
requirements: []
|
177
213
|
rubyforge_project: rdf-turtle
|
178
|
-
rubygems_version: 2.
|
214
|
+
rubygems_version: 2.5.1
|
179
215
|
signing_key:
|
180
216
|
specification_version: 4
|
181
217
|
summary: Turtle reader/writer for Ruby.
|
182
218
|
test_files: []
|
183
|
-
has_rdoc: false
|