rdf 3.1.5 → 3.1.10

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.
@@ -42,7 +42,7 @@ module RDF; class Literal
42
42
  # @see http://www.w3.org/TR/xmlschema11-2/#time
43
43
  def canonicalize!
44
44
  if self.valid?
45
- @string = if has_timezone?
45
+ @string = if timezone?
46
46
  @object.new_offset.new_offset.strftime(FORMAT[0..-4] + 'Z').sub('.000', '')
47
47
  else
48
48
  @object.strftime(FORMAT[0..-4]).sub('.000', '')
@@ -57,7 +57,7 @@ module RDF; class Literal
57
57
  # @return [RDF::Literal]
58
58
  # @see http://www.w3.org/TR/sparql11-query/#func-tz
59
59
  def tz
60
- zone = has_timezone? ? object.zone : ""
60
+ zone = timezone? ? object.zone : ""
61
61
  zone = "Z" if zone == "+00:00"
62
62
  RDF::Literal(zone)
63
63
  end
@@ -79,11 +79,13 @@ module RDF; class Literal
79
79
  #
80
80
  # @return [Boolean]
81
81
  # @since 1.1.6
82
- def has_timezone?
82
+ def timezone?
83
83
  md = self.to_s.match(GRAMMAR)
84
84
  md && !!md[2]
85
85
  end
86
- alias_method :has_tz?, :has_timezone?
86
+ alias_method :tz?, :timezone?
87
+ alias_method :has_tz?, :timezone?
88
+ alias_method :has_timezone?, :timezone?
87
89
 
88
90
  ##
89
91
  # Returns the value as a string.
@@ -101,7 +103,7 @@ module RDF; class Literal
101
103
  # @since 1.1.6
102
104
  def humanize(lang = :en)
103
105
  t = object.strftime("%r")
104
- if has_timezone?
106
+ if timezone?
105
107
  t += if self.tz == 'Z'
106
108
  " UTC"
107
109
  else
@@ -13,18 +13,14 @@ module RDF
13
13
  include RDF::Resource
14
14
 
15
15
  ##
16
- # Defines the maximum number of interned Node references that can be held
17
- # cached in memory at any one time.
16
+ # Cache size may be set through {RDF.config} using `node_cache_size`.
18
17
  #
19
18
  # @note caching interned nodes means that two different invocations using the same symbol will result in the same node, which may not be appropriate depending on the graph from which it is used. RDF requires that bnodes with the same label are, in fact, different bnodes, unless they are used within the same document.
20
- CACHE_SIZE = -1 # unlimited by default
21
-
22
- ##
23
19
  # @return [RDF::Util::Cache]
24
20
  # @private
25
21
  def self.cache
26
22
  require 'rdf/util/cache' unless defined?(::RDF::Util::Cache)
27
- @cache ||= RDF::Util::Cache.new(CACHE_SIZE)
23
+ @cache ||= RDF::Util::Cache.new(RDF.config.node_cache_size)
28
24
  end
29
25
 
30
26
  ##
@@ -96,7 +96,7 @@ module RDF
96
96
  @predicate = predicate
97
97
  @object = object
98
98
  end
99
- @id = @options.delete(:id) if @options.has_key?(:id)
99
+ @id = @options.delete(:id) if @options.key?(:id)
100
100
  @graph_name = @options.delete(:graph_name)
101
101
  initialize!
102
102
  end
@@ -149,10 +149,10 @@ module RDF
149
149
  #
150
150
  # @return [Boolean]
151
151
  def variable?
152
- !(has_subject? && subject.constant? &&
153
- has_predicate? && predicate.constant? &&
154
- has_object? && object.constant? &&
155
- (has_graph? ? graph_name.constant? : true))
152
+ !(subject? && subject.constant? &&
153
+ predicate? && predicate.constant? &&
154
+ object? && object.constant? &&
155
+ (graph? ? graph_name.constant? : true))
156
156
  end
157
157
 
158
158
  ##
@@ -172,10 +172,10 @@ module RDF
172
172
  ##
173
173
  # @return [Boolean]
174
174
  def valid?
