rdf 0.0.6 → 0.0.7

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.
Files changed (59) hide show
  1. data/AUTHORS +1 -1
  2. data/VERSION +1 -1
  3. data/lib/rdf.rb +25 -22
  4. data/lib/rdf/enumerable.rb +554 -0
  5. data/lib/rdf/format.rb +239 -41
  6. data/lib/rdf/model/graph.rb +82 -0
  7. data/lib/rdf/{literal.rb → model/literal.rb} +47 -4
  8. data/lib/rdf/{node.rb → model/node.rb} +0 -0
  9. data/lib/rdf/{resource.rb → model/resource.rb} +0 -0
  10. data/lib/rdf/{statement.rb → model/statement.rb} +12 -0
  11. data/lib/rdf/{uri.rb → model/uri.rb} +20 -7
  12. data/lib/rdf/model/value.rb +135 -0
  13. data/lib/rdf/ntriples.rb +35 -2
  14. data/lib/rdf/ntriples/format.rb +4 -4
  15. data/lib/rdf/ntriples/reader.rb +2 -2
  16. data/lib/rdf/ntriples/writer.rb +26 -19
  17. data/lib/rdf/query.rb +4 -4
  18. data/lib/rdf/query/pattern.rb +3 -3
  19. data/lib/rdf/query/solution.rb +2 -2
  20. data/lib/rdf/query/variable.rb +3 -3
  21. data/lib/rdf/reader.rb +85 -16
  22. data/lib/rdf/repository.rb +104 -12
  23. data/lib/rdf/version.rb +1 -1
  24. data/lib/rdf/vocab.rb +171 -0
  25. data/lib/rdf/vocab/cc.rb +18 -0
  26. data/lib/rdf/vocab/dc.rb +63 -0
  27. data/lib/rdf/vocab/doap.rb +45 -0
  28. data/lib/rdf/vocab/exif.rb +168 -0
  29. data/lib/rdf/vocab/foaf.rb +69 -0
  30. data/lib/rdf/vocab/http.rb +26 -0
  31. data/lib/rdf/vocab/owl.rb +59 -0
  32. data/lib/rdf/{vocabulary → vocab}/rdf.rb +7 -1
  33. data/lib/rdf/vocab/rdfs.rb +17 -0
  34. data/lib/rdf/{vocabulary → vocab}/rss.rb +6 -1
  35. data/lib/rdf/vocab/sioc.rb +93 -0
  36. data/lib/rdf/vocab/skos.rb +36 -0
  37. data/lib/rdf/vocab/wot.rb +21 -0
  38. data/lib/rdf/vocab/xhtml.rb +9 -0
  39. data/lib/rdf/vocab/xsd.rb +58 -0
  40. data/lib/rdf/writer.rb +123 -16
  41. metadata +26 -27
  42. data/lib/rdf/graph.rb +0 -197
  43. data/lib/rdf/reader/ntriples.rb +0 -5
  44. data/lib/rdf/value.rb +0 -76
  45. data/lib/rdf/vocabulary.rb +0 -133
  46. data/lib/rdf/vocabulary/cc.rb +0 -9
  47. data/lib/rdf/vocabulary/dc.rb +0 -9
  48. data/lib/rdf/vocabulary/doap.rb +0 -9
  49. data/lib/rdf/vocabulary/exif.rb +0 -9
  50. data/lib/rdf/vocabulary/foaf.rb +0 -9
  51. data/lib/rdf/vocabulary/http.rb +0 -9
  52. data/lib/rdf/vocabulary/owl.rb +0 -9
  53. data/lib/rdf/vocabulary/rdfs.rb +0 -9
  54. data/lib/rdf/vocabulary/sioc.rb +0 -9
  55. data/lib/rdf/vocabulary/skos.rb +0 -9
  56. data/lib/rdf/vocabulary/wot.rb +0 -9
  57. data/lib/rdf/vocabulary/xhtml.rb +0 -9
  58. data/lib/rdf/vocabulary/xsd.rb +0 -9
  59. data/lib/rdf/writer/ntriples.rb +0 -5
data/AUTHORS CHANGED
@@ -1 +1 @@
1
- * Arto Bendiken <arto.bendiken@gmail.com> (Lead developer)
1
+ * Arto Bendiken <arto.bendiken@gmail.com>
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.6
1
+ 0.0.7
data/lib/rdf.rb CHANGED
@@ -1,14 +1,17 @@
1
1
  require 'rdf/version'
