rdf 0.2.3 → 0.3.0.pre

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 (44) hide show
  1. data/AUTHORS +1 -0
  2. data/{CONTRIBUTORS → CREDITS} +3 -1
  3. data/README +17 -8
  4. data/VERSION +1 -1
  5. data/etc/doap.nt +28 -10
  6. data/lib/rdf/format.rb +55 -47
  7. data/lib/rdf/mixin/countable.rb +3 -6
  8. data/lib/rdf/mixin/enumerable.rb +69 -69
  9. data/lib/rdf/mixin/indexable.rb +26 -0
  10. data/lib/rdf/mixin/mutable.rb +2 -2
  11. data/lib/rdf/mixin/queryable.rb +50 -12
  12. data/lib/rdf/mixin/writable.rb +8 -19
  13. data/lib/rdf/model/literal/boolean.rb +42 -6
  14. data/lib/rdf/model/literal/date.rb +17 -5
  15. data/lib/rdf/model/literal/datetime.rb +18 -6
  16. data/lib/rdf/model/literal/decimal.rb +32 -5
  17. data/lib/rdf/model/literal/double.rb +32 -5
  18. data/lib/rdf/model/literal/integer.rb +16 -5
  19. data/lib/rdf/model/literal/time.rb +6 -6
  20. data/lib/rdf/model/literal/token.rb +5 -5
  21. data/lib/rdf/model/literal/xml.rb +5 -5
  22. data/lib/rdf/model/literal.rb +24 -11
  23. data/lib/rdf/model/node.rb +14 -13
  24. data/lib/rdf/model/uri.rb +315 -42
  25. data/lib/rdf/model/value.rb +1 -1
  26. data/lib/rdf/ntriples/reader.rb +23 -15
  27. data/lib/rdf/ntriples/writer.rb +1 -1
  28. data/lib/rdf/query/pattern.rb +131 -15
  29. data/lib/rdf/query/solution.rb +94 -29
  30. data/lib/rdf/query/solutions.rb +202 -0
  31. data/lib/rdf/query/variable.rb +42 -18
  32. data/lib/rdf/query.rb +210 -160
  33. data/lib/rdf/reader.rb +300 -112
  34. data/lib/rdf/repository.rb +88 -6
  35. data/lib/rdf/transaction.rb +161 -0
  36. data/lib/rdf/util/cache.rb +5 -0
  37. data/lib/rdf/util/file.rb +31 -0
  38. data/lib/rdf/util/uuid.rb +36 -0
  39. data/lib/rdf/util.rb +2 -0
  40. data/lib/rdf/version.rb +3 -3
  41. data/lib/rdf/vocab.rb +43 -35
  42. data/lib/rdf/writer.rb +105 -50
  43. data/lib/rdf.rb +29 -27
  44. metadata +26 -17
