rdf 0.1.10 → 0.2.0

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.
@@ -0,0 +1,131 @@
1
+ module RDF; module Util
2
+ ##
3
+ # A `Hash`-like cache that holds only weak references to the values it
4
+ # caches, meaning that values contained in the cache can be garbage
5
+ # collected. This allows the cache to dynamically adjust to changing
6
+ # memory conditions, caching more objects when memory is plentiful, but
7
+ # evicting most objects if memory pressure increases to the point of
8
+ # scarcity.
9
+ #
10
+ # @see RDF::URI.intern
11
+ # @see http://en.wikipedia.org/wiki/Weak_reference
12
+ # @since 0.2.0
13
+ class Cache
14
+ ##
15
+ # @private
16
+ def self.new(*args)
17
+ # JRuby doesn't support `ObjectSpace#_id2ref` unless the `-X+O`
18
+ # startup option is given, so on that platform we'll default to using
19
+ # the WeakRef-based cache:
20
+ klass = case RUBY_PLATFORM
21
+ when /java/ then WeakRefCache
22
+ else ObjectSpaceCache
23
+ end
24
+ cache = klass.allocate
25
+ cache.send(:initialize, *args)
26
+ cache
27
+ end
28
+
29
+ ##
30
+ # @param [Integer] capacity
31
+ def initialize(capacity = -1)
32
+ @capacity = capacity
33
+ @cache ||= {}
34
+ @index ||= {}
35
+ end
36
+
37
+ ##
38
+ # @return [Integer]
39
+ def size
40
+ @cache.size
41
+ end
42
+
43
+ ##
44
+ # @return [Boolean]
45
+ def has_capacity?
46
+ @capacity == -1 || @capacity > @cache.size
47
+ end
48
+
49
+ ##
50
+ # @param [Object] value
51
+ # @return [void]
52
+ def define_finalizer!(value)
53
+ ObjectSpace.define_finalizer(value, finalizer)
54
+ end
55
+
56
+ ##
57
+ # @return [Proc]
58
+ def finalizer
59
+ lambda { |object_id| @cache.delete(@index.delete(object_id)) }
60
+ end
61
+
62
+ ##
63
+ # This implementation relies on `ObjectSpace#_id2ref` and performs
64
+ # optimally on Ruby 1.8.x and 1.9.x; however, it does not work on JRuby
65
+ # by default since much `ObjectSpace` functionality on that platform is
66
+ # disabled unless the `-X+O` startup option is given.
67
+ #
68
+ # @see http://ruby-doc.org/ruby-1.9/classes/ObjectSpace.html
69
+ # @see http://eigenclass.org/hiki/weakhash+and+weakref
70
+ class ObjectSpaceCache < Cache
71
+ ##
72
+ # @param [Object] key
73
+ # @return [Object]
74
+ def [](key)
75
+ if value_id = @cache[key]
76
+ value = ObjectSpace._id2ref(value_id)
77
+ end
78
+ end
79
+
80
+ ##
81
+ # @param [Object] key
82
+ # @param [Object] value
83
+ # @return [Object]
84
+ def []=(key, value)
85
+ if has_capacity?
86
+ @cache[key] = value.object_id
87
+ @index[value.object_id] = key
88
+ define_finalizer!(value)
89
+ end
90
+ value
91
+ end
92
+ end # class ObjectSpaceCache
93
+
94
+ ##
95
+ # This implementation uses the `WeakRef` class from Ruby's standard
96
+ # library, and provides adequate performance on JRuby and on Ruby 1.9.x;
97
+ # however, it performs very suboptimally on Ruby 1.8.x.
98
+ #
99
+ # @see http://ruby-doc.org/ruby-1.9/classes/WeakRef.html
100
+ class WeakRefCache < Cache
101
+ ##
102
+ # @param [Integer] capacity
103
+ def initialize(capacity = -1)
104
+ require 'weakref' unless defined?(::WeakRef)
105
+ super
106
+ end
107
+
108
+ ##
109
+ # @param [Object] key
110
+ # @return [Object]
111
+ def [](key)
112
+ if (ref = @cache[key]) && ref.weakref_alive?
113
+ value = ref.__getobj__
114
+ end
115
+ end
116
+
117
+ ##
118
+ # @param [Object] key
119
+ # @param [Object] value
120
+ # @return [Object]
121
+ def []=(key, value)
122
+ if has_capacity?
123
+ @cache[key] = WeakRef.new(value)
124
+ @index[value.object_id] = key
125
+ define_finalizer!(value)
126
+ end
127
+ value
128
+ end
129
+ end # class WeakRefCache
130
+ end # class Cache
131
+ end; end # module RDF::Util
@@ -1,12 +1,11 @@
1
1
  module RDF