2
2
 
3
3
  module RDF
4
+ # RDF mixins
5
+ autoload :Enumerable, 'rdf/enumerable'
6
+
4
7
  # RDF objects
5
- autoload :Graph, 'rdf/graph'
6
- autoload :Literal, 'rdf/literal'
7
- autoload :Node, 'rdf/node'
8
- autoload :Resource, 'rdf/resource'
9
- autoload :Statement, 'rdf/statement'
10
- autoload :URI, 'rdf/uri'
11
- autoload :Value, 'rdf/value'
8
+ autoload :Graph, 'rdf/model/graph'
9
+ autoload :Literal, 'rdf/model/literal'
10
+ autoload :Node, 'rdf/model/node'
11
+ autoload :Resource, 'rdf/model/resource'
12
+ autoload :Statement, 'rdf/model/statement'
13
+ autoload :URI, 'rdf/model/uri'
14
+ autoload :Value, 'rdf/model/value'
12
15
 
13
16
  # RDF serialization
14
17
  autoload :Format, 'rdf/format'
@@ -25,21 +28,21 @@ module RDF
25
28
  autoload :Query, 'rdf/query'
26
29
 
27
30
  # RDF vocabularies
28
- autoload :Vocabulary, 'rdf/vocabulary'
29
- autoload :CC, 'rdf/vocabulary/cc'
30
- autoload :DC, 'rdf/vocabulary/dc'
31
- autoload :DOAP, 'rdf/vocabulary/doap'
32
- autoload :EXIF, 'rdf/vocabulary/exif'
33
- autoload :FOAF, 'rdf/vocabulary/foaf'
34
- autoload :HTTP, 'rdf/vocabulary/http'
35
- autoload :OWL, 'rdf/vocabulary/owl'
36
- autoload :RDFS, 'rdf/vocabulary/rdfs'
37
- autoload :RSS, 'rdf/vocabulary/rss'
38
- autoload :SIOC, 'rdf/vocabulary/sioc'
39
- autoload :SKOS, 'rdf/vocabulary/skos'
40
- autoload :WOT, 'rdf/vocabulary/wot'
41
- autoload :XHTML, 'rdf/vocabulary/xhtml'
42
- autoload :XSD, 'rdf/vocabulary/xsd'
31
+ autoload :Vocabulary, 'rdf/vocab'
32
+ autoload :CC, 'rdf/vocab/cc'
33
+ autoload :DC, 'rdf/vocab/dc'
34
+ autoload :DOAP, 'rdf/vocab/doap'
35
+ autoload :EXIF, 'rdf/vocab/exif'
36
+ autoload :FOAF, 'rdf/vocab/foaf'
37
+ autoload :HTTP, 'rdf/vocab/http'
38
+ autoload :OWL, 'rdf/vocab/owl'
39
+ autoload :RDFS, 'rdf/vocab/rdfs'
40
+ autoload :RSS, 'rdf/vocab/rss'
41
+ autoload :SIOC, 'rdf/vocab/sioc'
42
+ autoload :SKOS, 'rdf/vocab/skos'
43
+ autoload :WOT, 'rdf/vocab/wot'
44
+ autoload :XHTML, 'rdf/vocab/xhtml'
45
+ autoload :XSD, 'rdf/vocab/xsd'
43
46
 
44
47
  ##
45
48
  # @return [String] uri