@@ -0,0 +1,161 @@
1
+ module RDF
2
+ ##
3
+ # An RDF transaction.
4
+ #
5
+ # Transactions consist of a sequence of RDF statements to delete from and
6
+ # a sequence of RDF statements to insert into a given named graph.
7
+ #
8
+ # @example Executing a transaction against a repository
9
+ # repository = ...
10
+ # RDF::Transaction.execute(repository) do |tx|
11
+ # subject = RDF::URI("http://example.org/article")
12
+ # tx.delete [subject, RDF::DC.title, "Old title"]
13
+ # tx.insert [subject, RDF::DC.title, "New title"]
14
+ # end
15
+ #
16
+ # @since 0.3.0
17
+ class Transaction
18
+ include RDF::Mutable
19
+
20
+ ##
21
+ # Executes a transaction against the given RDF repository.
22
+ #
23
+ # @param [RDF::Repository] repository
24
+ # @param [Hash{Symbol => Object}] options
25
+ # @yield [tx]
26
+ # @yieldparam [RDF::Transaction] tx
27
+ # @return [void]
28
+ def self.execute(repository, options = {}, &block)
29
+ self.new(&block).execute(repository, options)
30
+ end
31
+
32
+ ##
33
+ # RDF graph to modify when executed.
34
+ #
35
+ # @return [RDF::Resource]
36
+ attr_reader :graph
37
+
38
+ ##
39
+ # RDF statements to delete when executed.
40
+ #
41
+ # @return [RDF::Enumerable]
42
+ attr_reader :deletes
43
+
44
+ ##
45
+ # RDF statements to insert when executed.
46
+ #
47
+ # @return [RDF::Enumerable]
48
+ attr_reader :inserts
49
+
50
+ ##
51
+ # Any additional options for this transaction.
52
+ #
53
+ # @return [Hash{Symbol => Object}]
54
+ attr_reader :options
55
+
56
+ ##
57
+ # Initializes this transaction.
58
+ #
59
+ # @param [Hash{Symbol => Object}] options
60
+ # @option options [RDF::Resource] :graph (nil)
61
+ # @option options [RDF::Enumerable] :insert (RDF::Graph.new)
62
+ # @option options [RDF::Enumerable] :delete (RDF::Graph.new)
63
+ # @yield [tx]
64
+ # @yieldparam [RDF::Transaction] tx
65
+ def initialize(options = {}, &block)
66
+ @options = options.dup
67
+ @graph = @options.delete(:graph) || @options.delete(:context)
68
+ @inserts = @options.delete(:insert) || RDF::Graph.new
69
+ @deletes = @options.delete(:delete) || RDF::Graph.new
70
+ @inserts.extend(RDF::Enumerable) unless @inserts.kind_of?(RDF::Enumerable)
71
+ @deletes.extend(RDF::Enumerable) unless @deletes.kind_of?(RDF::Enumerable)
72
+
73
+ if block_given?
74
+ case block.arity
75
+ when 1 then block.call(self)
76
+ else instance_eval(&block)
77
+ end
78
+ end
79
+ end
80
+
81
+ ##
82
+ # Returns `false` to indicate that this transaction is append-only.
83
+ #
84
+ # Transactions do not support the `RDF::Enumerable` protocol directly.
85
+ # To enumerate the RDF statements to be inserted or deleted, use the
86
+ # {#inserts} and {#deletes} accessors.
87
+ #
88
+ # @return [Boolean]
89
+ # @see RDF::Readable#readable?
90
+ def readable?
91
+ false
92
+ end
93
+
94
+ ##
95
+ # Executes this transaction against the given RDF repository.
96
+ #
97
+ # @param [RDF::Repository] repository
98
+ # @param [Hash{Symbol => Object}] options
99
+ # @return [void]
100
+ def execute(repository, options = {})
101
+ before_execute(repository, options) if respond_to?(:before_execute)
102
+
103
+ deletes.each_statement do |statement|
104
+ statement = statement.dup
105
+ statement.context = graph
106
+ repository.delete(statement)
107
+ end
108
+
109
+ inserts.each_statement do |statement|
110
+ statement = statement.dup
111
+ statement.context = graph
112
+ repository.insert(statement)
113
+ end
114
+
115
+ after_execute(repository, options) if respond_to?(:after_execute)
116
+ self
117
+ end
118
+
119
+ ##
120
+ # Returns a developer-friendly representation of this transaction.
121
+ #
122
+ # @return [String]
123
+ def inspect
124
+ sprintf("#<%s:%#0x(graph: %s, deletes: %d, inserts: %d)>", self.class.name, __id__,
125
+ graph ? graph.to_s : 'nil', deletes.count, inserts.count)
126
+ end
127
+
128
+ ##
129
+ # Outputs a developer-friendly representation of this transaction to
130
+ # `stderr`.
131
+ #
132
+ # @return [void]
133
+ def inspect!
134
+ warn(inspect)
135
+ end
136
+
137
+ ##
138
+ # Appends an RDF statement to the sequence to insert when executed.
139
+ #
140
+ # @param [RDF::Statement] statement
141
+ # @return [void]
142
+ # @see RDF::Writable#insert_statement
143
+ def insert_statement(statement)
144
+ inserts << statement
145
+ end
146
+
147
+ ##
148
+ # Appends an RDF statement to the sequence to delete when executed.
149
+ #
150
+ # @param [RDF::Statement] statement
151
+ # @return [void]
152
+ # @see RDF::Mutable#delete_statement
153
+ def delete_statement(statement)
154
+ deletes << statement
155
+ end
156
+
157
+ undef_method :load, :update, :clear
158
+ protected :insert_statement
159
+ protected :delete_statement
160
+ end # Transaction
161
+ end # RDF
@@ -7,6 +7,11 @@ module RDF; module Util
7
7
  # evicting most objects if memory pressure increases to the point of
