rdf 3.1.0 → 3.1.5
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/AUTHORS +1 -1
- data/README.md +43 -9
- data/VERSION +1 -1
- data/bin/rdf +2 -2
- data/etc/doap.nt +74 -80
- data/lib/rdf.rb +16 -11
- data/lib/rdf/changeset.rb +86 -18
- data/lib/rdf/cli.rb +11 -3
- data/lib/rdf/mixin/enumerable.rb +1 -0
- data/lib/rdf/mixin/mutable.rb +3 -13
- data/lib/rdf/mixin/queryable.rb +8 -0
- data/lib/rdf/mixin/writable.rb +9 -14
- data/lib/rdf/model/dataset.rb +1 -1
- data/lib/rdf/model/graph.rb +3 -0
- data/lib/rdf/model/statement.rb +30 -7
- data/lib/rdf/model/uri.rb +10 -10
- data/lib/rdf/nquads.rb +2 -2
- data/lib/rdf/ntriples.rb +6 -4
- data/lib/rdf/ntriples/reader.rb +28 -3
- data/lib/rdf/ntriples/writer.rb +9 -0
- data/lib/rdf/query.rb +4 -1
- data/lib/rdf/query/hash_pattern_normalizer.rb +9 -8
- data/lib/rdf/query/pattern.rb +49 -16
- data/lib/rdf/query/solution.rb +20 -1
- data/lib/rdf/query/solutions.rb +15 -5
- data/lib/rdf/query/variable.rb +17 -5
- data/lib/rdf/reader.rb +65 -20
- data/lib/rdf/repository.rb +27 -13
- data/lib/rdf/util.rb +6 -5
- data/lib/rdf/util/cache.rb +2 -2
- data/lib/rdf/util/coercions.rb +60 -0
- data/lib/rdf/util/file.rb +3 -3
- data/lib/rdf/util/logger.rb +1 -1
- data/lib/rdf/vocab/owl.rb +401 -86
- data/lib/rdf/vocab/rdfs.rb +81 -18
- data/lib/rdf/vocab/rdfv.rb +122 -1
- data/lib/rdf/vocab/writer.rb +43 -4
- data/lib/rdf/vocab/xsd.rb +203 -2
- data/lib/rdf/vocabulary.rb +105 -11
- data/lib/rdf/writer.rb +21 -5
- metadata +9 -8
data/lib/rdf/cli.rb
CHANGED
@@ -8,7 +8,7 @@ begin
|
|
8
8
|
require 'linkeddata'
|
9
9
|
rescue LoadError
|
10
10
|
# Silently load without linkeddata, but try some others
|
11
|
-
%w(
|
11
|
+
%w(microdata n3 rdfa rdfxml reasoner tabular trig trix turtle vocab xsd json/ld ld/patch).each do |ser|
|
12
12
|
begin
|
13
13
|
require ser.include?('/') ? ser : "rdf/#{ser}"
|
14
14
|
rescue LoadError
|
@@ -296,6 +296,12 @@ module RDF
|
|
296
296
|
control: :none,
|
297
297
|
on: ["-o", "--output FILE"],
|
298
298
|
description: "File to write output, defaults to STDOUT") {|arg| File.open(arg, "w")},
|
299
|
+
RDF::CLI::Option.new(
|
300
|
+
symbol: :ordered,
|
301
|
+
control: :checkbox,
|
302
|
+
datatype: TrueClass,
|
303
|
+
on: ["--ordered"],
|
304
|
+
description: "Use order preserving repository"),
|
299
305
|
RDF::CLI::Option.new(
|
300
306
|
symbol: :format,
|
301
307
|
control: :select,
|
@@ -495,14 +501,16 @@ module RDF
|
|
495
501
|
options[:format] = options[:format].to_sym if options[:format]
|
496
502
|
options[:output_format] = options[:output_format].to_sym if options[:output_format]
|
497
503
|
|
498
|
-
@repository =
|
504
|
+
@repository = options[:ordered] ?
|
505
|
+
[].extend(RDF::Enumerable, RDF::Queryable) :
|
506
|
+
RDF::Repository.new
|
499
507
|
|
500
508
|
# Parse input files if any command requires it
|
501
509
|
if cmds.any? {|c| COMMANDS[c.to_sym][:parse]}
|
502
510
|
start = Time.new
|
503
511
|
count = 0
|
504
512
|
self.parse(args, **options) do |reader|
|
505
|
-
@repository <<
|
513
|
+
reader.each_statement {|st| @repository << st}
|
506
514
|
end
|
507
515
|
secs = Time.new - start
|
508
516
|
options[:logger].info "Parsed #{repository.count} statements with #{@readers.join(', ')} in #{secs} seconds @ #{count/secs} statements/second."
|
data/lib/rdf/mixin/enumerable.rb
CHANGED
@@ -71,6 +71,7 @@ module RDF
|
|
71
71
|
# * `:literal_equality' preserves [term-equality](https://www.w3.org/TR/rdf11-concepts/#dfn-literal-term-equality) for literals. Literals are equal only if their lexical values and datatypes are equal, character by character. Literals may be "inlined" to value-space for efficiency only if `:literal_equality` is `false`.
|
72
72
|
# * `:validity` allows a concrete Enumerable implementation to indicate that it does or does not support valididty checking. By default implementations are assumed to support validity checking.
|
73
73
|
# * `:skolemize` supports [Skolemization](https://www.w3.org/wiki/BnodeSkolemization) of an `Enumerable`. Implementations supporting this feature must implement a `#skolemize` method, taking a base URI used for minting URIs for BNodes as stable identifiers and a `#deskolemize` method, also taking a base URI used for turning URIs having that prefix back into the same BNodes which were originally skolemized.
|
74
|
+
# * `:rdfstar` supports RDF* where statements may be subjects or objects of other statements.
|
74
75
|
#
|
75
76
|
# @param [Symbol, #to_sym] feature
|
76
77
|
# @return [Boolean]
|
data/lib/rdf/mixin/mutable.rb
CHANGED
@@ -9,6 +9,7 @@ module RDF
|
|
9
9
|
extend RDF::Util::Aliasing::LateBound
|
10
10
|
include RDF::Readable
|
11
11
|
include RDF::Writable
|
12
|
+
include RDF::Util::Coercions
|
12
13
|
|
13
14
|
##
|
14
15
|
# Returns `true` if `self` is mutable.
|
@@ -154,20 +155,9 @@ module RDF
|
|
154
155
|
def delete(*statements)
|
155
156
|
raise TypeError.new("#{self} is immutable") if immutable?
|
156
157
|
|
157
|
-
statements
|
158
|
-
|
159
|
-
when value.respond_to?(:each_statement)
|
160
|
-
delete_statements(value)
|
161
|
-
nil
|
162
|
-
when (statement = Statement.from(value)).constant?
|
163
|
-
statement
|
164
|
-
else
|
165
|
-
delete_statements(query(value))
|
166
|
-
nil
|
167
|
-
end
|
158
|
+
coerce_statements(statements, query: true, constant: true) do |value|
|
159
|
+
delete_statements(value)
|
168
160
|
end
|
169
|
-
statements.compact!
|
170
|
-
delete_statements(statements) unless statements.empty?
|
171
161
|
|
172
162
|
return self
|
173
163
|
end
|
data/lib/rdf/mixin/queryable.rb
CHANGED
@@ -128,6 +128,14 @@ module RDF
|
|
128
128
|
# method in order to provide for storage-specific optimized triple
|
129
129
|
# pattern matching.
|
130
130
|
#
|
131
|
+
# ## RDFStar (RDF*)
|
132
|
+
#
|
133
|
+
# Statements may have embedded statements as either a subject or object, recursively.
|
134
|
+
#
|
135
|
+
# Patterns may also have embedded patterns as either a subject or object, recursively.
|
136
|
+
#
|
137
|
+
# When matching, match an embedded pattern against embedded statements, recursively. (see {RDF::Query::Pattern#eql?})
|
138
|
+
#
|
131
139
|
# @param [RDF::Query::Pattern] pattern
|
132
140
|
# the query pattern to match
|
133
141
|
# @param [Hash{Symbol => Object}] options ({})
|
data/lib/rdf/mixin/writable.rb
CHANGED
@@ -7,6 +7,7 @@ module RDF
|
|
7
7
|
# @see RDF::Repository
|
8
8
|
module Writable
|
9
9
|
extend RDF::Util::Aliasing::LateBound
|
10
|
+
include RDF::Util::Coercions
|
10
11
|
|
11
12
|
##
|
12
13
|
# Returns `true` if `self` is writable.
|
@@ -53,31 +54,20 @@ module RDF
|
|
53
54
|
# @overload insert(*statements)
|
54
55
|
# @param [Array<RDF::Statement>] statements
|
55
56
|
# @return [self]
|
57
|
+
# @raise [ArgumentError] on an attempt to insert an embedded statement when it is not supported
|
56
58
|
#
|
57
59
|
# @overload insert(statements)
|
58
60
|
# @param [Enumerable<RDF::Statement>] statements
|
59
61
|
# @return [self]
|
62
|
+
# @raise [ArgumentError] on an attempt to insert an embedded statement when it is not supported
|
60
63
|
def insert(*statements)
|
61
|
-
statements
|
62
|
-
case
|
63
|
-
when value.respond_to?(:each_statement)
|
64
|
-
insert_statements(value)
|
65
|
-
nil
|
66
|
-
when (statement = Statement.from(value))
|
67
|
-
statement
|
68
|
-
else
|
69
|
-
raise ArgumentError.new("not a valid statement: #{value.inspect}")
|
70
|
-
end
|
71
|
-
end
|
72
|
-
statements.compact!
|
73
|
-
insert_statements(statements) unless statements.empty?
|
64
|
+
coerce_statements(statements) { |value| insert_statements value }
|
74
65
|
|
75
66
|
return self
|
76
67
|
end
|
77
68
|
alias_method :insert!, :insert
|
78
69
|
|
79
70
|
protected
|
80
|
-
|
81
71
|
##
|
82
72
|
# Inserts statements from the given RDF reader into the underlying
|
83
73
|
# storage or output stream.
|
@@ -132,10 +122,14 @@ module RDF
|
|
132
122
|
#
|
133
123
|
# @param [RDF::Enumerable] statements
|
134
124
|
# @return [void]
|
125
|
+
# @raise [ArgumentError] on an attempt to insert an embedded statement when it is not supported
|
135
126
|
# @since 0.1.6
|
136
127
|
def insert_statements(statements)
|
137
128
|
each = statements.respond_to?(:each_statement) ? :each_statement : :each
|
138
129
|
statements.__send__(each) do |statement|
|
130
|
+
if statement.embedded? && respond_to?(:supports?) && !supports?(:rdfstar)
|
131
|
+
raise ArgumentError, "Wriable does not support embedded statements"
|
132
|
+
end
|
139
133
|
insert_statement(statement)
|
140
134
|
end
|
141
135
|
end
|
@@ -150,6 +144,7 @@ module RDF
|
|
150
144
|
#
|
151
145
|
# @param [RDF::Statement] statement
|
152
146
|
# @return [void]
|
147
|
+
# @raise [ArgumentError] on an attempt to insert an embedded statement when it is not supported
|
153
148
|
# @abstract
|
154
149
|
def insert_statement(statement)
|
155
150
|
raise NotImplementedError.new("#{self.class}#insert_statement")
|
data/lib/rdf/model/dataset.rb
CHANGED
data/lib/rdf/model/graph.rb
CHANGED
@@ -283,6 +283,9 @@ module RDF
|
|
283
283
|
# @private
|
284
284
|
# @see RDF::Mutable#insert
|
285
285
|
def insert_statement(statement)
|
286
|
+
if statement.embedded? && !@data.supports?(:rdfstar)
|
287
|
+
raise ArgumentError, "Graph does not support embedded statements"
|
288
|
+
end
|
286
289
|
statement = statement.dup
|
287
290
|
statement.graph_name = graph_name
|
288
291
|
@data.insert(statement)
|
data/lib/rdf/model/statement.rb
CHANGED
@@ -26,7 +26,7 @@ module RDF
|
|
26
26
|
# RDF::Statement(s, p, "o")
|
27
27
|
#
|
28
28
|
class Statement
|
29
|
-
include RDF::
|
29
|
+
include RDF::Resource
|
30
30
|
|
31
31
|
##
|
32
32
|
# @private
|
@@ -112,7 +112,7 @@ module RDF
|
|
112
112
|
elsif @subject.nil?
|
113
113
|
nil
|
114
114
|
else
|
115
|
-
raise ArgumentError, "expected subject to be nil or a
|
115
|
+
raise ArgumentError, "expected subject to be nil or a resource, was #{@subject.inspect}"
|
116
116
|
end
|
117
117
|
@predicate = Node.intern(@predicate) if @predicate.is_a?(Symbol)
|
118
118
|
@object = if @object.is_a?(Value)
|
@@ -124,6 +124,15 @@ module RDF
|
|
124
124
|
else
|
125
125
|
Literal.new(@object)
|
126
126
|
end
|
127
|
+
@graph_name = if @graph_name.is_a?(Value)
|
128
|
+
@graph_name.to_term
|
129
|
+
elsif @graph_name.is_a?(Symbol)
|
130
|
+
Node.intern(@graph_name)
|
131
|
+
elsif !@graph_name
|
132
|
+
@graph_name
|
133
|
+
else
|
134
|
+
raise ArgumentError, "expected graph_name to be nil or a resource, was #{@graph_name.inspect}"
|
135
|
+
end
|
127
136
|
end
|
128
137
|
|
129
138
|
##
|
@@ -140,10 +149,18 @@ module RDF
|
|
140
149
|
#
|
141
150
|
# @return [Boolean]
|
142
151
|
def variable?
|
143
|
-
!(has_subject? && subject.
|
144
|
-
has_predicate? && predicate.
|
145
|
-
has_object? &&
|
146
|
-
(has_graph? ? graph_name.
|
152
|
+
!(has_subject? && subject.constant? &&
|
153
|
+
has_predicate? && predicate.constant? &&
|
154
|
+
has_object? && object.constant? &&
|
155
|
+
(has_graph? ? graph_name.constant? : true))
|
156
|
+
end
|
157
|
+
|
158
|
+
##
|
159
|
+
# Returns `true` if any element of the statement is, itself, a statement.
|
160
|
+
#
|
161
|
+
# @return [Boolean]
|
162
|
+
def embedded?
|
163
|
+
subject && subject.statement? || object && object.statement?
|
147
164
|
end
|
148
165
|
|
149
166
|
##
|
@@ -386,7 +403,13 @@ module RDF
|
|
386
403
|
# @return [String]
|
387
404
|
def to_s
|
388
405
|
(graph_name ? to_quad : to_triple).map do |term|
|
389
|
-
term.
|
406
|
+
if term.is_a?(Statement)
|
407
|
+
"<<#{term.to_s[0..-3]}>>"
|
408
|
+
elsif term.respond_to?(:to_base)
|
409
|
+
term.to_base
|
410
|
+
else
|
411
|
+
term.inspect
|
412
|
+
end
|
390
413
|
end.join(" ") + " ."
|
391
414
|
end
|
392
415
|
|
data/lib/rdf/model/uri.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
require '
|
2
|
+
require 'cgi'
|
3
3
|
|
4
4
|
module RDF
|
5
5
|
##
|
@@ -400,7 +400,7 @@ module RDF
|
|
400
400
|
# @example Joining two URIs
|
401
401
|
# RDF::URI.new('http://example.org/foo/bar').join('/foo')
|
402
402
|
# #=> RDF::URI('http://example.org/foo')
|
403
|
-
# @see <
|
403
|
+
# @see <https://github.com/ruby-rdf/rdf-spec/blob/master/lib/rdf/spec/uri.rb>
|
404
404
|
# @see <http://tools.ietf.org/html/rfc3986#section-5.2>
|
405
405
|
# @see RDF::URI#/
|
406
406
|
# @see RDF::URI#+
|
@@ -471,7 +471,7 @@ module RDF
|
|
471
471
|
# @see RDF::URI#+
|
472
472
|
# @see RDF::URI#join
|
473
473
|
# @see <http://tools.ietf.org/html/rfc3986#section-5.2>
|
474
|
-
# @see <
|
474
|
+
# @see <https://github.com/ruby-rdf/rdf-spec/blob/master/lib/rdf/spec/uri.rb>
|
475
475
|
# @example Building a HTTP URL
|
476
476
|
# RDF::URI.new('http://example.org') / 'jhacker' / 'foaf.ttl'
|
477
477
|
# #=> RDF::URI('http://example.org/jhacker/foaf.ttl')
|
@@ -846,7 +846,7 @@ module RDF
|
|
846
846
|
parts[:user] = (user.dup.force_encoding(Encoding::UTF_8) if user)
|
847
847
|
parts[:password] = (password.dup.force_encoding(Encoding::UTF_8) if password)
|
848
848
|
parts[:host] = (host.dup.force_encoding(Encoding::UTF_8) if host)
|
849
|
-
parts[:port] = (
|
849
|
+
parts[:port] = (CGI.unescape(port).to_i if port)
|
850
850
|
parts[:path] = (path.to_s.dup.force_encoding(Encoding::UTF_8) unless path.empty?)
|
851
851
|
parts[:query] = (query[1..-1].dup.force_encoding(Encoding::UTF_8) if query)
|
852
852
|
parts[:fragment] = (fragment[1..-1].dup.force_encoding(Encoding::UTF_8) if fragment)
|
@@ -902,7 +902,7 @@ module RDF
|
|
902
902
|
# Normalized version of user
|
903
903
|
# @return [String]
|
904
904
|
def normalized_user
|
905
|
-
URI.encode(
|
905
|
+
URI.encode(CGI.unescape(user), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/).force_encoding(Encoding::UTF_8) if user
|
906
906
|
end
|
907
907
|
|
908
908
|
##
|
@@ -928,7 +928,7 @@ module RDF
|
|
928
928
|
# Normalized version of password
|
929
929
|
# @return [String]
|
930
930
|
def normalized_password
|
931
|
-
URI.encode(
|
931
|
+
URI.encode(CGI.unescape(password), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/).force_encoding(Encoding::UTF_8) if password
|
932
932
|
end
|
933
933
|
|
934
934
|
HOST_FROM_AUTHORITY_RE = /(?:[^@]+@)?([^:]+)(?::.*)?$/.freeze
|
@@ -1180,8 +1180,8 @@ module RDF
|
|
1180
1180
|
inject(return_type == Hash ? {} : []) do |memo,kv|
|
1181
1181
|
k,v = kv.to_s.split('=', 2)
|
1182
1182
|
next if k.to_s.empty?
|
1183
|
-
k =
|
1184
|
-
v =
|
1183
|
+
k = CGI.unescape(k)
|
1184
|
+
v = CGI.unescape(v) if v
|
1185
1185
|
if return_type == Hash
|
1186
1186
|
case memo[k]
|
1187
1187
|
when nil then memo[k] = v
|
@@ -1293,9 +1293,9 @@ module RDF
|
|
1293
1293
|
def normalize_segment(value, expr, downcase = false)
|
1294
1294
|
if value
|
1295
1295
|
value = value.dup.force_encoding(Encoding::UTF_8)
|
1296
|
-
decoded =
|
1296
|
+
decoded = CGI.unescape(value)
|
1297
1297
|
decoded.downcase! if downcase
|
1298
|
-
URI.encode(decoded, /[^(?:#{expr})]/)
|
1298
|
+
URI.encode(decoded, /[^(?:#{expr})]/).force_encoding(Encoding::UTF_8)
|
1299
1299
|
end
|
1300
1300
|
end
|
1301
1301
|
|
data/lib/rdf/nquads.rb
CHANGED
@@ -69,9 +69,9 @@ module RDF
|
|
69
69
|
|
70
70
|
begin
|
71
71
|
unless blank? || read_comment
|
72
|
-
subject = read_uriref || read_node || fail_subject
|
72
|
+
subject = read_uriref || read_node || read_rdfstar || fail_subject
|
73
73
|
predicate = read_uriref(intern: true) || fail_predicate
|
74
|
-
object = read_uriref || read_node || read_literal || fail_object
|
74
|
+
object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
|
75
75
|
graph_name = read_uriref || read_node
|
76
76
|
if validate? && !read_eos
|
77
77
|
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
data/lib/rdf/ntriples.rb
CHANGED
@@ -15,15 +15,17 @@ module RDF
|
|
15
15
|
#
|
16
16
|
# <https://rubygems.org/gems/rdf> <http://purl.org/dc/terms/title> "rdf" .
|
17
17
|
#
|
18
|
-
#
|
19
|
-
#
|
18
|
+
# ## RDFStar (RDF*)
|
19
|
+
#
|
20
|
+
# Supports statements as resources using `<<s p o>>`.
|
21
|
+
#
|
22
|
+
# ## Installation
|
20
23
|
#
|
21
24
|
# This is the only RDF serialization format that is directly supported by
|
22
25
|
# RDF.rb. Support for other formats is available in the form of add-on
|
23
26
|
# gems, e.g. 'rdf-xml' or 'rdf-json'.
|
24
27
|
#
|
25
|
-
# Documentation
|
26
|
-
# -------------
|
28
|
+
# ## Documentation
|
27
29
|
#
|
28
30
|
# * {RDF::NTriples::Format}
|
29
31
|
# * {RDF::NTriples::Reader}
|
data/lib/rdf/ntriples/reader.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'strscan'
|
4
|
+
|
2
5
|
module RDF::NTriples
|
3
6
|
##
|
4
7
|
# N-Triples parser.
|
@@ -25,6 +28,10 @@ module RDF::NTriples
|
|
25
28
|
# end
|
26
29
|
# end
|
27
30
|
#
|
31
|
+
# ** RDFStar (RDF*)
|
32
|
+
#
|
33
|
+
# Supports statements as resources using `<<s p o>>`.
|
34
|
+
#
|
28
35
|
# @see http://www.w3.org/TR/rdf-testcases/#ntriples
|
29
36
|
# @see http://www.w3.org/TR/n-triples/
|
30
37
|
class Reader < RDF::Reader
|
@@ -70,6 +77,10 @@ module RDF::NTriples
|
|
70
77
|
# 22
|
71
78
|
STRING_LITERAL_QUOTE = /"((?:[^\"\\\n\r]|#{ECHAR}|#{UCHAR})*)"/.freeze
|
72
79
|
|
80
|
+
# RDF*
|
81
|
+
ST_START = /^<</.freeze
|
82
|
+
ST_END = /^\s*>>/.freeze
|
83
|
+
|
73
84
|
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar
|
74
85
|
COMMENT = /^#\s*(.*)$/.freeze
|
75
86
|
NODEID = /^#{BLANK_NODE_LABEL}/.freeze
|
@@ -202,7 +213,7 @@ module RDF::NTriples
|
|
202
213
|
begin
|
203
214
|
read_statement
|
204
215
|
rescue RDF::ReaderError
|
205
|
-
value = read_uriref || read_node || read_literal
|
216
|
+
value = read_uriref || read_node || read_literal || read_rdfstar
|
206
217
|
log_recover
|
207
218
|
value
|
208
219
|
end
|
@@ -218,9 +229,9 @@ module RDF::NTriples
|
|
218
229
|
|
219
230
|
begin
|
220
231
|
unless blank? || read_comment
|
221
|
-
subject = read_uriref || read_node || fail_subject
|
232
|
+
subject = read_uriref || read_node || read_rdfstar || fail_subject
|
222
233
|
predicate = read_uriref(intern: true) || fail_predicate
|
223
|
-
object = read_uriref || read_node || read_literal || fail_object
|
234
|
+
object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
|
224
235
|
|
225
236
|
if validate? && !read_eos
|
226
237
|
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
@@ -234,6 +245,20 @@ module RDF::NTriples
|
|
234
245
|
end
|
235
246
|
end
|
236
247
|
|
248
|
+
##
|
249
|
+
# @return [RDF::Statement]
|
250
|
+
def read_rdfstar
|
251
|
+
if @options[:rdfstar] && match(ST_START)
|
252
|
+
subject = read_uriref || read_node || read_rdfstar || fail_subject
|
253
|
+
predicate = read_uriref(intern: true) || fail_predicate
|
254
|
+
object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
|
255
|
+
if !match(ST_END)
|
256
|
+
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
257
|
+
end
|
258
|
+
RDF::Statement.new(subject, predicate, object)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
237
262
|
##
|
238
263
|
# @return [Boolean]
|
239
264
|
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (comment)
|
data/lib/rdf/ntriples/writer.rb
CHANGED
@@ -221,6 +221,15 @@ module RDF::NTriples
|
|
221
221
|
format_triple(*statement.to_triple, **options)
|
222
222
|
end
|
223
223
|
|
224
|
+
##
|
225
|
+
# Returns the N-Triples representation of an RDF* reified statement.
|
226
|
+
#
|
227
|
+
# @param [RDF::Statement] statement
|
228
|
+
# @param [Hash{Symbol => Object}] options ({})
|
229
|
+
# @return [String]
|
230
|
+
def format_rdfstar(statement, **options)
|
231
|
+
"<<%s %s %s>>" % statement.to_a.map { |value| format_term(value, **options) }
|
232
|
+
end
|
224
233
|
##
|
225
234
|
# Returns the N-Triples representation of a triple.
|
226
235
|
#
|
data/lib/rdf/query.rb
CHANGED
@@ -289,6 +289,8 @@ module RDF
|
|
289
289
|
# any additional keyword options
|
290
290
|
# @option options [Hash{Symbol => RDF::Term}] bindings
|
291
291
|
# optional variable bindings to use
|
292
|
+
# @option options [Boolean] :optimize
|
293
|
+
# Optimize query before execution.
|
292
294
|
# @option options [RDF::Query::Solutions] solutions
|
293
295
|
# optional initial solutions for chained queries
|
294
296
|
# @yield [solution]
|
@@ -311,6 +313,7 @@ module RDF
|
|
311
313
|
return @solutions
|
312
314
|
end
|
313
315
|
|
316
|
+
self.optimize! if options[:optimize]
|
314
317
|
patterns = @patterns
|
315
318
|
graph_name = name if graph_name.nil?
|
316
319
|
@graph_name = graph_name unless graph_name.nil?
|
@@ -505,7 +508,7 @@ module RDF
|
|
505
508
|
# @return [RDF::Query]
|
506
509
|
def dup
|
507
510
|
patterns = @patterns.map {|p| p.dup}
|
508
|
-
Query.new(patterns, solutions: @solutions.dup, **options)
|
511
|
+
Query.new(patterns, graph_name: graph_name, solutions: @solutions.dup, **options)
|
509
512
|
end
|
510
513
|
|
511
514
|
##
|