openlogic-rdf 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
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