rdf-virtuoso 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ require 'active_rdf/association_reflection'
2
+
3
+ module ActiveRDF
4
+ module Reflections
5
+ # Returns a hash containing all AssociationReflection objects for the current class
6
+ # Example:
7
+ #
8
+ # Invoice.reflections
9
+ # Account.reflections
10
+ #
11
+ def reflections
12
+ read_inheritable_attribute(:reflections) || write_inheritable_attribute(:reflections, {})
13
+ end
14
+
15
+ def reflect_on_association(association)
16
+ reflections[association].is_a?(AssociationReflection) ? reflections[association] : nil
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ module ActiveRDF
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 10
6
+ PRE = nil
7
+
8
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ module RDF
2
+ module Virtuoso
3
+ autoload :Repository, 'rdf/virtuoso/repository'
4
+ autoload :Query, 'rdf/virtuoso/query'
5
+ autoload :Prefixes, 'rdf/virtuoso/prefixes'
6
+ autoload :Parser, 'rdf/virtuoso/parser'
7
+ end
8
+ end
@@ -0,0 +1,42 @@
1
+ module RDF
2
+ module Virtuoso
3
+ module Parser
4
+ class JSON
5
+
6
+ def self.call(response)
7
+ parse_json_bindings(response)
8
+ end
9
+
10
+ def self.parse_json_bindings(response)
11
+ case
12
+ when response['boolean']
13
+ response['boolean']
14
+ when response['results']
15
+ solutions = response['results']['bindings'].map do |row|
16
+ row = row.inject({}) do |cols, (name, value)|
17
+ cols.merge(name.to_sym => parse_json_value(value))
18
+ end
19
+ RDF::Query::Solution.new(row)
20
+ end
21
+ RDF::Query::Solutions.new(solutions)
22
+ end
23
+ end
24
+
25
+ def self.parse_json_value(value, nodes = {})
26
+ case value['type'].to_sym
27
+ when :bnode
28
+ nodes[id = value['value']] ||= RDF::Node.new(id)
29
+ when :uri
30
+ RDF::URI.new(value['value'])
31
+ when :literal
32
+ RDF::Literal.new(value['value'], :language => value['xml:lang'])
33
+ when :'typed-literal'
34
+ RDF::Literal.new(value['value'], :datatype => value['datatype'])
35
+ else nil
36
+ end
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,54 @@
1
+ module RDF::Virtuoso
2
+ require 'uri'
3
+
4
+ class UnProcessable; end
5
+ class Prefixes
6
+
7
+ PREFIXES = {
8
+ dc: 'http://purl.org/dc/terms/',
9
+ bibo: 'http://purl.org/ontology/bibo/',
10
+ fabio: 'http://purl.org/spar/fabio/',
11
+ rev: 'http://purl.org/stuff/rev#',
12
+ foaf: 'http://xmlns.com/foaf/0.1/',
13
+ lang: 'http://lexvo.org/id/iso639-3/'
14
+ }
15
+
16
+ class << self
17
+ def parse(uri_or_array)
18
+ prefixes = case uri_or_array
19
+ when String then [uri_or_array]
20
+ when Array then uri_or_array
21
+ else return UnProcessable.new
22
+ end
23
+ result = Set.new
24
+ prefixes.each do |prefix|
25
+ uri = URI(prefix)
26
+ str = ""
27
+ str << uri.host.split('.')[-2]
28
+ /^(?<iri>.*[\/|#]).+$/ =~ uri.to_s
29
+ str << ": <%s>" % iri
30
+ result << str
31
+ end
32
+ result.to_a
33
+ end
34
+ end
35
+
36
+ def initialize(prefixes={})
37
+ @prefixes = prefixes
38
+ end
39
+
40
+ def to_a
41
+ ary = []
42
+ @prefixes.each_pair do |key, value|
43
+ ary << "#{key}: <#{value}>"
44
+ end
45
+ ary
46
+ end
47
+
48
+ def to_s
49
+ @prefixes.inspect
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,632 @@
1
+ module RDF::Virtuoso
2
+
3
+ ##
4
+ # A SPARQL query builder.
5
+ #
6
+ # @example Iterating over all found solutions
7
+ # query.each_solution { |solution| puts solution.inspect }
8
+ #
9
+ class Query < RDF::Query
10
+ ##
11
+ # @return [Symbol]
12
+ # @see http://www.w3.org/TR/rdf-sparql-query/#QueryForms
13
+ attr_reader :form
14
+
15
+ ##
16
+ # @return [Hash{Symbol => Object}]
17
+ attr_reader :options
18
+
19
+ ##
20
+ # @return [Array<[key, RDF::Value]>]
21
+ attr_reader :values
22
+
23
+
24
+ attr_reader :data_values
25
+
26
+ ##
27
+ # Creates a boolean `ASK` query.
28
+ #
29
+ # @param [Hash{Symbol => Object}] options
30
+ # @return [Query]
31
+ # @see http://www.w3.org/TR/rdf-sparql-query/#ask
32
+ def self.ask(options = {})
33
+ self.new(:ask, options)
34
+ end
35
+
36
+ ##
37
+ # Creates a tuple `SELECT` query.
38
+ #
39
+ # @param [Array<Symbol>] variables
40
+ # @param [Hash{Symbol => Object}] options
41
+ # @return [Query]
42
+ # @see http://www.w3.org/TR/rdf-sparql-query/#select
43
+ def self.select(*variables)
44
+ options = variables.last.is_a?(Hash) ? variables.pop : {}
45
+ self.new(:select, options).select(*variables)
46
+ end
47
+
48
+ ##
49
+ # Creates a `DESCRIBE` query.
50
+ #
51
+ # @param [Array<Symbol, RDF::URI>] variables
52
+ # @param [Hash{Symbol => Object}] options
53
+ # @return [Query]
54
+ # @see http://www.w3.org/TR/rdf-sparql-query/#describe
55
+ def self.describe(*variables)
56
+ options = variables.last.is_a?(Hash) ? variables.pop : {}
57
+ self.new(:describe, options).describe(*variables)
58
+ end
59
+
60
+ ##
61
+ # Creates a graph `CONSTRUCT` query.
62
+ #
63
+ # @param [Array<RDF::Query::Pattern, Array>] patterns
64
+ # @param [Hash{Symbol => Object}] options
65
+ # @return [Query]
66
+ # @see http://www.w3.org/TR/rdf-sparql-query/#construct
67
+ def self.construct(*patterns)
68
+ options = patterns.last.is_a?(Hash) ? patterns.pop : {}
69
+ self.new(:construct, options).construct(*patterns) # FIXME
70
+ end
71
+
72
+ ##
73
+ # Creates an `UPDATE` query.
74
+ #
75
+ # @param [Array<RDF::Query::Pattern, Array>] patterns
76
+ # @param [Hash{Symbol => Object}] options
77
+ # @return [Query]
78
+ # @see http://www.w3.org/Submission/SPARQL-Update/
79
+ def self.insert_data(*patterns)
80
+ # options = variables.last.is_a?(Hash) ? variables.pop : {}
81
+ options = patterns.last.is_a?(Hash) ? patterns.pop : {}
82
+ self.new(:insert_data, options).insert_data(*patterns)
83
+ end
84
+
85
+ def self.insert(*patterns)
86
+ # options = variables.last.is_a?(Hash) ? variables.pop : {}
87
+ options = patterns.last.is_a?(Hash) ? patterns.pop : {}
88
+ self.new(:insert, options).insert(*patterns)
89
+ end
90
+
91
+ def self.delete_data(*patterns)
92
+ options = patterns.last.is_a?(Hash) ? patterns.pop : {}
93
+ self.new(:delete_data, options).delete_data(*patterns)
94
+ end
95
+
96
+ def self.delete(*patterns)
97
+ options = patterns.last.is_a?(Hash) ? patterns.pop : {}
98
+ self.new(:delete, options).delete(*patterns)
99
+ end
100
+
101
+ def self.create(*variables)
102
+ options = variables.last.is_a?(Hash) ? variables.pop : {}
103
+ self.new(:create, options).create(variables.first)
104
+ end
105
+
106
+ def self.drop(*variables)
107
+ options = variables.last.is_a?(Hash) ? variables.pop : {}
108
+ self.new(:drop, options).drop(variables.first)
109
+ end
110
+
111
+ def self.clear(*variables)
112
+ options = variables.last.is_a?(Hash) ? variables.pop : {}
113
+ self.new(:clear, options).clear(variables.first)
114
+ end
115
+
116
+ ##
117
+ # @param [Symbol, #to_s] form
118
+ # @param [Hash{Symbol => Object}] options
119
+ # @yield [query]
120
+ # @yieldparam [Query]
121
+ def initialize(form = :ask, options = {}, &block)
122
+ @form = form.respond_to?(:to_sym) ? form.to_sym : form.to_s.to_sym
123
+ super([], options, &block)
124
+ end
125
+
126
+ ##
127
+ # @return [Query]
128
+ # @see http://www.w3.org/TR/rdf-sparql-query/#ask
129
+ def ask
130
+ @form = :ask
131
+ self
132
+ end
133
+
134
+ ##
135
+ # @param [Array<Symbol>] variables
136
+ # @return [Query]
137
+ # @see http://www.w3.org/TR/rdf-sparql-query/#select
138
+ def select(*variables)
139
+ @values = variables.map { |var| [var, RDF::Query::Variable.new(var)] }
140
+ self
141
+ end
142
+
143
+ ##
144
+ # @param [Array<Symbol>] variables
145
+ # @return [Query]
146
+ # @see http://www.w3.org/TR/rdf-sparql-query/#describe
147
+ def describe(*variables)
148
+ @values = variables.map { |var|
149
+ [var, var.is_a?(RDF::URI) ? var : RDF::Query::Variable.new(var)]
150
+ }
151
+ self
152
+ end
153
+
154
+ ##
155
+ # @param [Array<RDF::Query::Pattern, Array>] patterns
156
+ # @return [Query]
157
+ # @see http://www.w3.org/TR/rdf-sparql-query/#construct
158
+ def construct(*patterns)
159
+ new_patterns = []
160
+ patterns.each do |pattern|
161
+ new_patterns << pattern.map do |value|
162
+ if value.is_a?(Symbol)
163
+ value = RDF::Query::Variable.new(value)
164
+ elsif value.is_a?(RDF::URI)
165
+ value = value
166
+ else
167
+ value = RDF::Literal.new(value)
168
+ end
169
+ end
170
+ end
171
+ @data_values = build_patterns(new_patterns)
172
+ self
173
+ end
174
+
175
+
176
+ ##
177
+ # @param [Array<RDF::Query::Pattern, Array>] patterns
178
+ # @return [Query]
179
+ # @see http://www.w3.org/Submission/SPARQL-Update/
180
+ def insert_data(*patterns)
181
+ new_patterns = []
182
+ patterns.each do |values|
183
+ new_patterns << values.map { |var| [var, var.is_a?(RDF::URI) ? var : var] }
184
+ end
185
+ @data_values = new_patterns #build_patterns(new_patterns)
186
+ self
187
+ end
188
+
189
+ def insert(*patterns)
190
+ new_patterns = []
191
+ patterns.each do |pattern|
192
+ new_patterns << pattern.map do |value|
193
+ if value.is_a?(Symbol)
194
+ value = RDF::Query::Variable.new(value)
195
+ elsif value.is_a?(RDF::URI)
196
+ value = value
197
+ else
198
+ value = RDF::Literal.new(value)
199
+ end
200
+ end
201
+ end
202
+ @data_values = build_patterns(new_patterns)
203
+ self
204
+ end
205
+
206
+ def delete_data(*patterns)
207
+ new_patterns = []
208
+ patterns.each do |values|
209
+ new_patterns << values.map { |var| [var, var.is_a?(RDF::URI) ? var : var] }
210
+ end
211
+ @data_values = new_patterns #build_patterns(new_patterns)
212
+ self
213
+ end
214
+
215
+ def delete(*patterns)
216
+ new_patterns = []
217
+ patterns.each do |pattern|
218
+ new_patterns << pattern.map do |value|
219
+ if value.is_a?(Symbol)
220
+ value = RDF::Query::Variable.new(value)
221
+ elsif value.is_a?(RDF::URI)
222
+ value = value
223
+ else
224
+ value = RDF::Literal.new(value)
225
+ end
226
+ end
227
+ end
228
+ @data_values = build_patterns(new_patterns)
229
+ self
230
+ end
231
+
232
+ # def delete(*variables)
233
+ # @values = variables.map { |var|
234
+ # [var, var.is_a?(RDF::URI) ? var : RDF::Query::Variable.new(var)]
235
+ # }
236
+ # self
237
+ # end
238
+
239
+ def create(uri)
240
+ options[:graph] = uri
241
+ self
242
+ end
243
+
244
+ def drop(uri)
245
+ options[:graph] = uri
246
+ self
247
+ end
248
+
249
+ def clear(uri)
250
+ options[:graph] = uri
251
+ self
252
+ end
253
+
254
+ # @param RDF::URI uri
255
+ # @return [Query]
256
+ # @see http://www.w3.org/TR/rdf-sparql-query/#specDataset
257
+ def from(uri)
258
+ options[:from] = uri
259
+ self
260
+ end
261
+
262
+ # @param RDF::URI uri
263
+ # @return [Query]
264
+ def graph(uri)
265
+ options[:graph] = uri
266
+ self
267
+ end
268
+
269
+ ##
270
+ # @param [Array<RDF::Query::Pattern, Array>] patterns
271
+ # @return [Query]
272
+ # @see http://www.w3.org/TR/rdf-sparql-query/#GraphPattern
273
+ def where(*patterns)
274
+ @patterns += build_patterns(patterns)
275
+ self
276
+ end
277
+
278
+ alias_method :whether, :where
279
+
280
+ ##
281
+ # @param [Array<Symbol, String>] variables
282
+ # @return [Query]
283
+ # @see http://www.w3.org/TR/rdf-sparql-query/#modOrderBy
284
+ def order(*variables)
285
+ options[:order_by] = variables
286
+ self
287
+ end
288
+
289
+ alias_method :order_by, :order
290
+
291
+ ##
292
+ # @return [Query]
293
+ # @see http://www.w3.org/TR/rdf-sparql-query/#modDistinct
294
+ def distinct(state = true)
295
+ options[:distinct] = state
296
+ self
297
+ end
298
+
299
+ ##
300
+ # @return [Query]
301
+ # @see http://www.w3.org/TR/rdf-sparql-query/#modReduced
302
+ def reduced(state = true)
303
+ options[:reduced] = state
304
+ self
305
+ end
306
+
307
+ ## SPARQL 1.1 Aggregates
308
+ # @return [Query]
309
+ # @see http://www.w3.org/TR/sparql11-query/#defn_aggCount
310
+ # def count(*variables)
311
+ # options[:count] = variables
312
+ # self
313
+ # end
314
+ AGG_METHODS = %w(count min max sum avg sample group_concat group_digest)
315
+
316
+ AGG_METHODS.each do |m|
317
+ define_method m do |*variables|
318
+ options[m.to_sym] = variables
319
+ self
320
+ end
321
+ end
322
+
323
+ ##
324
+ # @param [Integer, #to_i] start
325
+ # @return [Query]
326
+ # @see http://www.w3.org/TR/rdf-sparql-query/#modOffset
327
+ def offset(start)
328
+ slice(start, nil)
329
+ end
330
+
331
+ ##
332
+ # @param [Integer, #to_i] length
333
+ # @return [Query]
334
+ # @see http://www.w3.org/TR/rdf-sparql-query/#modResultLimit
335
+ def limit(length)
336
+ slice(nil, length)
337
+ end
338
+
339
+ ##
340
+ # @param [Integer, #to_i] start
341
+ # @param [Integer, #to_i] length
342
+ # @return [Query]
343
+ def slice(start, length)
344
+ options[:offset] = start.to_i if start
345
+ options[:limit] = length.to_i if length
346
+ self
347
+ end
348
+
349
+ ##
350
+ # @return [Query]
351
+ # @see http://www.w3.org/TR/rdf-sparql-query/#prefNames
352
+ def prefix(string)
353
+ (options[:prefixes] ||= []) << string
354
+ self
355
+ end
356
+
357
+ ##
358
+ # @return [Query]
359
+ # @see http://www.w3.org/TR/rdf-sparql-query/#prefNames
360
+ def prefixes(prefixes = nil)
361
+ options[:prefixes] ||= []
362
+ options[:prefixes] += prefixes.to_a
363
+ self
364
+ end
365
+
366
+ ##
367
+ # @return [Query]
368
+ # @see http://www.w3.org/TR/rdf-sparql-query/#optionals
369
+ def optional(*patterns)
370
+ (options[:optionals] ||= []) << build_patterns(patterns)
371
+ self
372
+ end
373
+
374
+ ##
375
+ # @return [Query]
376
+ # @see http://www.w3.org/TR/rdf-sparql-query/#minus
377
+ def minus(*patterns)
378
+ (options[:minuses] ||= []) << build_patterns(patterns)
379
+ self
380
+ end
381
+
382
+ def union(*patterns)
383
+ (options[:unions] ||= []) << build_patterns(patterns)
384
+ self
385
+ end
386
+
387
+ ##
388
+ # @private
389
+ def build_patterns(patterns)
390
+ patterns.map do |pattern|
391
+ case pattern
392
+ when RDF::Query::Pattern then pattern
393
+ else RDF::Query::Pattern.new(*pattern.to_a)
394
+ end
395
+ end
396
+ end
397
+
398
+ ##
399
+ # @private
400
+ def filter(string)
401
+ (options[:filters] ||= []) << string
402
+ self
403
+ end
404
+
405
+ def filters(filters = nil)
406
+ options[:filters] ||= []
407
+ options[:filters] += filters.to_a
408
+ self
409
+ end
410
+
411
+ ##
412
+ # @return [Boolean]
413
+ def true?
414
+ case result
415
+ when TrueClass, FalseClass then result
416
+ when Enumerable then !result.empty?
417
+ else false
418
+ end
419
+ end
420
+
421
+ ##
422
+ # @return [Boolean]
423
+ def false?
424
+ !true?
425
+ end
426
+
427
+ ##
428
+ # @return [Enumerable<RDF::Query::Solution>]
429
+ def solutions
430
+ result
431
+ end
432
+
433
+ ##
434
+ # @yield [statement]
435
+ # @yieldparam [RDF::Statement]
436
+ # @return [Enumerator]
437
+ def each_statement(&block)
438
+ result.each_statement(&block)
439
+ end
440
+
441
+ ##
442
+ # @return [Object]
443
+ def result
444
+ @result ||= execute
445
+ end
446
+
447
+ ##
448
+ # @return [Object]
449
+ def execute
450
+ #query
451
+ #raise NotImplementedError
452
+ end
453
+
454
+ ##
455
+ # Returns the string representation of this query.
456
+ #
457
+ # @return [String]
458
+ def to_s
459
+ buffer = [form.to_s.gsub('_', ' ').upcase]
460
+ case form
461
+ when :select, :describe
462
+ buffer << 'DISTINCT' if options[:distinct]
463
+ buffer << 'REDUCED' if options[:reduced]
464
+ # Aggregates in select/describe
465
+ aggregates = [:count, :min, :max, :avg, :sum, :sample, :group_concat, :group_digest]
466
+ if (options.keys & aggregates).any?
467
+ (options.keys & aggregates).each do |agg|
468
+ case agg
469
+ when :sample
470
+ buffer << '(sql:' + agg.to_s.upcase
471
+ buffer << options[agg].map { |var| var.is_a?(String) ? var : "(?#{var})" }
472
+ when :group_concat, :group_digest
473
+ buffer << '(sql:' + agg.to_s.upcase
474
+ buffer << options[agg].map { |var| var.is_a?(Symbol) ? "(?#{var}" : "'#{var}'"}.join(', ')
475
+ buffer << ')'
476
+ else
477
+ buffer << '(' + agg.to_s.gsub('_', ' ').upcase
478
+ buffer << options[agg].map { |var| var.is_a?(String) ? var : "(?#{var})" }
479
+ end
480
+
481
+ buffer << 'AS ?' + agg.to_s + ')'
482
+ end
483
+ else
484
+ buffer << (values.empty? ? '*' : values.map { |v| serialize_value(v[1]) }.join(' '))
485
+ end
486
+ when :construct
487
+ buffer << '{'
488
+ buffer += serialize_patterns(@data_values)
489
+ buffer << '}'
490
+
491
+ # for virtuoso inserts
492
+ when :insert_data
493
+ buffer << "INTO GRAPH #{serialize_value(options[:graph])}" if options[:graph]
494
+ buffer << '{'
495
+ @data_values.each do |triple|
496
+ if triple.first.first.is_a?(RDF::Statement)
497
+ buffer << triple.map { |v| serialize_value(v[1])}
498
+ else
499
+ buffer << triple.map { |v| serialize_value(v[1])}.join(' ') + " ."
500
+ end
501
+ end
502
+ buffer << '}'
503
+
504
+ when :insert
505
+ buffer << "INTO GRAPH #{serialize_value(options[:graph])}" if options[:graph]
506
+ # buffer += serialize_patterns(options[:template])
507
+ # (@data_values.map { |v| puts v[1].inspect; puts 'xxx ' } )
508
+ buffer << '{'
509
+ buffer += serialize_patterns(@data_values)
510
+ buffer << '}'
511
+
512
+ when :delete_data
513
+ buffer << "FROM #{serialize_value(options[:graph])}" #if options[:graph]
514
+ buffer << '{'
515
+ @data_values.each do |triple|
516
+ if triple.first.first.is_a?(RDF::Statement)
517
+ buffer << triple.map { |v| serialize_value(v[1])}
518
+ else
519
+ buffer << triple.map { |v| serialize_value(v[1])}.join(' ') + " ."
520
+ end
521
+ end
522
+ buffer << '}'
523
+
524
+ when :delete
525
+ buffer << "FROM #{serialize_value(options[:graph])}" if options[:graph]
526
+ buffer << '{'
527
+ buffer += serialize_patterns(@data_values)
528
+ buffer << '}'
529
+
530
+ when :create, :drop
531
+ buffer << 'SILENT' if options[:silent]
532
+ buffer << "GRAPH #{serialize_value(options[:graph])}"
533
+
534
+ when :clear
535
+ buffer << "GRAPH #{serialize_value(options[:graph])}"
536
+
537
+ end
538
+
539
+ buffer << "FROM #{serialize_value(options[:from])}" if options[:from]
540
+
541
+ unless patterns.empty? && ([:describe, :insert_data, :delete_data, :create, :clear, :drop].include?(form))
542
+ buffer << 'WHERE {'
543
+
544
+ buffer << '{' if options[:unions]
545
+
546
+ buffer += serialize_patterns(patterns)
547
+ if options[:optionals]
548
+ options[:optionals].each do |patterns|
549
+ buffer << 'OPTIONAL {'
550
+ buffer += serialize_patterns(patterns)
551
+ buffer << '}'
552
+ end
553
+ end
554
+
555
+ if options[:minuses]
556
+ options[:minuses].each do |patterns|
557
+ buffer << 'MINUS {'
558
+ buffer += serialize_patterns(patterns)
559
+ buffer << '}'
560
+ end
561
+ end
562
+
563
+ if options[:filters]
564
+ buffer += options[:filters].map { |filter| "FILTER(#{filter})" }
565
+ end
566
+ buffer << '}'
567
+
568
+ if options[:unions]
569
+ options[:unions].each do |patterns|
570
+ buffer << 'UNION {'
571
+ buffer += serialize_patterns(patterns)
572
+ buffer << '}'
573
+ end
574
+ buffer << '}'
575
+ end
576
+
577
+ end
578
+
579
+ if options[:order_by]
580
+ buffer << 'ORDER BY'
581
+ buffer += options[:order_by].map { |var| var.is_a?(String) ? var : "?#{var}" }
582
+ end
583
+
584
+ buffer << "OFFSET #{options[:offset]}" if options[:offset]
585
+ buffer << "LIMIT #{options[:limit]}" if options[:limit]
586
+ options[:prefixes].reverse.each {|e| buffer.unshift("PREFIX #{e}") } if options[:prefixes]
587
+
588
+ buffer.join(' ')
589
+ end
590
+
591
+ ##
592
+ # @private
593
+ def serialize_patterns(patterns)
594
+ patterns.map do |p|
595
+ p.to_triple.map { |v| serialize_value(v) }.join(' ') << " ."
596
+ end
597
+ end
598
+
599
+ ##
600
+ # Outputs a developer-friendly representation of this query to `stderr`.
601
+ #
602
+ # @return [void]
603
+ def inspect!
604
+ warn(inspect)
605
+ self
606
+ end
607
+
608
+ ##
609
+ # Returns a developer-friendly representation of this query.
610
+ #
611
+ # @return [String]
612
+ def inspect
613
+ sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, to_s)
614
+ end
615
+
616
+ ##
617
+ # Serializes an RDF::Value into a format appropriate for select, construct, and where clauses
618
+ #
619
+ # @param [RDF::Value]
620
+ # @return [String]
621
+ # @private
622
+ def serialize_value(value)
623
+ # SPARQL queries are UTF-8, but support ASCII-style Unicode escapes, so
624
+ # the N-Triples serializer is fine unless it's a variable:
625
+ case
626
+ when value.is_a?(String) then value.inspect
627
+ when value.variable? then value.to_s
628
+ else RDF::NTriples.serialize(value)
629
+ end
630
+ end
631
+ end
632
+ end