2
2
  module VERSION
3
3
  MAJOR = 0
4
- MINOR = 1
5
- TINY = 10
4
+ MINOR = 2
5
+ TINY = 0
6
6
  EXTRA = nil
7
7
 
8
- STRING = [MAJOR, MINOR, TINY].join('.')
9
- STRING << ".#{EXTRA}" if EXTRA
8
+ STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
10
9
 
11
10
  ##
12
11
  # @return [String]
@@ -7,14 +7,17 @@ module RDF
7
7
  # The following vocabularies are pre-defined for your convenience:
8
8
  #
9
9
  # * {RDF::CC} - Creative Commons (CC)
10
+ # * {RDF::CERT} - W3 Authentication Certificate (CERT)
10
11
  # * {RDF::DC} - Dublin Core (DC)
11
12
  # * {RDF::DC11} - Dublin Core 1.1 (DC11) _deprecated_
12
13
  # * {RDF::DOAP} - Description of a Project (DOAP)
13
14
  # * {RDF::EXIF} - Exchangeable Image File Format (EXIF)
14
15
  # * {RDF::FOAF} - Friend of a Friend (FOAF)
16
+ # * {RDF::GEO} - WGS84 Geo Positioning (GEO)
15
17
  # * {RDF::HTTP} - Hypertext Transfer Protocol (HTTP)
16
18
  # * {RDF::OWL} - Web Ontology Language (OWL)
17
19
  # * {RDF::RDFS} - RDF Schema (RDFS)
20
+ # * {RDF::RSA} - W3 RSA Keys (RSA)
18
21
  # * {RDF::RSS} - RDF Site Summary (RSS)
19
22
  # * {RDF::SIOC} - Semantically-Interlinked Online Communities (SIOC)
20
23
  # * {RDF::SKOS} - Simple Knowledge Organization System (SKOS)
@@ -52,11 +55,9 @@ module RDF
52
55
  def self.each(&block)
53
56
  if self.equal?(Vocabulary)
54
57
  # This is needed since all vocabulary classes are defined using
55
- # Ruby's autoloading facility, meaning that `@@subclasses` will
56
- # be empty until each subclass has been touched or require'd.
57
- %w(cc dc dc11 doap exif foaf http owl rdfs rss sioc skos wot xhtml xsd).each do |prefix|
58
- require "rdf/vocab/#{prefix}"
59
- end
58
+ # Ruby's autoloading facility, meaning that `@@subclasses` will be
59
+ # empty until each subclass has been touched or require'd.
60
+ RDF::VOCABS.each { |v| require "rdf/vocab/#{v}" unless v == :rdf }
60
61
  @@subclasses.each(&block)
61
62
  else
62
63
  # TODO: should enumerate vocabulary-specific defined properties.
@@ -79,7 +80,7 @@ module RDF
79
80
  # @param [#to_s] property
80
81
  # @return [URI]
81
82
  def self.[](property)
82
- RDF::URI.new([to_s, property.to_s].join(''))
83
+ RDF::URI.intern([to_s, property.to_s].join(''))
83
84
  end
84
85
 
85
86
  ##
@@ -87,7 +88,7 @@ module RDF
87
88
  #
88
89
  # @return [URI]
89
90
  def self.to_uri
90
- RDF::URI.new(to_s)
91
+ RDF::URI.intern(to_s)
91
92
  end
92
93
 
93
94
  ##
@@ -117,7 +118,7 @@ module RDF
117
118
  end
118
119
 
119
120
  # Undefine all superfluous instance methods:
120
- undef_method *(instance_methods.map { |s| s.to_sym } - [:__id__, :__send__, :__class__, :__eval__, :object_id, :instance_eval, :inspect, :class, :is_a?])
121
+ undef_method(*(instance_methods.map(&:to_sym) - [:__id__, :__send__, :__class__, :__eval__, :object_id, :instance_eval, :inspect, :class, :is_a?]))
121
122
 
122
123
  ##
123
124
  # @param [URI, String, #to_s]