175
- has_subject? && subject.resource? && subject.valid? &&
176
- has_predicate? && predicate.uri? && predicate.valid? &&
177
- has_object? && object.term? && object.valid? &&
178
- (has_graph? ? (graph_name.resource? && graph_name.valid?) : true)
175
+ subject? && subject.resource? && subject.valid? &&
176
+ predicate? && predicate.uri? && predicate.valid? &&
177
+ object? && object.term? && object.valid? &&
178
+ (graph? ? (graph_name.resource? && graph_name.valid?) : true)
179
179
  end
180
180
 
181
181
  ##
@@ -216,31 +216,37 @@ module RDF
216
216
 
217
217
  ##
218
218
  # @return [Boolean]
219
- def has_graph?
219
+ def graph?
220
220
  !!graph_name
221
221
  end
222
- alias_method :has_name?, :has_graph?
222
+ alias_method :name?, :graph?
223
+ alias_method :has_graph?, :graph?
224
+ alias_method :has_name?, :graph?
223
225
 
224
226
  ##
225
227
  # @return [Boolean]
226
- def has_subject?
228
+ def subject?
227
229
  !!subject
228
230
  end
231
+ alias_method :has_subject?, :subject?
229
232
 
230
233
  ##
231
234
  # @return [Boolean]
232
- def has_predicate?
235
+ def predicate?
233
236
  !!predicate
234
237
  end
238
+ alias_method :has_predicate?, :predicate?
235
239
 
236
240
  ##
237
241
  # @return [Boolean]
238
- def has_object?
242
+ def object?
239
243
  !!object
240
244
  end
245
+ alias_method :has_object?, :object?
241
246
 
242
247
  ##
243
- # Returns `true` if any resource of this statement is a blank node.
248
+ # Returns `true` if any resource of this statement is a blank node
249
+ # or has an embedded statement including a blank node.
244
250
  #
245
251
  # @return [Boolean]
246
252
  # @since 2.0
@@ -312,10 +318,10 @@ module RDF
312
318
  # @see RDF::Literal#eql?
313
319
  # @see RDF::Query::Variable#eql?
314
320
  def ===(other)
315
- return false if has_object? && !object.eql?(other.object)
316
- return false if has_predicate? && !predicate.eql?(other.predicate)
317
- return false if has_subject? && !subject.eql?(other.subject)
318
- return false if has_graph? && !graph_name.eql?(other.graph_name)
321
+ return false if object? && !object.eql?(other.object)
322
+ return false if predicate? && !predicate.eql?(other.predicate)
323
+ return false if subject? && !subject.eql?(other.subject)
324
+ return false if graph? && !graph_name.eql?(other.graph_name)
319
325
  return true
320
326
  end
321
327
 
@@ -359,6 +365,13 @@ module RDF
359
365
  end
360
366
  alias_method :to_a, :to_triple
361
367
 
368
+ ##
369
+ # Returns an array of all the non-nil non-statement terms.
370
+ # @return [Array(RDF::Term)]
371
+ def terms
372
+ to_quad.map {|t| t.respond_to?(:terms) ? t.terms : t}.flatten.compact
373
+ end
374
+
362
375
  ##
363
376
  # Canonicalizes each unfrozen term in the statement
364
377
  #
@@ -366,10 +379,10 @@ module RDF
366
379
  # @since 1.0.8
367
380
  # @raise [ArgumentError] if any element cannot be canonicalized.
368
381
  def canonicalize!
369
- self.subject.canonicalize! if has_subject? && !self.subject.frozen?
370
- self.predicate.canonicalize! if has_predicate? && !self.predicate.frozen?
371
- self.object.canonicalize! if has_object? && !self.object.frozen?
372
- self.graph_name.canonicalize! if has_graph? && !self.graph_name.frozen?
382
+ self.subject.canonicalize! if subject? && !self.subject.frozen?
383
+ self.predicate.canonicalize! if predicate? && !self.predicate.frozen?
384
+ self.object.canonicalize! if object? && !self.object.frozen?
385
+ self.graph_name.canonicalize! if graph? && !self.graph_name.frozen?
373
386
  self.validate!
374
387
  @hash = nil
375
388
  self
@@ -72,6 +72,14 @@ module RDF
72
72
  self
73
73
  end
74
74
 
75
+ ##
76
+ # Returns an array including just itself.
77
+ #
78
+ # @return [Array<RDF::Value>]
79
+ def terms
80
+ [self]
81
+ end
82
+
75
83
  ##
