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.
- data/AUTHORS +1 -0
- data/{CONTRIBUTORS → CREDITS} +3 -1
- data/README +17 -8
- data/VERSION +1 -1
- data/etc/doap.nt +28 -10
- data/lib/rdf/format.rb +55 -47
- data/lib/rdf/mixin/countable.rb +3 -6
- data/lib/rdf/mixin/enumerable.rb +69 -69
- data/lib/rdf/mixin/indexable.rb +26 -0
- data/lib/rdf/mixin/mutable.rb +2 -2
- data/lib/rdf/mixin/queryable.rb +50 -12
- data/lib/rdf/mixin/writable.rb +8 -19
- data/lib/rdf/model/literal/boolean.rb +42 -6
- data/lib/rdf/model/literal/date.rb +17 -5
- data/lib/rdf/model/literal/datetime.rb +18 -6
- data/lib/rdf/model/literal/decimal.rb +32 -5
- data/lib/rdf/model/literal/double.rb +32 -5
- data/lib/rdf/model/literal/integer.rb +16 -5
- data/lib/rdf/model/literal/time.rb +6 -6
- data/lib/rdf/model/literal/token.rb +5 -5
- data/lib/rdf/model/literal/xml.rb +5 -5
- data/lib/rdf/model/literal.rb +24 -11
- data/lib/rdf/model/node.rb +14 -13
- data/lib/rdf/model/uri.rb +315 -42
- data/lib/rdf/model/value.rb +1 -1
- data/lib/rdf/ntriples/reader.rb +23 -15
- data/lib/rdf/ntriples/writer.rb +1 -1
- data/lib/rdf/query/pattern.rb +131 -15
- data/lib/rdf/query/solution.rb +94 -29
- data/lib/rdf/query/solutions.rb +202 -0
- data/lib/rdf/query/variable.rb +42 -18
- data/lib/rdf/query.rb +210 -160
- data/lib/rdf/reader.rb +300 -112
- data/lib/rdf/repository.rb +88 -6
- data/lib/rdf/transaction.rb +161 -0
- data/lib/rdf/util/cache.rb +5 -0
- data/lib/rdf/util/file.rb +31 -0
- data/lib/rdf/util/uuid.rb +36 -0
- data/lib/rdf/util.rb +2 -0
- data/lib/rdf/version.rb +3 -3
- data/lib/rdf/vocab.rb +43 -35
- data/lib/rdf/writer.rb +105 -50
- data/lib/rdf.rb +29 -27
- 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
|
data/lib/rdf/util/cache.rb
CHANGED
@@ -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
data/lib/rdf/version.rb
CHANGED
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
|
-
|
176
|
+
protected
|
168
177
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
178
|
+
def self.create(uri) # @private
|
179
|
+
@@uri = uri
|
180
|
+
self
|
181
|
+
end
|
173
182
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
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
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
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
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
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
|
-
|
201
|
-
|
202
|
-
@@subclasses = [::RDF] # @private
|
203
|
-
@@uris = {} # @private
|
204
|
-
@@uri = nil # @private
|
209
|
+
private
|
205
210
|
|
206
|
-
|
207
|
-
|
211
|
+
@@subclasses = [::RDF] # @private
|
212
|
+
@@uris = {} # @private
|
213
|
+
@@uri = nil # @private
|
214
|
+
end # Vocabulary
|
215
|
+
end # RDF
|