@@ -134,7 +135,7 @@ module RDF
134
135
  # @param [#to_s] property
135
136
  # @return [URI]
136
137
  def [](property)
137
- RDF::URI.new([to_s, property.to_s].join(''))
138
+ RDF::URI.intern([to_s, property.to_s].join(''))
138
139
  end
139
140
 
140
141
  ##
@@ -142,7 +143,7 @@ module RDF
142
143
  #
143
144
  # @return [URI]
144
145
  def to_uri
145
- RDF::URI.new(to_s)
146
+ RDF::URI.intern(to_s)
146
147
  end
147
148
 
148
149
  ##
@@ -0,0 +1,13 @@
1
+ module RDF
2
+ ##
3
+ # W3 Authentication Certificates (CERT) vocabulary.
4
+ #
5
+ # @see http://www.w3.org/ns/auth/cert#
6
+ # @since 0.2.0
7
+ class CERT < Vocabulary("http://www.w3.org/ns/auth/cert#")
8
+ property :decimal
9
+ property :hex
10
+ property :identity
11
+ property :public_key
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module RDF
2
+ ##
3
+ # WGS84 Geo Positioning (GEO) vocabulary.
4
+ #
5
+ # @see http://www.w3.org/2003/01/geo/wgs84_pos#
6
+ # @since 0.2.0
7
+ class GEO < Vocabulary("http://www.w3.org/2003/01/geo/wgs84_pos#")
8
+ property :lat
9
+ property :location
10
+ property :long
11
+ property :lat_long
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module RDF
2
+ ##
3
+ # W3 RSA Keys (RSA) vocabulary.
4
+ #
5
+ # @see http://www.w3.org/ns/auth/rsa#
6
+ # @since 0.2.0
7
+ class RSA < Vocabulary("http://www.w3.org/ns/auth/rsa#")
8
+ property :modulus
9
+ property :private_exponent
10
+ property :public_exponent
11
+ end
12
+ end
@@ -34,7 +34,7 @@ module RDF
34
34
  # @see RDF::Reader
35
35
  class Writer
36
36
  extend ::Enumerable
37
- include ::Enumerable
37
+ include RDF::Writable
38
38
 
39
39
  ##
40
40
  # Enumerates known RDF writer classes.
@@ -96,24 +96,34 @@ module RDF
96
96
  alias_method :format_class, :format
97
97
  end
98
98
 
99
+ ##
100
+ # @param [Object] data
101
+ # @param [IO, File] io
102
+ # @param [Hash{Symbol => Object}] options
103
+ # @return [void]
99
104
  def self.dump(data, io = nil, options = {})
100
105
  io = File.open(io, 'w') if io.is_a?(String)
106
+ method = data.respond_to?(:each_statement) ? :each_statement : :each
101
107
  if io
102
108
  new(io) do |writer|
103
- data.each_statement do |statement|
109
+ data.send(method) do |statement|
104
110
  writer << statement
105
111
  end
106
112
  writer.flush
107
113
  end
108
114
  else
109
115
  buffer do |writer|
110
- data.each_statement do |statement|
116
+ data.send(method) do |statement|
111
117
  writer << statement
112
118
  end
113
119
  end
114
120
  end
115
121
  end
116
122
 
123
+ ##
124
+ # @yield [writer]
125
+ # @yieldparam [Writer] writer
126
+ # @return [String]
117
127
  def self.buffer(*args, &block)
118
128
  require 'stringio' unless defined?(StringIO)
119
129
 
@@ -123,6 +133,10 @@ module RDF
123
133
  end
124
134
  end
125
135
 
136
+ ##
137
+ # @param [String] filename
138
+ # @param [Hash{Symbol => Object}] options
139
+ # @return [Writer]
126
140
  def self.open(filename, options = {}, &block)
127
141
  File.open(filename, 'wb') do |file|
128
142
  self.for(options[:format] || filename).new(file, options, &block)
@@ -135,16 +149,29 @@ module RDF
135
149
  # @yield [writer]
136
150
  # @yieldparam [RDF::Writer] writer
137
151
  def initialize(output = $stdout, options = {}, &block)
138
- @output, @options = output, options
139
- @nodes, @node_id = {}, 0
152
+ @output, @options = output, options.dup
153
+ @nodes, @node_id = {}, 0
140
154
 
141
155
  if block_given?
142
156
  write_prologue