76
84
  # Returns the base representation of this term.
77
85
  #
data/lib/rdf/model/uri.rb CHANGED
@@ -27,11 +27,6 @@ module RDF
27
27
  class URI
28
28
  include RDF::Resource
29
29
 
30
- ##
31
- # Defines the maximum number of interned URI references that can be held
32
- # cached in memory at any one time.
33
- CACHE_SIZE = -1 # unlimited by default
34
-
35
30
  # IRI components
36
31
  UCSCHAR = Regexp.compile(<<-EOS.gsub(/\s+/, ''))
37
32
  [\\u00A0-\\uD7FF]|[\\uF900-\\uFDCF]|[\\uFDF0-\\uFFEF]|
@@ -117,11 +112,13 @@ module RDF
117
112
  ).freeze
118
113
 
119
114
  ##
115
+ # Cache size may be set through {RDF.config} using `uri_cache_size`.
116
+ #
120
117
  # @return [RDF::Util::Cache]
121
118
  # @private
122
119
  def self.cache
123
120
  require 'rdf/util/cache' unless defined?(::RDF::Util::Cache)
124
- @cache ||= RDF::Util::Cache.new(CACHE_SIZE)
121
+ @cache ||= RDF::Util::Cache.new(RDF.config.uri_cache_size)
125
122
  end
126
123
 
127
124
  ##
@@ -229,13 +226,13 @@ module RDF
229
226
  @value.dup.force_encoding(Encoding::UTF_8) if @value.encoding != Encoding::UTF_8
230
227
  @value.freeze
231
228
  else
232
- %w(
229
+ %i(
233
230
  scheme
234
231
  user password userinfo
235
232
  host port authority
236
233
  path query fragment
237
- ).map(&:to_sym).each do |meth|
238
- if options.has_key?(meth)
234
+ ).each do |meth|
235
+ if options.key?(meth)
239
236
  self.send("#{meth}=".to_sym, options[meth])
240
237
  else
241
238
  self.send(meth)
@@ -311,12 +308,22 @@ module RDF
311
308
  # @param [#to_s] base_uri
312
309
  # @return [RDF::URI]
313
310
  def relativize(base_uri)
314
- if base_uri.to_s.end_with?("/", "#") &&
311
+ if self.to_s.start_with?(base_uri.to_s) && %w(# ?).include?(self.to_s[base_uri.to_s.length, 1]) ||
312
+ base_uri.to_s.end_with?("/", "#") &&
315
313
  self.to_s.start_with?(base_uri.to_s)
316
- RDF::URI(self.to_s[base_uri.to_s.length..-1])
314
+ return RDF::URI(self.to_s[base_uri.to_s.length..-1])
317
315
  else
318
- self
316
+ # Create a list of parents, for which this IRI may be relative.
317
+ u = RDF::URI(base_uri)
318
+ iri_set = u.to_s.end_with?('/') ? [u.to_s] : []
319
+ iri_set << u.to_s while (u = u.parent)
320
+ iri_set.each_with_index do |bb, index|
321
+ next unless self.to_s.start_with?(bb)
322
+ rel = "../" * index + self.to_s[bb.length..-1]
323
+ return rel.empty? ? "./" : rel
324
+ end
319
325
  end
326
+ self
320
327
  end
321
328
 
322
329
  ##
@@ -409,7 +416,7 @@ module RDF
409
416
  # @see http://tools.ietf.org/html/rfc3986#section-5.2.2
410
417
  # @see http://tools.ietf.org/html/rfc3986#section-5.2.3
411
418
  def join(*uris)
412
- joined_parts = object.dup.delete_if {|k, v| [:user, :password, :host, :port].include?(k)}
419
+ joined_parts = object.dup.delete_if {|k, v| %i(user password host port).include?(k)}
413
420
 
414
421
  uris.each do |uri|
415
422
  uri = RDF::URI.new(uri) unless uri.is_a?(RDF::URI)
@@ -573,7 +580,7 @@ module RDF
573
580
  else
574
581
  RDF::URI.new(
575
582
  **object.merge(path: '/').
576
- keep_if {|k, v| [:scheme, :authority, :path].include?(k)})
583
+ keep_if {|k, v| %i(scheme authority path).include?(k)})
577
584
  end
578
585
  end
579
586
 
