rdf-turtle 1.99.0 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|