143
- block.call(self)
157
+ case block.arity
158
+ when 1 then block.call(self)
159
+ else instance_eval(&block)
160
+ end
144
161
  write_epilogue
145
162
  end
146
163
  end
147
164
 
165
+ ##
166
+ # Flushes the underlying output buffer.
167
+ #
168
+ # @return [void]
169
+ def flush
170
+ @output.flush if @output.respond_to?(:flush)
171
+ end
172
+
173
+ alias_method :flush!, :flush
174
+
148
175
  ##
149
176
  # @return [void]
150
177
  # @abstract
@@ -156,84 +183,57 @@ module RDF
156
183
  def write_epilogue() end
157
184
 
158
185
  ##
186
+ # @param [String] text
159
187
  # @return [void]
160
188
  # @abstract
161
189
  def write_comment(text) end
162
190
 
163
191
  ##
164
- # @raise [ArgumentError]
165
- def <<(data)
166
- case data # TODO
167
- #when Graph
168
- # write_graph(data)
169
- #when Resource
170
- # #register!(resource) && write_node(resource)
171
- # write_resource(data)
172
- when Statement
173
- write_statement(data)
174
- else
175
- if data.respond_to?(:to_a)
176
- write_triple(*data.to_a)
177
- else
178
- raise ArgumentError.new("expected RDF::Statement or RDF::Resource, got #{data.inspect}")
179
- end
180
- end
181
- end
182
-
183
- ##
184
- # @param [Graph] graph
192
+ # @param [RDF::Graph] graph
185
193
  # @return [void]
186
194
  def write_graph(graph)
187
- write_triples(*graph.triples)
195
+ graph.each_triple { |*triple| write_triple(*triple) }
188
196
  end
189
197
 
190
198
  ##
191
- # @return [void]
192
- def write_resource(subject) # FIXME
193
- edge_nodes = []
194
- subject.each do |predicate, objects|
195
- [objects].flatten.each do |object|
196
- edge_nodes << object if register!(object)
197
- write_triple subject, predicate, object
198
- end
199
- end
200
- edge_nodes.each { |node| write_resource node }
201
- end
202
-
203
- ##
204
- # @param [Array<Statement>] statements
199
+ # @param [Array<RDF::Statement>] statements
205
200
  # @return [void]
206
201
  def write_statements(*statements)
207
- statements.flatten.each { |stmt| write_statement(stmt) }
202
+ statements.flatten.each { |statement| write_statement(statement) }
208
203
  end
209
204
 
210
205
  ##
211
- # @param [Statement] statement
206
+ # @param [RDF::Statement] statement
212
207
  # @return [void]
213
208
  def write_statement(statement)
214
- write_triple(*statement.to_a)
209
+ write_triple(*statement.to_triple)
215
210
  end
216
211
 
217
212
  ##
218
- # @param [Array<Array(Value)>] triples
213
+ # @param [Array<Array(RDF::Resource, RDF::URI, RDF::Value)>] triples
219
214
  # @return [void]
220
215
  def write_triples(*triples)
221
216
  triples.each { |triple| write_triple(*triple) }
222
217
  end
223
218
 
224
219
  ##
225
- # @param [Resource] subject
226
- # @param [URI] predicate
227
- # @param [Value] object
220
+ # @param [RDF::Resource] subject
221
+ # @param [RDF::URI] predicate
222
+ # @param [RDF::Value] object
228
223
  # @return [void]
229
224
  # @raise [NotImplementedError] unless implemented in subclass
230
225
  # @abstract
231
226
  def write_triple(subject, predicate, object)
232
- raise NotImplementedError # override in subclasses
227
+ raise NotImplementedError.new("#{self.class}#write_triple") # override in subclasses
233
228
  end
234
229
 
230
+ # Support the RDF::Writable interface:
231
+ alias_method :insert_graph, :write_graph
232
+ alias_method :insert_statements, :write_statements
233
+ alias_method :insert_statement, :write_statement
234
+
235
235
  ##
236
- # @param [Value] value
236
+ # @param [RDF::Value] value
237
237
  # @return [String]
238
238
  def format_value(value, options = {})
239
239
  case value
@@ -252,7 +252,7 @@ module RDF
252
252
  # @raise [NotImplementedError] unless implemented in subclass
253
253
  # @abstract
254
254
  def format_uri(value, options = {})
