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.
- data/AUTHORS +1 -1
- data/VERSION +1 -1
- data/lib/rdf.rb +25 -22
- data/lib/rdf/enumerable.rb +554 -0
- data/lib/rdf/format.rb +239 -41
- data/lib/rdf/model/graph.rb +82 -0
- data/lib/rdf/{literal.rb → model/literal.rb} +47 -4
- data/lib/rdf/{node.rb → model/node.rb} +0 -0
- data/lib/rdf/{resource.rb → model/resource.rb} +0 -0
- data/lib/rdf/{statement.rb → model/statement.rb} +12 -0
- data/lib/rdf/{uri.rb → model/uri.rb} +20 -7
- data/lib/rdf/model/value.rb +135 -0
- data/lib/rdf/ntriples.rb +35 -2
- data/lib/rdf/ntriples/format.rb +4 -4
- data/lib/rdf/ntriples/reader.rb +2 -2
- data/lib/rdf/ntriples/writer.rb +26 -19
- data/lib/rdf/query.rb +4 -4
- data/lib/rdf/query/pattern.rb +3 -3
- data/lib/rdf/query/solution.rb +2 -2
- data/lib/rdf/query/variable.rb +3 -3
- data/lib/rdf/reader.rb +85 -16
- data/lib/rdf/repository.rb +104 -12
- data/lib/rdf/version.rb +1 -1
- data/lib/rdf/vocab.rb +171 -0
- data/lib/rdf/vocab/cc.rb +18 -0
- data/lib/rdf/vocab/dc.rb +63 -0
- data/lib/rdf/vocab/doap.rb +45 -0
- data/lib/rdf/vocab/exif.rb +168 -0
- data/lib/rdf/vocab/foaf.rb +69 -0
- data/lib/rdf/vocab/http.rb +26 -0
- data/lib/rdf/vocab/owl.rb +59 -0
- data/lib/rdf/{vocabulary → vocab}/rdf.rb +7 -1
- data/lib/rdf/vocab/rdfs.rb +17 -0
- data/lib/rdf/{vocabulary → vocab}/rss.rb +6 -1
- data/lib/rdf/vocab/sioc.rb +93 -0
- data/lib/rdf/vocab/skos.rb +36 -0
- data/lib/rdf/vocab/wot.rb +21 -0
- data/lib/rdf/vocab/xhtml.rb +9 -0
- data/lib/rdf/vocab/xsd.rb +58 -0
- data/lib/rdf/writer.rb +123 -16
- metadata +26 -27
- data/lib/rdf/graph.rb +0 -197
- data/lib/rdf/reader/ntriples.rb +0 -5
- data/lib/rdf/value.rb +0 -76
- data/lib/rdf/vocabulary.rb +0 -133
- data/lib/rdf/vocabulary/cc.rb +0 -9
- data/lib/rdf/vocabulary/dc.rb +0 -9
- data/lib/rdf/vocabulary/doap.rb +0 -9
- data/lib/rdf/vocabulary/exif.rb +0 -9
- data/lib/rdf/vocabulary/foaf.rb +0 -9
- data/lib/rdf/vocabulary/http.rb +0 -9
- data/lib/rdf/vocabulary/owl.rb +0 -9
- data/lib/rdf/vocabulary/rdfs.rb +0 -9
- data/lib/rdf/vocabulary/sioc.rb +0 -9
- data/lib/rdf/vocabulary/skos.rb +0 -9
- data/lib/rdf/vocabulary/wot.rb +0 -9
- data/lib/rdf/vocabulary/xhtml.rb +0 -9
- data/lib/rdf/vocabulary/xsd.rb +0 -9
- data/lib/rdf/writer/ntriples.rb +0 -5
data/lib/rdf/format.rb
CHANGED
@@ -1,20 +1,125 @@
|
|
1
1
|
module RDF
|
2
2
|
##
|
3
3
|
# An RDF serialization format.
|
4
|
+
#
|
5
|
+
# @example Iterating over known RDF serialization formats
|
6
|
+
# RDF::Format.each { |klass| puts klass.name }
|
7
|
+
#
|
8
|
+
# @example Getting a serialization format class
|
9
|
+
# RDF::Format.for(:ntriples) #=> RDF::NTriples::Format
|
10
|
+
# RDF::Format.for("spec/data/test.nt")
|
11
|
+
# RDF::Format.for(:file_name => "spec/data/test.nt")
|
12
|
+
# RDF::Format.for(:file_extension => "nt")
|
13
|
+
# RDF::Format.for(:content_type => "text/plain")
|
14
|
+
#
|
15
|
+
# @example Obtaining serialization format MIME types
|
16
|
+
# RDF::Format.content_types #=> {"text/plain" => [RDF::NTriples::Format]}
|
17
|
+
#
|
18
|
+
# @example Obtaining serialization format file extension mappings
|
19
|
+
# RDF::Format.file_extensions #=> {:nt => "text/plain"}
|
20
|
+
#
|
21
|
+
# @example Defining a new RDF serialization format class
|
22
|
+
# class RDF::NTriples::Format < RDF::Format
|
23
|
+
# content_type 'text/plain', :extension => :nt
|
24
|
+
# content_encoding 'ascii'
|
25
|
+
#
|
26
|
+
# reader RDF::NTriples::Reader
|
27
|
+
# writer RDF::NTriples::Writer
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# @example Instantiating an RDF reader or writer class (1)
|
31
|
+
# RDF::Format.for(:ntriples).reader.new($stdin) { |reader| ... }
|
32
|
+
# RDF::Format.for(:ntriples).writer.new($stdout) { |writer| ... }
|
33
|
+
#
|
34
|
+
# @example Instantiating an RDF reader or writer class (2)
|
35
|
+
# RDF::Reader.for(:ntriples).new($stdin) { |reader| ... }
|
36
|
+
# RDF::Writer.for(:ntriples).new($stdout) { |writer| ... }
|
37
|
+
#
|
38
|
+
# @abstract
|
39
|
+
# @see RDF::Reader
|
40
|
+
# @see RDF::Writer
|
41
|
+
# @see http://en.wikipedia.org/wiki/Resource_Description_Framework#Serialization_formats
|
4
42
|
class Format
|
5
|
-
|
43
|
+
extend ::Enumerable
|
6
44
|
|
7
45
|
##
|
8
|
-
# Enumerates known RDF format classes.
|
46
|
+
# Enumerates known RDF serialization format classes.
|
9
47
|
#
|
10
48
|
# @yield [klass]
|
11
49
|
# @yieldparam [Class]
|
50
|
+
# @return [Enumerator]
|
12
51
|
def self.each(&block)
|
13
|
-
|
52
|
+
@@subclasses.each(&block)
|
14
53
|
end
|
15
54
|
|
16
55
|
##
|
17
|
-
#
|
56
|
+
# Finds an RDF serialization format class based on the given criteria.
|
57
|
+
#
|
58
|
+
# @overload for(format)
|
59
|
+
# Finds an RDF serialization format class based on a symbolic name.
|
60
|
+
#
|
61
|
+
# @param [Symbol] format
|
62
|
+
# @return [Class]
|
63
|
+
#
|
64
|
+
# @overload for(filename)
|
65
|
+
# Finds an RDF serialization format class based on a file name.
|
66
|
+
#
|
67
|
+
# @param [String] filename
|
68
|
+
# @return [Class]
|
69
|
+
#
|
70
|
+
# @overload for(options = {})
|
71
|
+
# Finds an RDF serialization format class based on various options.
|
72
|
+
#
|
73
|
+
# @param [Hash{Symbol => Object}] options
|
74
|
+
# @option options [String, #to_s] :file_name (nil)
|
75
|
+
# @option options [Symbol, #to_sym] :file_extension (nil)
|
76
|
+
# @option options [String, #to_s] :content_type (nil)
|
77
|
+
# @return [Class]
|
78
|
+
#
|
79
|
+
# @return [Class]
|
80
|
+
def self.for(options = {})
|
81
|
+
case options
|
82
|
+
when String
|
83
|
+
# Find a format based on the file name
|
84
|
+
self.for(:file_name => options)
|
85
|
+
|
86
|
+
when Hash
|
87
|
+
case
|
88
|
+
# Find a format based on the file name
|
89
|
+
when file_name = options[:file_name]
|
90
|
+
self.for(:file_extension => File.extname(file_name.to_s)[1..-1])
|
91
|
+
# Find a format based on the file extension
|
92
|
+
when file_ext = options[:file_extension]
|
93
|
+
if file_extensions.has_key?(file_ext = file_ext.to_sym)
|
94
|
+
self.for(:content_type => file_extensions[file_ext])
|
95
|
+
end
|
96
|
+
# Find a format based on the MIME content type
|
97
|
+
when mime_type = options[:content_type]
|
98
|
+
if content_types.has_key?(mime_type = mime_type.to_s)
|
99
|
+
content_types[mime_type].first
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
when Symbol
|
104
|
+
case format = options
|
105
|
+
# Special case, since we want this to work despite autoloading
|
106
|
+
when :ntriples
|
107
|
+
RDF::NTriples::Format
|
108
|
+
# For anything else, find a match based on the full class name
|
109
|
+
else
|
110
|
+
format = format.to_s.downcase
|
111
|
+
@@subclasses.each do |klass|
|
112
|
+
if klass.name.to_s.split('::').map(&:downcase).include?(format)
|
113
|
+
return klass
|
114
|
+
end
|
115
|
+
end
|
116
|
+
nil # not found
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
##
|
122
|
+
# Returns MIME content types for known RDF serialization formats.
|
18
123
|
#
|
19
124
|
# @return [Hash{String => Array<Class>}]
|
20
125
|
def self.content_types
|
@@ -22,7 +127,7 @@ module RDF
|
|
22
127
|
end
|
23
128
|
|
24
129
|
##
|
25
|
-
# Returns
|
130
|
+
# Returns file extensions for known RDF serialization formats.
|
26
131
|
#
|
27
132
|
# @return [Hash{Symbol => String}]
|
28
133
|
def self.file_extensions
|
@@ -30,66 +135,159 @@ module RDF
|
|
30
135
|
end
|
31
136
|
|
32
137
|
##
|
33
|
-
#
|
34
|
-
#
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
138
|
+
# Retrieves or defines the reader class for this RDF serialization
|
139
|
+
# format.
|
140
|
+
#
|
141
|
+
# @overload reader(klass)
|
142
|
+
# Defines the reader class for this RDF serialization format.
|
143
|
+
#
|
144
|
+
# The class should be a subclass of {RDF::Reader}, or implement the
|
145
|
+
# same interface.
|
146
|
+
#
|
147
|
+
# @param [Class] klass
|
148
|
+
# @return [void]
|
149
|
+
#
|
150
|
+
# @overload reader
|
151
|
+
# Defines the reader class for this RDF serialization format.
|
152
|
+
#
|
153
|
+
# The block should return a subclass of {RDF::Reader}, or a class that
|
154
|
+
# implements the same interface. The block won't be invoked until the
|
155
|
+
# reader class is first needed.
|
156
|
+
#
|
157
|
+
# @yield
|
158
|
+
# @yieldreturn [Class] klass
|
159
|
+
# @return [void]
|
160
|
+
#
|
161
|
+
# @overload reader
|
162
|
+
# Retrieves the reader class for this RDF serialization format.
|
163
|
+
#
|
164
|
+
# @return [Class]
|
165
|
+
#
|
166
|
+
# @return [void]
|
167
|
+
def self.reader(klass = nil, &block)
|
168
|
+
case
|
169
|
+
when klass
|
170
|
+
@@readers[self] = klass
|
171
|
+
when block_given?
|
172
|
+
@@readers[self] = block
|
173
|
+
else
|
174
|
+
klass = @@readers[self]
|
175
|
+
klass = @@readers[self] = klass.call if klass.is_a?(Proc)
|
176
|
+
klass
|
39
177
|
end
|
40
178
|
end
|
41
179
|
|
42
180
|
##
|
43
|
-
#
|
44
|
-
#
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
181
|
+
# Retrieves or defines the writer class for this RDF serialization
|
182
|
+
# format.
|
183
|
+
#
|
184
|
+
# @overload writer(klass)
|
185
|
+
# Defines the writer class for this RDF serialization format.
|
186
|
+
#
|
187
|
+
# The class should be a subclass of {RDF::Writer}, or implement the
|
188
|
+
# same interface.
|
189
|
+
#
|
190
|
+
# @param [Class] klass
|
191
|
+
# @return [void]
|
192
|
+
#
|
193
|
+
# @overload writer
|
194
|
+
# Defines the writer class for this RDF serialization format.
|
195
|
+
#
|
196
|
+
# The block should return a subclass of {RDF::Writer}, or a class that
|
197
|
+
# implements the same interface. The block won't be invoked until the
|
198
|
+
# writer class is first needed.
|
199
|
+
#
|
200
|
+
# @yield
|
201
|
+
# @yieldreturn [Class] klass
|
202
|
+
# @return [void]
|
203
|
+
#
|
204
|
+
# @overload writer
|
205
|
+
# Retrieves the writer class for this RDF serialization format.
|
206
|
+
#
|
207
|
+
# @return [Class]
|
208
|
+
#
|
209
|
+
# @return [void]
|
210
|
+
def self.writer(klass = nil, &block)
|
211
|
+
case
|
212
|
+
when klass
|
213
|
+
@@writers[self] = klass
|
214
|
+
when block_given?
|
215
|
+
@@writers[self] = block
|
216
|
+
else
|
217
|
+
klass = @@writers[self]
|
218
|
+
klass = @@writers[self] = klass.call if klass.is_a?(Proc)
|
219
|
+
klass
|
53
220
|
end
|
54
221
|
end
|
55
222
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
@@content_types = {} # @private
|
61
|
-
@@content_encoding = {} # @private
|
223
|
+
class << self
|
224
|
+
alias_method :reader_class, :reader
|
225
|
+
alias_method :writer_class, :writer
|
226
|
+
end
|
62
227
|
|
63
|
-
|
64
|
-
@@subclasses << child
|
65
|
-
super
|
66
|
-
end
|
228
|
+
protected
|
67
229
|
|
230
|
+
##
|
231
|
+
# Defines a required Ruby library for this RDF serialization format.
|
232
|
+
#
|
233
|
+
# The given library will be required lazily, i.e. only when it is
|
234
|
+
# actually first needed, such as when instantiating a reader or parser
|
235
|
+
# instance for this format.
|
236
|
+
#
|
237
|
+
# @param [String, #to_s] library
|
238
|
+
# @return [void]
|
68
239
|
def self.require(library)
|
69
|
-
|
240
|
+
(@@requires[self] ||= []) << library.to_s
|
70
241
|
end
|
71
242
|
|
243
|
+
##
|
244
|
+
# Defines MIME content types for this RDF serialization format.
|
245
|
+
#
|
246
|
+
# Optionally also defines a file extension, or a list of file
|
247
|
+
# extensions, that should be mapped to the given MIME type and handled
|
248
|
+
# by this class.
|
249
|
+
#
|
250
|
+
# @param [String] type
|
251
|
+
# @param [Hash{Symbol => Object}] options
|
252
|
+
# @option options [Symbol] :extension (nil)
|
253
|
+
# @option options [Array<Symbol>] :extensions (nil)
|
254
|
+
# @return [void]
|
72
255
|
def self.content_type(type, options = {})
|
73
|
-
@@content_types[type] ||= []
|
74
|
-
@@content_types[type] << self
|
256
|
+
(@@content_types[type] ||= []) << self
|
75
257
|
|
76
|
-
if options[:extension]
|
77
|
-
extensions = [
|
258
|
+
if extensions = (options[:extension] || options[:extensions])
|
259
|
+
extensions = [extensions].flatten.map { |ext| ext.to_sym }
|
78
260
|
extensions.each { |ext| @@file_extensions[ext] = type }
|
79
261
|
end
|
80
262
|
end
|
81
263
|
|
264
|
+
##
|
265
|
+
# Defines the content encoding for this RDF serialization format.
|
266
|
+
#
|
267
|
+
# @param [#to_sym] encoding
|
268
|
+
# @return [void]
|
82
269
|
def self.content_encoding(encoding)
|
83
270
|
@@content_encoding[self] = encoding.to_sym
|
84
271
|
end
|
85
272
|
|
86
|
-
|
87
|
-
|
88
|
-
|
273
|
+
private
|
274
|
+
|
275
|
+
private_class_method :new
|
89
276
|
|
90
|
-
|
91
|
-
|
277
|
+
@@subclasses = [] # @private
|
278
|
+
@@requires = {} # @private
|
279
|
+
@@file_extensions = {} # @private
|
280
|
+
@@content_types = {} # @private
|
281
|
+
@@content_encoding = {} # @private
|
282
|
+
@@readers = {} # @private
|
283
|
+
@@writers = {} # @private
|
284
|
+
|
285
|
+
def self.inherited(child) # @private
|
286
|
+
@@subclasses << child
|
287
|
+
super
|
92
288
|
end
|
93
289
|
|
94
290
|
end
|
291
|
+
|
292
|
+
class FormatError < IOError; end
|
95
293
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module RDF
|
2
|
+
##
|
3
|
+
# An RDF graph.
|
4
|
+
class Graph < Resource
|
5
|
+
include RDF::Enumerable
|
6
|
+
|
7
|
+
# @return [URI]
|
8
|
+
attr_accessor :uri
|
9
|
+
|
10
|
+
# @return [Array<Statement>]
|
11
|
+
attr_accessor :data
|
12
|
+
|
13
|
+
##
|
14
|
+
# @param [URI] uri
|
15
|
+
# @yield [graph]
|
16
|
+
# @yieldparam [Graph]
|
17
|
+
def initialize(uri = nil, options = {}, &block)
|
18
|
+
@uri, @options = uri, options
|
19
|
+
|
20
|
+
if block_given?
|
21
|
+
case block.arity
|
22
|
+
when 1 then block.call(self)
|
23
|
+
else instance_eval(&block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Returns `true`.
|
30
|
+
#
|
31
|
+
# @return [Boolean]
|
32
|
+
def graph?
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# @return [Boolean]
|
38
|
+
def named?() !unnamed? end
|
39
|
+
|
40
|
+
##
|
41
|
+
# @return [Boolean]
|
42
|
+
def unnamed?() uri.nil? end
|
43
|
+
|
44
|
+
##
|
45
|
+
# @return [Integer]
|
46
|
+
def size() @data.size end
|
47
|
+
|
48
|
+
##
|
49
|
+
# @yield [statement]
|
50
|
+
# @yieldparam [Array<Statement>]
|
51
|
+
# @return [Graph]
|
52
|
+
def each(&block)
|
53
|
+
@data.each(&block)
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# @return [Resource]
|
58
|
+
def context() uri end
|
59
|
+
|
60
|
+
##
|
61
|
+
# @param [Statement, Array(Value)]
|
62
|
+
# @return [Graph]
|
63
|
+
def <<(statement)
|
64
|
+
@data << case statement
|
65
|
+
when Array then Statement.new(*statement)
|
66
|
+
when Statement then statement
|
67
|
+
else statement
|
68
|
+
end
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# @return [URI]
|
74
|
+
def to_uri() uri end
|
75
|
+
|
76
|
+
##
|
77
|
+
# @return [String]
|
78
|
+
def to_s
|
79
|
+
named? ? uri.to_s : "<>"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -29,8 +29,8 @@ module RDF
|
|
29
29
|
# @example Creating implicitly datatyped literals
|
30
30
|
# RDF::Literal.new(false).datatype #=> XSD.boolean
|
31
31
|
# RDF::Literal.new(true).datatype #=> XSD.boolean
|
32
|
-
# RDF::Literal.new(123).datatype #=> XSD.
|
33
|
-
# RDF::Literal.new(9223372036854775807).datatype #=> XSD.
|
32
|
+
# RDF::Literal.new(123).datatype #=> XSD.integer
|
33
|
+
# RDF::Literal.new(9223372036854775807).datatype #=> XSD.integer
|
34
34
|
# RDF::Literal.new(3.1415).datatype #=> XSD.double
|
35
35
|
# RDF::Literal.new(Time.now).datatype #=> XSD.dateTime
|
36
36
|
# RDF::Literal.new(Date.new(2010)).datatype #=> XSD.date
|
@@ -63,8 +63,8 @@ module RDF
|
|
63
63
|
when String then nil # implicit XSD.string
|
64
64
|
when TrueClass then XSD.boolean
|
65
65
|
when FalseClass then XSD.boolean
|
66
|
-
when Fixnum then XSD.
|
67
|
-
when Integer then XSD.
|
66
|
+
when Fixnum then XSD.integer
|
67
|
+
when Integer then XSD.integer
|
68
68
|
when Float
|
69
69
|
@value = case
|
70
70
|
when value.nan? then 'NaN'
|
@@ -80,12 +80,55 @@ module RDF
|
|
80
80
|
when Date then XSD.date
|
81
81
|
when Time then XSD.dateTime
|
82
82
|
end
|
83
|
+
else
|
84
|
+
require 'bigdecimal' unless defined?(BigDecimal)
|
85
|
+
case value
|
86
|
+
when BigDecimal
|
87
|
+
case
|
88
|
+
when value.nan? then 'NaN'
|
89
|
+
when value.infinite? then value.to_s[0...-'inity'.length].upcase
|
90
|
+
when value.finite? then value.to_s('F')
|
91
|
+
end
|
92
|
+
end
|
83
93
|
end
|
84
94
|
end
|
85
95
|
|
86
96
|
@value = @value.to_s
|
87
97
|
end
|
88
98
|
|
99
|
+
##
|
100
|
+
# @return [Object]
|
101
|
+
def object
|
102
|
+
case datatype
|
103
|
+
when XSD.string, nil
|
104
|
+
value
|
105
|
+
when XSD.boolean
|
106
|
+
%w(true 1).include?(value)
|
107
|
+
when XSD.double, XSD.float
|
108
|
+
value.to_f
|
109
|
+
when XSD.integer, XSD.long, XSD.int, XSD.short, XSD.byte
|
110
|
+
value.to_i
|
111
|
+
when XSD.decimal
|
112
|
+
require 'bigdecimal' unless defined?(BigDecimal)
|
113
|
+
BigDecimal.new(value)
|
114
|
+
when XSD.date
|
115
|
+
require 'date' unless defined?(Date)
|
116
|
+
Date.parse(value)
|
117
|
+
when XSD.dateTime
|
118
|
+
require 'date' unless defined?(DateTime)
|
119
|
+
DateTime.parse(value)
|
120
|
+
when XSD.time
|
121
|
+
require 'time'
|
122
|
+
Time.parse(value)
|
123
|
+
when XSD.nonPositiveInteger, XSD.negativeInteger
|
124
|
+
value.to_i
|
125
|
+
when XSD.nonNegativeInteger, XSD.positiveInteger
|
126
|
+
value.to_i
|
127
|
+
when XSD.unsignedLong, XSD.unsignedInt, XSD.unsignedShort, XSD.unsignedByte
|
128
|
+
value.to_i
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
89
132
|
##
|
90
133
|
# Returns `true`.
|
91
134
|
#
|