@@ -581,13 +588,14 @@ module RDF
581
588
  # Returns `true` if this URI is hierarchical and it's path component isn't equal to `/`.
582
589
  #
583
590
  # @example
584
- # RDF::URI('http://example.org/').has_parent? #=> false
585
- # RDF::URI('http://example.org/path/').has_parent? #=> true
591
+ # RDF::URI('http://example.org/').parent? #=> false
592
+ # RDF::URI('http://example.org/path/').parent? #=> true
586
593
  #
587
594
  # @return [Boolean] `true` or `false`
588
- def has_parent?
595
+ def parent?
589
596
  !root?
590
597
  end
598
+ alias_method :has_parent?, :parent?
591
599
 
592
600
  ##
593
601
  # Returns a copy of this URI with the path component ascended to the
@@ -1115,7 +1123,7 @@ module RDF
1115
1123
  # @param [String, #to_s] value
1116
1124
  # @return [RDF::URI] self
1117
1125
  def authority=(value)
1118
- object.delete_if {|k, v| [:user, :password, :host, :port, :userinfo].include?(k)}
1126
+ object.delete_if {|k, v| %i(user password host port userinfo).include?(k)}
1119
1127
  object[:authority] = (value.to_s.dup.force_encoding(Encoding::UTF_8) if value)
1120
1128
  user; password; userinfo; host; port
1121
1129
  @value = nil
@@ -1145,7 +1153,7 @@ module RDF
1145
1153
  # @param [String, #to_s] value
1146
1154
  # @return [RDF::URI] self
1147
1155
  def userinfo=(value)
1148
- object.delete_if {|k, v| [:user, :password, :authority].include?(k)}
1156
+ object.delete_if {|k, v| %i(user password authority).include?(k)}
1149
1157
  object[:userinfo] = (value.to_s.dup.force_encoding(Encoding::UTF_8) if value)
1150
1158
  user; password; authority
1151
1159
  @value = nil
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 || read_rdfstar || fail_subject
72
+ subject = read_uriref || read_node || read_embTriple || fail_subject
73
73
  predicate = read_uriref(intern: true) || fail_predicate
74
- object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
74
+ object = read_uriref || read_node || read_literal || read_embTriple || 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)
@@ -213,7 +213,7 @@ module RDF::NTriples
213
213
  begin
214
214
  read_statement
215
215
  rescue RDF::ReaderError
216
- value = read_uriref || read_node || read_literal || read_rdfstar
216
+ value = read_uriref || read_node || read_literal || read_embTriple
217
217
  log_recover
218
218
  value
219
219
  end
@@ -229,9 +229,9 @@ module RDF::NTriples
229
229
 
230
230
  begin
231
231
  unless blank? || read_comment
232
- subject = read_uriref || read_node || read_rdfstar || fail_subject
232
+ subject = read_uriref || read_node || read_embTriple || fail_subject
233
233
  predicate = read_uriref(intern: true) || fail_predicate
234
- object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
234
+ object = read_uriref || read_node || read_literal || read_embTriple || fail_object
235
235
 
236
236
  if validate? && !read_eos
237
237
  log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
@@ -247,11 +247,11 @@ module RDF::NTriples
247
247
 
248
248
  ##
249
249
  # @return [RDF::Statement]
250
- def read_rdfstar
250
+ def read_embTriple
251
251
  if @options[:rdfstar] && match(ST_START)
252
- subject = read_uriref || read_node || read_rdfstar || fail_subject
252
+ subject = read_uriref || read_node || read_embTriple || fail_subject
253
253
  predicate = read_uriref(intern: true) || fail_predicate
254
- object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
254
+ object = read_uriref || read_node || read_literal || read_embTriple || fail_object
255
255
  if !match(ST_END)
256
256
  log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
257
257
  end
@@ -227,7 +227,7 @@ module RDF::NTriples
227
227
  # @param [RDF::Statement] statement
228
228
  # @param [Hash{Symbol => Object}] options ({})
229
229
  # @return [String]
230
- def format_rdfstar(statement, **options)
230
+ def format_embTriple(statement, **options)
231
231
  "<<%s %s %s>>" % statement.to_a.map { |value| format_term(value, **options) }
232
232
  end
233
233
  ##
@@ -309,8 +309,8 @@ module RDF::NTriples
309
309
  when RDF::Literal