255
- raise NotImplementedError # override in subclasses
255
+ raise NotImplementedError.new("#{self.class}#format_uri") # override in subclasses
256
256
  end
257
257
 
258
258
  ##
@@ -262,7 +262,7 @@ module RDF
262
262
  # @raise [NotImplementedError] unless implemented in subclass
263
263
  # @abstract
264
264
  def format_node(value, options = {})
265
- raise NotImplementedError # override in subclasses
265
+ raise NotImplementedError.new("#{self.class}#format_node") # override in subclasses
266
266
  end
267
267
 
268
268
  ##
@@ -272,78 +272,71 @@ module RDF
272
272
  # @raise [NotImplementedError] unless implemented in subclass
273
273
  # @abstract
274
274
  def format_literal(value, options = {})
275
- raise NotImplementedError # override in subclasses
275
+ raise NotImplementedError.new("#{self.class}#format_literal") # override in subclasses
276
276
  end
277
277
 
278
+ protected
279
+
278
280
  ##
279
- # Flushes the underlying output buffer.
280
- #
281
281
  # @return [void]
282
- def flush
283
- @output.flush if @output.respond_to?(:flush)
282
+ def puts(*args)
283
+ @output.puts(*args)
284
284
  end
285
285
 
286
- alias_method :flush!, :flush
287
-
288
- protected
289
-
290
- def puts(*args)
291
- @output.puts(*args)
292
- end
293
-
294
- ##
295
- # @param [Resource] uriref
296
- # @return [String]
297
- def uri_for(uriref)
298
- case
299
- when uriref.is_a?(RDF::Node)
300
- @nodes[uriref]
301
- when uriref.respond_to?(:to_uri)
302
- uriref.to_uri.to_s
303
- else
304
- uriref.to_s
305
- end
286
+ ##
287
+ # @param [RDF::Resource] uriref
288
+ # @return [String]
289
+ def uri_for(uriref)
290
+ case
291
+ when uriref.is_a?(RDF::Node)
292
+ @nodes[uriref]
293
+ when uriref.respond_to?(:to_uri)
294
+ uriref.to_uri.to_s
295
+ else
296
+ uriref.to_s
306
297
  end
298
+ end
307
299
 
308
- ##
309
- # @return [String]
310
- def node_id
311
- "_:n#{@node_id += 1}"
312
- end
300
+ ##
301
+ # @return [String]
302
+ def node_id
303
+ "_:n#{@node_id += 1}"
304
+ end
313
305
 
314
- def register!(resource)
315
- if resource.kind_of?(RDF::Resource)
316
- unless @nodes[resource] # have we already seen it?
317
- @nodes[resource] = resource.uri || node_id
318
- end
306
+ ##
307
+ # @deprecated
308
+ def register!(resource)
309
+ if resource.kind_of?(RDF::Resource)
310
+ unless @nodes[resource] # have we already seen it?
311
+ @nodes[resource] = resource.uri || node_id
319
312
  end
320
313
  end
314
+ end
321
315
 
322
- ##
323
- # @param [String] string
324
- # @return [String]
325
- def escaped(string)
326
- string.gsub('\\', '\\\\').gsub("\t", '\\t').
327
- gsub("\n", '\\n').gsub("\r", '\\r').gsub('"', '\\"')
328
- end
329
-
330
- ##
331
- # @param [String] string
332
- # @return [String]
333
- def quoted(string)
334
- "\"#{string}\""
335
- end
316
+ ##
317
+ # @param [String] string
318
+ # @return [String]
319
+ def escaped(string)
320
+ string.gsub('\\', '\\\\').gsub("\t", '\\t').
321
+ gsub("\n", '\\n').gsub("\r", '\\r').gsub('"', '\\"')
322
+ end
336
323
 
337
- private
324
+ ##
325
+ # @param [String] string
326
+ # @return [String]
327
+ def quoted(string)
328
+ "\"#{string}\""
329
+ end
338
330
 
339
- @@subclasses = [] # @private
331
+ private
340
332
 
341
- def self.inherited(child) # @private
342
- @@subclasses << child
343
- super
344
- end
333
+ @@subclasses = [] # @private
345
334
 
346
- end
335
+ def self.inherited(child) # @private
336
+ @@subclasses << child
337
+ super
338
+ end
339
+ end # class Writer
347
340
 
348
341
  class WriterError < IOError; end
349
342
  end