rdf 0.2.3 → 0.3.0.pre

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