@@ -0,0 +1,554 @@
1
+ module RDF
2
+ ##
3
+ # An RDF statement enumeration mixin.
4
+ #
5
+ # Classes that include this module must implement an `#each` method that
6
+ # yields {RDF::Statement RDF statements}.
7
+ #
8
+ # @example Checking whether any statements exist
9
+ # enumerable.empty?
10
+ #
11
+ # @example Checking how many statements exist
12
+ # enumerable.count
13
+ #
14
+ # @example Checking whether a specific statement exists
15
+ # enumerable.has_statement?(RDF::Statement.new(subject, predicate, object))
16
+ # enumerable.has_triple?([subject, predicate, object])
17
+ # enumerable.has_quad?([subject, predicate, object, context])
18
+ #
19
+ # @example Checking whether a specific value exists
20
+ # enumerable.has_subject?(RDF::URI.new("http://rdf.rubyforge.org/"))
21
+ # enumerable.has_predicate?(RDF::DC.creator)
22
+ # enumerable.has_object?(RDF::Literal.new("Hello!", :language => :en))
23
+ # enumerable.has_context?(RDF::URI.new("http://rubyforge.org/"))
24
+ #
25
+ # @example Enumerating all statements
26
+ # enumerable.each_statement do |statement|
27
+ # puts statement.inspect
28
+ # end
29
+ #
30
+ # @example Enumerating all statements in the form of triples
31
+ # enumerable.each_triple do |subject, predicate, object|
32
+ # puts [subject, predicate, object].inspect
33
+ # end
34
+ #
35
+ # @example Enumerating all statements in the form of quads
36
+ # enumerable.each_quad do |subject, predicate, object, context|
37
+ # puts [subject, predicate, object, context].inspect
38
+ # end
39
+ #
40
+ # @example Enumerating all values
41
+ # enumerable.each_subject { |value| puts value.inspect }
42
+ # enumerable.each_predicate { |value| puts value.inspect }
43
+ # enumerable.each_object { |value| puts value.inspect }
44
+ # enumerable.each_context { |value| puts value.inspect }
45
+ #
46
+ # @example Obtaining all statements
47
+ # enumerable.statements #=> [RDF::Statement(subject1, predicate1, object1), ...]
48
+ # enumerable.triples #=> [[subject1, predicate1, object1], ...]
49
+ # enumerable.quads #=> [[subject1, predicate1, object1, context1], ...]
50
+ #
51
+ # @example Obtaining all unique values
52
+ # enumerable.subjects #=> [subject1, subject2, subject3, ...]
53
+ # enumerable.predicates #=> [predicate1, predicate2, predicate3, ...]
54
+ # enumerable.objects #=> [object1, object2, object3, ...]
55
+ # enumerable.contexts #=> [context1, context2, context3, ...]
56
+ #
57
+ # @see RDF::Graph
58
+ # @see RDF::Repository
59
+ module Enumerable
60
+ include ::Enumerable
61
+
62
+ ##
63
+ # Returns `true` if `self` contains no RDF statements.
64
+ #
65
+ # @return [Boolean]
66
+ def empty?
67
+ empty = true
68
+ each_statement { empty = false; break }
69
+ empty
70
+ end
71
+
72
+ ##
73
+ # Returns the number of RDF statements in `self`.
74
+ #
75
+ # @return [Integer]
76
+ def count
77
+ count = 0
78
+ each_statement { count += 1 }
79
+ count
80
+ end
81
+
82
+ alias_method :size, :count
83
+ alias_method :length, :count
84
+
85
+ ##
86
+ # Returns all RDF statements.
87
+ #
88
+ # @param [Hash{Symbol => Boolean}] options
89
+ # @return [Array<Statement>]
90
+ # @see #each_statement
91
+ # @see #enum_statement
92
+ def statements(options = {})
93
+ enum_statement.to_a
94
+ end
95
+
96
+ ##
97
+ # Returns `true` if `self` contains the given RDF statement.
98
+ #
99
+ # @param [Statement] statement
100
+ # @return [Boolean]
101
+ def has_statement?(statement)
102
+ enum_statement.include?(statement)
103
+ end
104
+
105
+ ##
106
+ # Iterates the given block for each RDF statement.
107
+ #
108
+ # If no block was given, returns an enumerator.
109
+ #
110
+ # @overload each_statement
111
+ # @yield [statement]
112
+ # @yieldparam [Statement] statement
113
+ # @return [void]
114
+ #
115
+ # @overload each_statement
116
+ # @return [Enumerator]
117
+ #
118
+ # @return [void]
119
+ # @see #enum_statement
120
+ def each_statement(&block)
121
+ if block_given?
122
+ # Invoke {#each} in the containing class:
123
+ each(&block)
124
+ else
125
+ enum_statement
126
+ end
127
+ end
128
+
129
+ ##
130
+ # Returns an enumerator for {#each_statement}.
131
+ #
132
+ # @return [Enumerator]
133
+ # @see #each_statement
134
+ def enum_statement
135
+ require_enumerator!
136
+ ::Enumerable::Enumerator.new(self, :each_statement)
137
+ end
138
+
139
+ alias_method :enum_statements, :enum_statement
140
+
141
+ ##
142
+ # Returns all RDF triples.
143
+ #
144
+ # @param [Hash{Symbol => Boolean}] options
145
+ # @return [Array<Array(Resource, URI, Value)>]
146
+ # @see #each_triple
147
+ # @see #enum_triple
148
+ def triples(options = {})
149
+ enum_statement.map(&:to_triple)
150
+ end
151
+
152
+ ##
153
+ # Returns `true` if `self` contains the given RDF triple.
154
+ #
155
+ # @param [Array(Resource, URI, Value)] triple
156
+ # @return [Boolean]
157
+ def has_triple?(triple)
158
+ enum_triple.include?(triple)
159
+ end
160
+
161
+ ##
162
+ # Iterates the given block for each RDF triple.
163
+ #
164
+ # If no block was given, returns an enumerator.
165
+ #
166
+ # @overload each_triple
167
+ # @yield [subject, predicate, object]
168
+ # @yieldparam [Resource] subject
169
+ # @yieldparam [URI] predicate
170
+ # @yieldparam [Value] object
171
+ # @return [void]
172
+ #
173
+ # @overload each_triple
174
+ # @return [Enumerator]
175
+ #
176
+ # @return [void]
177
+ # @see #enum_triple
178
+ def each_triple(&block)
179
+ if block_given?
180
+ each_statement do |statement|
181
+ block.call(*statement.to_triple)
182
+ end
183
+ else
184
+ enum_triple
185
+ end
186
+ end
187
+
188
+ ##
189
+ # Returns an enumerator for {#each_triple}.
190
+ #
191
+ # @return [Enumerator]
192
+ # @see #each_triple
193
+ def enum_triple
194
+ require_enumerator!
195
+ ::Enumerable::Enumerator.new(self, :each_triple)
196
+ end
197
+
198
+ alias_method :enum_triples, :enum_triple
199
+
200
+ ##
201
+ # Returns all RDF quads.
202
+ #
203
+ # @param [Hash{Symbol => Boolean}] options
204
+ # @return [Array<Array(Resource, URI, Value, Resource)>]
205
+ # @see #each_quad
206
+ # @see #enum_quad
207
+ def quads(options = {})
208
+ enum_statement.map(&:to_quad)
209
+ end
210
+
211
+ ##
212
+ # Returns `true` if `self` contains the given RDF quad.
213
+ #
214
+ # @param [Array(Resource, URI, Value, Resource)] quad
215
+ # @return [Boolean]
216
+ def has_quad?(quad)
217
+ enum_quad.include?(quad)
218
+ end
219
+
220
+ ##
221
+ # Iterates the given block for each RDF quad.
222
+ #
223
+ # If no block was given, returns an enumerator.
224
+ #
225
+ # @overload each_quad
226
+ # @yield [subject, predicate, object, context]
227
+ # @yieldparam [Resource] subject
228
+ # @yieldparam [URI] predicate
229
+ # @yieldparam [Value] object
230
+ # @yieldparam [Resource] context
231
+ # @return [void]
232
+ #
233
+ # @overload each_quad
234
+ # @return [Enumerator]
235
+ #
236
+ # @return [void]
237
+ # @see #enum_quad
238
+ def each_quad(&block)
239
+ if block_given?
240
+ each_statement do |statement|
241
+ block.call(*statement.to_quad)
242
+ end
243
+ else
244
+ enum_quad
245
+ end
246
+ end
247
+
248
+ ##
249
+ # Returns an enumerator for {#each_quad}.
250
+ #
251
+ # @return [Enumerator]
252
+ # @see #each_quad
253
+ def enum_quad
254
+ require_enumerator!
255
+ ::Enumerable::Enumerator.new(self, :each_quad)
256
+ end
257
+
258
+ alias_method :enum_quads, :enum_quad
259
+
260
+ ##
261
+ # Returns all unique RDF subjects.
262
+ #
263
+ # @param [Hash{Symbol => Boolean}] options
264
+ # @option options [Boolean] :unique (true)
265
+ # @return [Array<Resource>]
266
+ # @see #each_subject
267
+ # @see #enum_subject
268
+ def subjects(options = {})
269
+ if options[:unique] == false
270
+ enum_statement.map(&:subject)
271
+ else
272
+ enum_subject.to_a
273
+ end
274
+ end
275
+
276
+ ##
277
+ # Returns `true` if `self` contains the given RDF subject.
278
+ #
279
+ # @param [Resource] value
280
+ # @return [Boolean]
281
+ def has_subject?(value)
282
+ enum_subject.include?(value)
283
+ end
284
+
285
+ ##
286
+ # Iterates the given block for each unique RDF subject.
287
+ #
288
+ # If no block was given, returns an enumerator.
289
+ #
290
+ # @overload each_subject
291
+ # @yield [subject]
292
+ # @yieldparam [Resource] subject
293
+ # @return [void]
294
+ #
295
+ # @overload each_subject
296
+ # @return [Enumerator]
297
+ #
298
+ # @return [void]
299
+ # @see #enum_subject
300
+ def each_subject(&block)
301
+ if block_given?
302
+ values = {}
303
+ each_statement do |statement|
304
+ value = statement.subject
305
+ unless value.nil? || values.include?(value.to_s)
306
+ values[value.to_s] = true
307
+ block.call(value)
308
+ end
309
+ end
310
+ else
311
+ enum_subject
312
+ end
313
+ end
314
+
315
+ ##
316
+ # Returns an enumerator for {#each_subject}.
317
+ #
318
+ # @return [Enumerator]
319
+ # @see #each_subject
320
+ def enum_subject
321
+ require_enumerator!
322
+ ::Enumerable::Enumerator.new(self, :each_subject)
323
+ end
324
+
325
+ alias_method :enum_subjects, :enum_subject
326
+
327
+ ##
328
+ # Returns all unique RDF predicates.
329
+ #
330
+ # @param [Hash{Symbol => Boolean}] options
331
+ # @option options [Boolean] :unique (true)
332
+ # @return [Array<URI>]
333
+ # @see #each_predicate
334
+ # @see #enum_predicate
335
+ def predicates(options = {})
336
+ if options[:unique] == false
337
+ enum_statement.map(&:predicate)
338
+ else
339
+ enum_predicate.to_a
340
+ end
341
+ end
342
+
343
+ ##
344
+ # Returns `true` if `self` contains the given RDF predicate.
345
+ #
346
+ # @param [URI] value
347
+ # @return [Boolean]
348
+ def has_predicate?(value)
349
+ enum_predicate.include?(value)
350
+ end
351
+
352
+ ##
353
+ # Iterates the given block for each unique RDF predicate.
354
+ #
355
+ # If no block was given, returns an enumerator.
356
+ #
357
+ # @overload each_predicate
358
+ # @yield [predicate]
359
+ # @yieldparam [URI] predicate
360
+ # @return [void]
361
+ #
362
+ # @overload each_predicate
363
+ # @return [Enumerator]
364
+ #
365
+ # @return [void]
366
+ # @see #enum_predicate
367
+ def each_predicate(&block)
368
+ if block_given?
369
+ values = {}
370
+ each_statement do |statement|
371
+ value = statement.predicate
372
+ unless value.nil? || values.include?(value.to_s)
373
+ values[value.to_s] = true
374
+ block.call(value)
375
+ end
376
+ end
377
+ else
378
+ enum_predicate
379
+ end
380
+ end
381
+
382
+ ##
383
+ # Returns an enumerator for {#each_predicate}.
384
+ #
385
+ # @return [Enumerator]
386
+ # @see #each_predicate
387
+ def enum_predicate
388
+ require_enumerator!
389
+ ::Enumerable::Enumerator.new(self, :each_predicate)
390
+ end
391
+
392
+ alias_method :enum_predicates, :enum_predicate
393
+
394
+ ##
395
+ # Returns all unique RDF objects.
396
+ #
397
+ # @param [Hash{Symbol => Boolean}] options
398
+ # @option options [Boolean] :unique (true)
399
+ # @return [Array<Value>]
400
+ # @see #each_object
401
+ # @see #enum_object
402
+ def objects(options = {})
403
+ if options[:unique] == false
404
+ enum_statement.map(&:object)
405
+ else
406
+ enum_object.to_a
407
+ end
408
+ end
409
+
410
+ ##
411
+ # Returns `true` if `self` contains the given RDF object.
412
+ #
413
+ # @param [Value] value
414
+ # @return [Boolean]
415
+ def has_object?(value)
416
+ enum_object.include?(value)
417
+ end
418
+
419
+ ##
420
+ # Iterates the given block for each unique RDF object.
421
+ #
422
+ # If no block was given, returns an enumerator.
423
+ #
424
+ # @overload each_object
425
+ # @yield [object]
426
+ # @yieldparam [Value] object
427
+ # @return [void]
428
+ #
429
+ # @overload each_object
430
+ # @return [Enumerator]
431
+ #
432
+ # @return [void]
433
+ # @see #enum_object
434
+ def each_object(&block) # FIXME: deduplication
435
+ if block_given?
436
+ values = {}
437
+ each_statement do |statement|
438
+ value = statement.object
439
+ unless value.nil? || values.include?(value)
440
+ values[value] = true
441
+ block.call(value)
442
+ end
443
+ end
444
+ else
445
+ enum_object
446
+ end
447
+ end
448
+
449
+ ##
450
+ # Returns an enumerator for {#each_object}.
451
+ #
452
+ # @return [Enumerator]
453
+ # @see #each_object
454
+ def enum_object
455
+ require_enumerator!
456
+ ::Enumerable::Enumerator.new(self, :each_object)
457
+ end
458
+
459
+ alias_method :enum_objects, :enum_object
460
+
461
+ ##
462
+ # Returns all unique RDF contexts.
463
+ #
464
+ # @param [Hash{Symbol => Boolean}] options
465
+ # @option options [Boolean] :unique (true)
466
+ # @return [Array<Resource>]
467
+ # @see #each_context
468
+ # @see #enum_context
469
+ def contexts(options = {})
470
+ if options[:unique] == false
471
+ enum_statement.map(&:context)
472
+ else
473
+ enum_context.to_a
474
+ end
475
+ end
476
+
477
+ ##
478
+ # Returns `true` if `self` contains the given RDF context.
479
+ #
480
+ # @param [Resource] value
481
+ # @return [Boolean]
482
+ def has_context?(value)
483
+ enum_context.include?(value)
484
+ end
485
+
486
+ ##
487
+ # Iterates the given block for each unique RDF context.
488
+ #
489
+ # If no block was given, returns an enumerator.
490
+ #
491
+ # @overload each_context
492
+ # @yield [context]
493
+ # @yieldparam [Resource] context
494
+ # @return [void]
495
+ #
496
+ # @overload each_context
497
+ # @return [Enumerator]
498
+ #
499
+ # @return [void]
500
+ # @see #enum_context
501
+ def each_context(&block)
502
+ if block_given?
503
+ values = {}
504
+ each_statement do |statement|
505
+ value = statement.context
506
+ unless value.nil? || values.include?(value)
507
+ values[value] = true
508
+ block.call(value)
509
+ end
510
+ end
511
+ else
512
+ enum_context
513
+ end
514
+ end
515
+
516
+ ##
517
+ # Returns an enumerator for {#each_context}.
518
+ #
519
+ # @return [Enumerator]
520
+ # @see #each_context
521
+ def enum_context
522
+ require_enumerator!
523
+ ::Enumerable::Enumerator.new(self, :each_context)
524
+ end
525
+
526
+ alias_method :enum_contexts, :enum_context
527
+
528
+ ##
529
+ # Returns all RDF objects indexed by their subjects and predicates.
530
+ #
531
+ # The return value is a `Hash` instance that has the structure:
532
+ # `{subject => {predicate => [*objects]}}`.
533
+ #
534
+ # @return [Hash{Resource => Hash{URI => Array<Value>}}]
535
+ def to_hash
536
+ result = {}
537
+ each_statement do |statement|
538
+ next if statement.invalid? # skip any incomplete statements
539
+
540
+ result[statement.subject] ||= {}
541
+ values = (result[statement.subject][statement.predicate] ||= [])
542
+ values << statement.object unless values.include?(statement.object)
543
+ end
544
+ result
545
+ end
546
+
547
+ private
548
+
549
+ def require_enumerator! # @private
550
+ require 'enumerator' unless defined?(::Enumerable::Enumerator)
551
+ end
552
+
553
+ end
554
+ end