openlogic-rdf 0.3.6

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 (80) hide show
  1. data/AUTHORS +3 -0
  2. data/CREDITS +9 -0
  3. data/README +361 -0
  4. data/UNLICENSE +24 -0
  5. data/VERSION +1 -0
  6. data/bin/rdf +18 -0
  7. data/etc/doap.nt +62 -0
  8. data/lib/df.rb +1 -0
  9. data/lib/rdf/cli.rb +200 -0
  10. data/lib/rdf/format.rb +383 -0
  11. data/lib/rdf/mixin/countable.rb +39 -0
  12. data/lib/rdf/mixin/durable.rb +31 -0
  13. data/lib/rdf/mixin/enumerable.rb +637 -0
  14. data/lib/rdf/mixin/indexable.rb +26 -0
  15. data/lib/rdf/mixin/inferable.rb +5 -0
  16. data/lib/rdf/mixin/mutable.rb +191 -0
  17. data/lib/rdf/mixin/queryable.rb +265 -0
  18. data/lib/rdf/mixin/readable.rb +15 -0
  19. data/lib/rdf/mixin/type_check.rb +21 -0
  20. data/lib/rdf/mixin/writable.rb +152 -0
  21. data/lib/rdf/model/graph.rb +263 -0
  22. data/lib/rdf/model/list.rb +731 -0
  23. data/lib/rdf/model/literal/boolean.rb +121 -0
  24. data/lib/rdf/model/literal/date.rb +73 -0
  25. data/lib/rdf/model/literal/datetime.rb +72 -0
  26. data/lib/rdf/model/literal/decimal.rb +86 -0
  27. data/lib/rdf/model/literal/double.rb +189 -0
  28. data/lib/rdf/model/literal/integer.rb +126 -0
  29. data/lib/rdf/model/literal/numeric.rb +184 -0
  30. data/lib/rdf/model/literal/time.rb +87 -0
  31. data/lib/rdf/model/literal/token.rb +47 -0
  32. data/lib/rdf/model/literal/xml.rb +39 -0
  33. data/lib/rdf/model/literal.rb +373 -0
  34. data/lib/rdf/model/node.rb +156 -0
  35. data/lib/rdf/model/resource.rb +28 -0
  36. data/lib/rdf/model/statement.rb +296 -0
  37. data/lib/rdf/model/term.rb +77 -0
  38. data/lib/rdf/model/uri.rb +570 -0
  39. data/lib/rdf/model/value.rb +133 -0
  40. data/lib/rdf/nquads.rb +152 -0
  41. data/lib/rdf/ntriples/format.rb +48 -0
  42. data/lib/rdf/ntriples/reader.rb +239 -0
  43. data/lib/rdf/ntriples/writer.rb +219 -0
  44. data/lib/rdf/ntriples.rb +104 -0
  45. data/lib/rdf/query/pattern.rb +329 -0
  46. data/lib/rdf/query/solution.rb +252 -0
  47. data/lib/rdf/query/solutions.rb +237 -0
  48. data/lib/rdf/query/variable.rb +221 -0
  49. data/lib/rdf/query.rb +404 -0
  50. data/lib/rdf/reader.rb +511 -0
  51. data/lib/rdf/repository.rb +389 -0
  52. data/lib/rdf/transaction.rb +161 -0
  53. data/lib/rdf/util/aliasing.rb +63 -0
  54. data/lib/rdf/util/cache.rb +139 -0
  55. data/lib/rdf/util/file.rb +38 -0
  56. data/lib/rdf/util/uuid.rb +36 -0
  57. data/lib/rdf/util.rb +6 -0
  58. data/lib/rdf/version.rb +19 -0
  59. data/lib/rdf/vocab/cc.rb +18 -0
  60. data/lib/rdf/vocab/cert.rb +13 -0
  61. data/lib/rdf/vocab/dc.rb +63 -0
  62. data/lib/rdf/vocab/dc11.rb +23 -0
  63. data/lib/rdf/vocab/doap.rb +45 -0
  64. data/lib/rdf/vocab/exif.rb +168 -0
  65. data/lib/rdf/vocab/foaf.rb +69 -0
  66. data/lib/rdf/vocab/geo.rb +13 -0
  67. data/lib/rdf/vocab/http.rb +26 -0
  68. data/lib/rdf/vocab/owl.rb +59 -0
  69. data/lib/rdf/vocab/rdfs.rb +17 -0
  70. data/lib/rdf/vocab/rsa.rb +12 -0
  71. data/lib/rdf/vocab/rss.rb +14 -0
  72. data/lib/rdf/vocab/sioc.rb +93 -0
  73. data/lib/rdf/vocab/skos.rb +36 -0
  74. data/lib/rdf/vocab/wot.rb +21 -0
  75. data/lib/rdf/vocab/xhtml.rb +9 -0
  76. data/lib/rdf/vocab/xsd.rb +58 -0
  77. data/lib/rdf/vocab.rb +215 -0
  78. data/lib/rdf/writer.rb +475 -0
  79. data/lib/rdf.rb +192 -0
  80. metadata +173 -0