310
310
  # Note, escaping here is more robust than in Term
311
311
  text = quoted(escaped(literal.value))
312
- text << "@#{literal.language}" if literal.has_language?
313
- text << "^^<#{uri_for(literal.datatype)}>" if literal.has_datatype?
312
+ text << "@#{literal.language}" if literal.language?
313
+ text << "^^<#{uri_for(literal.datatype)}>" if literal.datatype?
314
314
  text
315
315
  else
316
316
  quoted(escaped(literal.to_s))
data/lib/rdf/query.rb CHANGED
@@ -247,15 +247,22 @@ module RDF
247
247
  # Optimizes this query by reordering its constituent triple patterns
248
248
  # according to their cost estimates.
249
249
  #
250
+ # Optional patterns have greater cost than non-optional patterns so they will always come after non-optional patterns
251
+ #
250
252
  # @param [Hash{Symbol => Object}] options
251
253
  # any additional options for optimization
252
254
  # @return [self]
253
255
  # @see RDF::Query::Pattern#cost
254
256
  # @since 0.3.0
255
257
  def optimize!(**options)
256
- @patterns.sort! do |a, b|
258
+ optional, required = @patterns.uniq.partition(&:optional?)
259
+ required.sort! do |a, b|
260
+ (a.cost || 0) <=> (b.cost || 0)
261
+ end
262
+ optional.sort! do |a, b|
257
263
  (a.cost || 0) <=> (b.cost || 0)
258
264
  end
265
+ @patterns = required + optional
259
266
  self
260
267
  end
261
268
 
@@ -85,13 +85,13 @@ module RDF; class Query
85
85
  #
86
86
  # @return [Boolean] `true` or `false`
87
87
  # @since 0.3.0
88
- def has_variables?
88
+ def variables?
89
89
  subject && subject.variable? ||
90
90
  predicate && predicate.variable? ||
91
91
  object && object.variable? ||
92
92
  graph_name && graph_name.variable?
93
93
  end
94
- alias_method :variables?, :has_variables?
94
+ alias_method :has_variables?, :variables?
95
95
 
96
96
  ##
97
97
  # Returns `true` if this is an optional pattern.
@@ -111,10 +111,10 @@ module RDF; class Query
111
111
  #
112
112
  # @return [Boolean] `true` or `false`
113
113
  def valid?
114
- (has_subject? ? (subject.resource? || subject.variable?) && subject.valid? : true) &&
115
- (has_predicate? ? (predicate.uri? || predicate.variable?) && predicate.valid? : true) &&
116
- (has_object? ? (object.term? || object.variable?) && object.valid? : true) &&
117
- (has_graph? ? (graph_name.resource? || graph_name.variable?) && graph_name.valid? : true)
114
+ (subject? ? (subject.resource? || subject.variable?) && subject.valid? : true) &&
115
+ (predicate? ? (predicate.uri? || predicate.variable?) && predicate.valid? : true) &&
116
+ (object? ? (object.term? || object.variable?) && object.valid? : true) &&
117
+ (graph? ? (graph_name.resource? || graph_name.variable?) && graph_name.valid? : true)
118
118
  rescue NoMethodError
119
119
  false
120
120
  end
@@ -181,16 +181,10 @@ module RDF; class Query
181
181
 
182
182
  # No, some terms actually refer to the same variable...
183
183
  else
184
- # Figure out which terms refer to the same variable:
185
- terms = variables.each_key.find do |name|
186
- terms = variable_terms(name)
187
- break terms if terms.size > 1
188
- end
184
+ # Considering embedding, figure out if variables that may appear more than once resolve to the same value.
185
+ vars = variables.keys
189
186
  queryable.query(query).select do |statement|
190
- # Only yield those matching statements where the variable
191
- # constraint is also satisfied:
192
- # FIXME: `Array#uniq` uses `#eql?` and `#hash`, not `#==`
193
- if terms.map { |term| statement.send(term) }.uniq.size.equal?(1)
187
+ if vars.all? {|var| self.var_values(var, statement).uniq.size == 1}
194
188
  yield statement if block_given?
195
189
  true
196
190
  end
@@ -220,8 +214,8 @@ module RDF; class Query
220
214
  solution[predicate.to_sym] = statement.predicate if predicate.is_a?(Variable)