8
8
  # scarcity.
9
9
  #
10
+ # While this cache is something of an internal implementation detail of
11
+ # RDF.rb, some external libraries do currently make use of it as well,
12
+ # including [Spira](http://spira.rubyforge.org/). Do be sure to include
13
+ # any changes here in the RDF.rb changelog.
14
+ #
10
15
  # @see RDF::URI.intern
11
16
  # @see http://en.wikipedia.org/wiki/Weak_reference
12
17
  # @since 0.2.0
@@ -0,0 +1,31 @@
1
+ module RDF; module Util
2
+ ##
3
+ # Wrapper for Kernel.open. Allows implementations to override to get
4
+ # more suffisticated behavior for HTTP resources
5
+ #
6
+ # Classes include this module when they represent some form of a file
7
+ # as a base resource, for instance an HTTP resource representing the
8
+ # serialization of a Graph.
9
+ #
10
+ # This module may be monkey-patched to allow for more options
11
+ # and interfaces.
12
+ #
13
+ # @since 0.2.4
14
+ module File
15
+ # Content
16
+ # @return [String]
17
+ attr_accessor :content_type
18
+
19
+ ##
20
+ # Open the file, returning or yielding an IO stream and mime_type.
21
+ #
22
+ # @param [String] filename_or_url to open
23
+ # @param [Hash{Symbol => Object}] options
24
+ # any options to pass through to the underlying UUID library
25
+ # @return [IO] File stream
26
+ # @yield [IO] File stream
27
+ def self.open_file(filename_or_url, options = {}, &block)
28
+ Kernel.open(filename_or_url, &block)
29
+ end
30
+ end # File
31
+ end; end # RDF::Util
@@ -0,0 +1,36 @@
1
+ module RDF; module Util
2
+ ##
3
+ # Utilities for UUID handling.
4
+ #
5
+ # @see http://en.wikipedia.org/wiki/Universally_unique_identifier
6
+ module UUID
7
+ ##
8
+ # Generates a UUID string.
9
+ #
10
+ # This will make use of either the [UUID][] gem or the [UUIDTools][]
11
+ # gem, whichever of the two happens to be available.
12
+ #
13
+ # [UUID]: http://rubygems.org/gems/uuid
14
+ # [UUIDTools]: http://rubygems.org/gems/uuidtools
15
+ #
16
+ # @param [Hash{Symbol => Object}] options
17
+ # any options to pass through to the underlying UUID library
18
+ # @return [String] a UUID string
19
+ # @raise [LoadError] if no UUID library is available
20
+ # @see http://rubygems.org/gems/uuid
21
+ # @see http://rubygems.org/gems/uuidtools
22
+ def self.generate(options = {})
23
+ begin
24
+ require 'uuid'
25
+ ::UUID.generate(options[:format] || :default)
26
+ rescue LoadError => e
27
+ begin
28
+ require 'uuidtools'
29
+ ::UUIDTools::UUID.random_create.hexdigest
30
+ rescue LoadError => e
31
+ raise LoadError.new("no such file to load -- uuid or uuidtools")
32
+ end
33
+ end
34
+ end
35
+ end # UUID
36
+ end; end # RDF::Util
data/lib/rdf/util.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  module RDF; module Util
2
2
  autoload :Aliasing, 'rdf/util/aliasing'
3
3
  autoload :Cache, 'rdf/util/cache'
4
+ autoload :File, 'rdf/util/file'
5
+ autoload :UUID, 'rdf/util/uuid'
4
6
  end; end