data/lib/rdf/reader.rb ADDED
@@ -0,0 +1,511 @@
1
+ module RDF
2
+ ##
3
+ # The base class for RDF parsers.
4
+ #
5
+ # @example Loading an RDF reader implementation
6
+ # require 'rdf/ntriples'
7
+ #
8
+ # @example Iterating over known RDF reader classes
9
+ # RDF::Reader.each { |klass| puts klass.name }
10
+ #
11
+ # @example Obtaining an RDF reader class
12
+ # RDF::Reader.for(:ntriples) #=> RDF::NTriples::Reader
13
+ # RDF::Reader.for("etc/doap.nt")
14
+ # RDF::Reader.for(:file_name => "etc/doap.nt")
15
+ # RDF::Reader.for(:file_extension => "nt")
16
+ # RDF::Reader.for(:content_type => "text/plain")
17
+ #
18
+ # @example Instantiating an RDF reader class
19
+ # RDF::Reader.for(:ntriples).new($stdin) { |reader| ... }
20
+ #
21
+ # @example Parsing RDF statements from a file
22
+ # RDF::Reader.open("etc/doap.nt") do |reader|
23
+ # reader.each_statement do |statement|
24
+ # puts statement.inspect
25
+ # end
26
+ # end
27
+ #
28
+ # @example Parsing RDF statements from a string
29
+ # data = StringIO.new(File.read("etc/doap.nt"))
30
+ # RDF::Reader.for(:ntriples).new(data) do |reader|
31
+ # reader.each_statement do |statement|
32
+ # puts statement.inspect
33
+ # end
34
+ # end
35
+ #
36
+ # @abstract
37
+ # @see RDF::Format
38
+ # @see RDF::Writer
39
+ class Reader
40
+ extend ::Enumerable
41
+ extend RDF::Util::Aliasing::LateBound
42
+ include RDF::Readable
43
+ include RDF::Enumerable # @since 0.3.0
44
+
45
+ ##
46
+ # Enumerates known RDF reader classes.
47
+ #
48
+ # @yield [klass]
49
+ # @yieldparam [Class] klass
50
+ # @return [Enumerator]
51
+ def self.each(&block)
52
+ @@subclasses.each(&block)
53
+ end
54
+
55
+ ##
56
+ # Finds an RDF reader class based on the given criteria.
57
+ #
58
+ # If the reader class has a defined format, use that.
59
+ #
60
+ # @overload for(format)
61
+ # Finds an RDF reader class based on a symbolic name.
62
+ #
63
+ # @param [Symbol] format
64
+ # @return [Class]
65
+ #
66
+ # @overload for(filename)
67
+ # Finds an RDF reader class based on a file name.
68
+ #
69
+ # @param [String] filename
70
+ # @return [Class]
71
+ #
72
+ # @overload for(options = {})
73
+ # Finds an RDF reader class based on various options.
74
+ #
75
+ # @param [Hash{Symbol => Object}] options
76
+ # @option options [String, #to_s] :file_name (nil)
77
+ # @option options [Symbol, #to_sym] :file_extension (nil)
78
+ # @option options [String, #to_s] :content_type (nil)
79
+ # @return [Class]
80
+ # @option options [String] :sample (nil)
81
+ # A sample of input used for performing format detection.
82
+ # If we find no formats, or we find more than one, and we have a sample, we can
83
+ # perform format detection to find a specific format to use, in which case
84
+ # we pick the first one we find
85
+ # @return [Class]
86
+ # @yieldreturn [String] another way to provide a sample, allows lazy for retrieving the sample.
87
+ #
88
+ # @return [Class]
89
+ def self.for(options = {}, &block)
90
+ options = options.merge(:has_reader => true) if options.is_a?(Hash)
91
+ if format = self.format || Format.for(options, &block)
92
+ format.reader
93
+ end
94
+ end
95
+
96
+ ##
97
+ # Retrieves the RDF serialization format class for this reader class.
98
+ #
99
+ # @return [Class]
100
+ def self.format(klass = nil)
101
+ if klass.nil?
102
+ Format.each do |format|
103
+ if format.reader == self
104
+ return format
105
+ end
106
+ end
107
+ nil # not found
108
+ end
109
+ end
110
+
111
+ class << self
112
+ alias_method :format_class, :format
113
+ end
114
+
115
+ ##
116
+ # Parses input from the given file name or URL.
117
+ #
118
+ # @param [String, #to_s] filename
119
+ # @param [Hash{Symbol => Object}] options
120
+ # any additional options (see {RDF::Reader#initialize} and {RDF::Format.for})
121
+ # @option options [Symbol] :format (:ntriples)
122
+ # @yield [reader]
123
+ # @yieldparam [RDF::Reader] reader
124
+ # @yieldreturn [void] ignored
125
+ # @raise [RDF::FormatError] if no reader found for the specified format
126
+ def self.open(filename, options = {}, &block)
127
+ Util::File.open_file(filename, options) do |file|
128
+ format_options = options.dup
129
+ format_options[:content_type] ||= file.content_type if file.respond_to?(:content_type)
130
+ format_options[:file_name] ||= filename
131
+ reader = self.for(format_options[:format] || format_options) do
132
+ # Return a sample from the input file
133
+ sample = file.read(1000)
134
+ file.rewind
135
+ sample
136
+ end
137
+ if reader
138
+ reader.new(file, options, &block)
139
+ else
140
+ raise FormatError, "unknown RDF format: #{format_options.inspect}"
141
+ end
142
+ end
143
+ end
144
+
145
+ ##
146
+ # Returns a symbol appropriate to use with RDF::Reader.for()
147
+ # @return [Symbol]
148
+ def self.to_sym
149
+ elements = self.to_s.split("::")
150
+ sym = elements.pop
151
+ sym = elements.pop if sym == 'Reader'
152
+ sym.downcase.to_s.to_sym
153
+ end
154
+
155
+ ##
156
+ # Returns a symbol appropriate to use with RDF::Reader.for()
157
+ # @return [Symbol]
158
+ def to_sym
159
+ self.class.to_sym
160
+ end
161
+
162
+ ##
163
+ # Initializes the reader.
164
+ #
165
+ # @param [IO, File, String] input
166
+ # the input stream to read
167
+ # @param [Hash{Symbol => Object}] options
168
+ # any additional options
169
+ # @option options [Encoding] :encoding (Encoding::UTF_8)
170
+ # the encoding of the input stream (Ruby 1.9+)
171
+ # @option options [Boolean] :validate (false)
172
+ # whether to validate the parsed statements and values
173
+ # @option options [Boolean] :canonicalize (false)
174
+ # whether to canonicalize parsed literals
175
+ # @option options [Boolean] :intern (true)
176
+ # whether to intern all parsed URIs
177
+ # @option options [Hash] :prefixes (Hash.new)
178
+ # the prefix mappings to use (not supported by all readers)
179
+ # @option options [#to_s] :base_uri (nil)
180
+ # the base URI to use when resolving relative URIs (not supported by
181
+ # all readers)
182
+ # @yield [reader] `self`
183
+ # @yieldparam [RDF::Reader] reader
184
+ # @yieldreturn [void] ignored
185
+ def initialize(input = $stdin, options = {}, &block)
186
+ @options = options.dup
187
+ @options[:validate] ||= false
188
+ @options[:canonicalize] ||= false
189
+ @options[:intern] ||= true
190
+ @options[:prefixes] ||= Hash.new
191
+
192
+ @input = case input
193
+ when String then StringIO.new(input)
194
+ else input
195
+ end
196
+
197
+ if block_given?
198
+ case block.arity
199
+ when 0 then instance_eval(&block)
200
+ else block.call(self)
201
+ end
202
+ end
203
+ end
204
+
205
+ ##
206
+ # Any additional options for this reader.
207
+ #
208
+ # @return [Hash]
209
+ # @since 0.3.0
210
+ attr_reader :options
211
+
212
+ ##
213
+ # Returns the base URI determined by this reader.
214
+ #
215
+ # @example
216
+ # reader.prefixes[:dc] #=> RDF::URI('http://purl.org/dc/terms/')
217
+ #
218
+ # @return [Hash{Symbol => RDF::URI}]
219
+ # @since 0.3.0
220
+ def base_uri
221
+ @options[:base_uri]
222
+ end
223
+
224
+ ##
225
+ # Returns the URI prefixes currently defined for this reader.
226
+ #
227
+ # @example
228
+ # reader.prefixes[:dc] #=> RDF::URI('http://purl.org/dc/terms/')
229
+ #
230
+ # @return [Hash{Symbol => RDF::URI}]
231
+ # @since 0.3.0
232
+ def prefixes
233
+ @options[:prefixes] ||= {}
234
+ end
235
+
236
+ ##
237
+ # Defines the given URI prefixes for this reader.
238
+ #
239
+ # @example
240
+ # reader.prefixes = {
241
+ # :dc => RDF::URI('http://purl.org/dc/terms/'),
242
+ # }
243
+ #
244
+ # @param [Hash{Symbol => RDF::URI}] prefixes
245
+ # @return [Hash{Symbol => RDF::URI}]
246
+ # @since 0.3.0
247
+ def prefixes=(prefixes)
248
+ @options[:prefixes] = prefixes
249
+ end
250
+
251
+ ##
252
+ # Defines the given named URI prefix for this reader.
253
+ #
254
+ # @example Defining a URI prefix
255
+ # reader.prefix :dc, RDF::URI('http://purl.org/dc/terms/')
256
+ #
257
+ # @example Returning a URI prefix
258
+ # reader.prefix(:dc) #=> RDF::URI('http://purl.org/dc/terms/')
259
+ #
260
+ # @overload prefix(name, uri)
261
+ # @param [Symbol, #to_s] name
262
+ # @param [RDF::URI, #to_s] uri
263
+ #
264
+ # @overload prefix(name)
265
+ # @param [Symbol, #to_s] name
266
+ #
267
+ # @return [RDF::URI]
268
+ def prefix(name, uri = nil)
269
+ name = name.to_s.empty? ? nil : (name.respond_to?(:to_sym) ? name.to_sym : name.to_s.to_sym)
270
+ uri.nil? ? prefixes[name] : prefixes[name] = uri
271
+ end
272
+ alias_method :prefix!, :prefix
273
+
274
+ ##
275
+ # Iterates the given block for each RDF statement.
276
+ #
277
+ # If no block was given, returns an enumerator.
278
+ #
279
+ # Statements are yielded in the order that they are read from the input
280
+ # stream.
281
+ #
282
+ # @overload each_statement
283
+ # @yield [statement]
284
+ # each statement
285
+ # @yieldparam [RDF::Statement] statement
286
+ # @yieldreturn [void] ignored
287
+ # @return [void]
288
+ #
289
+ # @overload each_statement
290
+ # @return [Enumerator]
291
+ #
292
+ # @return [void]
293
+ # @see RDF::Enumerable#each_statement
294
+ def each_statement(&block)
295
+ if block_given?
296
+ begin
297
+ loop { block.call(read_statement) }
298
+ rescue EOFError => e
299
+ rewind rescue nil
300
+ end
301
+ end
302
+ enum_for(:each_statement)
303
+ end
304
+ alias_method :each, :each_statement
305
+
306
+ ##
307
+ # Iterates the given block for each RDF triple.
308
+ #
309
+ # If no block was given, returns an enumerator.
310
+ #
311
+ # Triples are yielded in the order that they are read from the input
312
+ # stream.
313
+ #
314
+ # @overload each_triple
315
+ # @yield [subject, predicate, object]
316
+ # each triple
317
+ # @yieldparam [RDF::Resource] subject
318
+ # @yieldparam [RDF::URI] predicate
319
+ # @yieldparam [RDF::Term] object
320
+ # @yieldreturn [void] ignored
321
+ # @return [void]
322
+ #
323
+ # @overload each_triple
324
+ # @return [Enumerator]
325
+ #
326
+ # @return [void]
327
+ # @see RDF::Enumerable#each_triple
328
+ def each_triple(&block)
329
+ if block_given?
330
+ begin
331
+ loop { block.call(*read_triple) }
332
+ rescue EOFError => e
333
+ rewind rescue nil
334
+ end
335
+ end
336
+ enum_for(:each_triple)
337
+ end
338
+
339
+ ##
340
+ # Rewinds the input stream to the beginning of input.
341
+ #
342
+ # @return [void]
343
+ # @since 0.2.3
344
+ # @see http://ruby-doc.org/core-1.9/classes/IO.html#M001692
345
+ def rewind
346
+ @input.rewind
347
+ end
348
+ alias_method :rewind!, :rewind
349
+
350
+ ##
351
+ # Closes the input stream, after which an `IOError` will be raised for
352
+ # further read attempts.
353
+ #
354
+ # If the input stream is already closed, does nothing.
355
+ #
356
+ # @return [void]
357
+ # @since 0.2.2
358
+ # @see http://ruby-doc.org/core-1.9/classes/IO.html#M001699
359
+ def close
360
+ @input.close unless @input.closed?
361
+ end
362
+ alias_method :close!, :close
363
+
364
+ protected
365
+
366
+ ##
367
+ # Reads a statement from the input stream.
368
+ #
369
+ # @return [RDF::Statement] a statement
370
+ # @raise [NotImplementedError] unless implemented in subclass
371
+ # @abstract
372
+ def read_statement
373
+ Statement.new(*read_triple)
374
+ end
375
+
376
+ ##
377
+ # Reads a triple from the input stream.
378
+ #
379
+ # @return [Array(RDF::Term)] a triple
380
+ # @raise [NotImplementedError] unless implemented in subclass
381
+ # @abstract
382
+ def read_triple
383
+ raise NotImplementedError, "#{self.class}#read_triple" # override in subclasses
384
+ end
385
+
386
+ ##
387
+ # Raises an "expected subject" parsing error on the current line.
388
+ #
389
+ # @return [void]
390
+ # @raise [RDF::ReaderError]
391
+ def fail_subject
392
+ raise RDF::ReaderError, "expected subject in line #{lineno}: #{current_line.inspect}"
393
+ end
394
+
395
+ ##
396
+ # Raises an "expected predicate" parsing error on the current line.
397
+ #
398
+ # @return [void]
399
+ # @raise [RDF::ReaderError]
400
+ def fail_predicate
401
+ raise RDF::ReaderError, "expected predicate in line #{lineno}: #{current_line.inspect}"
402
+ end
403
+
404
+ ##
405
+ # Raises an "expected object" parsing error on the current line.
406
+ #
407
+ # @return [void]
408
+ # @raise [RDF::ReaderError]
409
+ def fail_object
410
+ raise RDF::ReaderError, "expected object in line #{lineno}: #{current_line.inspect}"
411
+ end
412
+
413
+ ##
414
+ # Returns the encoding of the input stream.
415
+ #
416
+ # _Note: this method requires Ruby 1.9 or newer._
417
+ #
418
+ # @return [Encoding]
419
+ def encoding
420
+ @options[:encoding] ||= Encoding::UTF_8
421
+ end
422
+
423
+ ##
424
+ # Returns `true` if parsed statements and values should be validated.
425
+ #
426
+ # @return [Boolean] `true` or `false`
427
+ # @since 0.3.0
428
+ def validate?
429
+ @options[:validate]
430
+ end
431
+
432
+ ##
433
+ # Returns `true` if parsed values should be canonicalized.
434
+ #
435
+ # @return [Boolean] `true` or `false`
436
+ # @since 0.3.0
437
+ def canonicalize?
438
+ @options[:canonicalize]
439
+ end
440
+
441
+ ##
442
+ # Returns `true` if parsed URIs should be interned.
443
+ #
444
+ # @return [Boolean] `true` or `false`
445
+ # @since 0.3.0
446
+ def intern?
447
+ @options[:intern]
448
+ end
449
+
450
+ private
451
+
452
+ @@subclasses = [] # @private
453
+
454
+ ##
455
+ # @private
456
+ # @return [void]
457
+ def self.inherited(child)
458
+ @@subclasses << child
459
+ super
460
+ end
461
+
462
+ ##
463
+ # @return [Integer]
464
+ def lineno
465
+ @input.lineno
466
+ end
467
+
468
+ ##
469
+ # @private
470
+ # @return [String] The most recently read line of the input
471
+ def current_line
472
+ @line
473
+ end
474
+
475
+ ##
476
+ # @return [String]
477
+ def readline
478
+ @line = @input.readline
479
+ @line.chomp!
480
+ @line.force_encoding(encoding) if @line.respond_to?(:force_encoding) # for Ruby 1.9+
481
+ @line
482
+ end
483
+
484
+ ##
485
+ # @return [void]
486
+ def strip!
487
+ @line.strip!
488
+ end
489
+
490
+ ##
491
+ # @return [Boolean]
492
+ def blank?
493
+ @line.nil? || @line.empty?
494
+ end
495
+
496
+ ##
497
+ # @param [Regexp] pattern
498
+ # @return [Object]
499
+ def match(pattern)
500
+ if @line =~ pattern
501
+ result, @line = $1, $'.lstrip
502
+ result || true
503
+ end
504
+ end
505
+ end # Reader
506
+
507
+ ##
508
+ # The base class for RDF parsing errors.
509
+ class ReaderError < IOError
510
+ end # ReaderError
511
+ end # RDF