221
215
  solution[object.to_sym] = statement.object if object.is_a?(Variable)
222
216
  solution[graph_name.to_sym] = statement.graph_name if graph_name.is_a?(Variable)
223
- solution.merge!(subject.solution(statement.subject)) if subject.is_a?(Pattern)
224
- solution.merge!(object.solution(statement.object)) if object.is_a?(Pattern)
217
+ solution.merge!(subject.solution(statement.subject)) if subject.respond_to?(:solution)
218
+ solution.merge!(object.solution(statement.object)) if object.respond_to?(:solution)
225
219
  end
226
220
  end
227
221
 
@@ -234,8 +228,11 @@ module RDF; class Query
234
228
  # @param [Symbol, #to_sym] name
235
229
  # an optional variable name
236
230
  # @return [Array<Symbol>]
231
+ # @deprecated use {#var_values} instead
237
232
  # @since 0.3.0
238
233
  def variable_terms(name = nil)
234
+ warn "[DEPRECATION] RDF::Query::Pattern#variable_terms is deprecated and will be removed in a future version.\n" +
235
+ "Called from #{Gem.location_of_caller.join(':')}"
239
236
  terms = []
240
237
  terms << :subject if subject.is_a?(Variable) && (!name || name.eql?(subject.name))
241
238
  terms << :predicate if predicate.is_a?(Variable) && (!name || name.eql?(predicate.name))
@@ -244,6 +241,20 @@ module RDF; class Query
244
241
  terms
245
242
  end
246
243
 
244
+ ##
245
+ # Returns all values the statement in the same pattern position
246
+ #
247
+ # @param [Symbol] var
248
+ # @param [RDF::Statement] statement
249
+ # @return [Array<RDF::Term>]
250
+ def var_values(var, statement)
251
+ %i(subject predicate object graph_name).map do |position|
252
+ po = self.send(position)
253
+ so = statement.send(position)
254
+ po.var_values(var, so) if po.respond_to?(:var_values)
255
+ end.flatten.compact
256
+ end
257
+
247
258
  ##
248
259
  # Returns the number of variables in this pattern.
249
260
  #
@@ -254,7 +265,7 @@ module RDF; class Query
254
265
  def variable_count
255
266
  [subject, predicate, object, graph_name].inject(0) do |memo, term|
256
267
  memo += (term.is_a?(Variable) ? 1 :
257
- (term.is_a?(Pattern) ? term.variable_count : 0))
268
+ (term.respond_to?(:variable_count) ? term.variable_count : 0))
258
269
  end
259
270
  end
260
271
  alias_method :cardinality, :variable_count
@@ -311,9 +322,9 @@ module RDF; class Query
311
322
  def bindings
312
323
  bindings = {}
313
324
  bindings.merge!(subject.bindings) if subject && subject.variable?
314
- bindings.merge!(predicate.bindings) if predicate.is_a?(Variable)
325
+ bindings.merge!(predicate.bindings) if predicate && predicate.variable?
315
326
  bindings.merge!(object.bindings) if object && object.variable?
316
- bindings.merge!(graph_name.bindings) if graph_name.is_a?(Variable)
327
+ bindings.merge!(graph_name.bindings) if graph_name && graph_name.variable?
317
328
  bindings
318
329
  end
319
330
 
@@ -354,24 +365,7 @@ module RDF; class Query
354
365
  #
355
366
  # @return [String]
356
367
  def to_s
357
- StringIO.open do |buffer| # FIXME in RDF::Statement
358
- buffer << 'OPTIONAL ' if optional?
359
- buffer << [subject, predicate, object].map do |r|
360
- if r.is_a?(RDF::Query::Variable)
361
- r.to_s
362
- elsif r.is_a?(RDF::Query::Pattern)
363
- "<<#{r.to_s[0..-3]}>>"
364
- else
365
- RDF::NTriples.serialize(r)
366
- end
367
- end.join(" ")
368
- buffer << case graph_name
369
- when nil, false then " ."
370
- when Variable then " #{graph_name.to_s} ."
371
- else " #{RDF::NTriples.serialize(graph_name)} ."
372
- end
373
- buffer.string
374
- end
368
+ (optional? ? 'OPTIONAL ' : '') + super
375
369
  end
376
370
  end # Pattern
377
371
  end; end # RDF::Query