data/lib/rdf/version.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  module RDF
2
2
  module VERSION
3
3
  MAJOR = 0
4
- MINOR = 2
5
- TINY = 3
6
- EXTRA = nil
4
+ MINOR = 3
5
+ TINY = 0
6
+ EXTRA = :pre
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
9
9
 
data/lib/rdf/vocab.rb CHANGED
@@ -80,7 +80,7 @@ module RDF
80
80
  # Returns the URI for the term `property` in this vocabulary.
81
81
  #
82
82
  # @param [#to_s] property
83
- # @return [URI]
83
+ # @return [RDF::URI]
84
84
  def self.[](property)
85
85
  RDF::URI.intern([to_s, property.to_s].join(''))
86
86
  end
@@ -88,7 +88,7 @@ module RDF
88
88
  ##
89
89
  # Returns the base URI for this vocabulary class.
90
90
  #
91
- # @return [URI]
91
+ # @return [RDF::URI]
92
92
  def self.to_uri
93
93
  RDF::URI.intern(to_s)
94
94
  end
@@ -119,11 +119,20 @@ module RDF
119
119
  alias_method :__name__, :name
120
120
  end
121
121
 
122
+ ##
123
+ # Returns a suggested CURIE/QName prefix for this vocabulary class.
124
+ #
125
+ # @return [Symbol]
126
+ # @since 0.3.0
127
+ def self.__prefix__
128
+ self.__name__.split('::').last.downcase.to_sym
129
+ end
130
+
122
131
  # Undefine all superfluous instance methods:
123
132
  undef_method(*(instance_methods.map(&:to_sym) - [:__id__, :__send__, :__class__, :__eval__, :object_id, :instance_eval, :inspect, :class, :is_a?]))
124
133
 
125
134
  ##
126
- # @param [URI, String, #to_s]
135
+ # @param [RDF::URI, String, #to_s]
127
136
  def initialize(uri)
128
137
  @uri = case uri
129
138
  when RDF::URI then uri.to_s
@@ -164,44 +173,43 @@ module RDF
164
173
  sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, to_s)
165
174
  end
166
175
 
167
- protected
176
+ protected
168
177
 
169
- def self.create(uri) # @private
170
- @@uri = uri
171
- self
172
- end
178
+ def self.create(uri) # @private
179
+ @@uri = uri
180
+ self
181
+ end
173
182
 
174
- def self.inherited(subclass) # @private
175
- @@subclasses << subclass
176
- unless @@uri.nil?
177
- subclass.send(:private_class_method, :new)
178
- @@uris[subclass] = @@uri
179
- @@uri = nil
180
- end
181
- super
183
+ def self.inherited(subclass) # @private
184
+ @@subclasses << subclass
185
+ unless @@uri.nil?
186
+ subclass.send(:private_class_method, :new)
187
+ @@uris[subclass] = @@uri
188
+ @@uri = nil
182
189
  end
190
+ super
191
+ end
183
192
 
184
- def self.method_missing(property, *args, &block)
185
- if args.empty? && @@uris.has_key?(self)
186
- self[property]
187
- else
188
- super
189
- end
193
+ def self.method_missing(property, *args, &block)
194
+ if args.empty? && @@uris.has_key?(self)
195
+ self[property]
196
+ else
197
+ super
190
198
  end
199
+ end
191
200
 
192
- def method_missing(property, *args, &block)
193
- if args.empty?
194
- self[property]
195
- else
196
- raise ArgumentError.new("wrong number of arguments (#{args.size} for 0)")
197
- end
201
+ def method_missing(property, *args, &block)
202
+ if args.empty?
203
+ self[property]
204
+ else
205
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 0)")
198
206
  end
207
+ end
199
208
 
200
- private
201
-
202
- @@subclasses = [::RDF] # @private
203
- @@uris = {} # @private
204
- @@uri = nil # @private
209
+ private
205
210
 
206
- end
207
- end
211
+ @@subclasses = [::RDF] # @private
212
+ @@uris = {} # @private
213
+ @@uri = nil # @private
214
+ end # Vocabulary
215
+ end # RDF