rdf-mongo 0.1.9.1 → 1.0.3

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/README.md CHANGED
@@ -15,7 +15,26 @@ It should also be noted that prior to 1.0, there are no guarantees of backwards
15
15
  You'll need the 'mongo', 'rdf', 'rdf-spec', and 'rspec' libraries. The easiest way to install these is via RubyGems.
16
16
 
17
17
  $ sudo gem install mongo rdf rdf-spec rspec rdf-mongo
18
-
18
+
19
+ ## Implementation Notes
20
+
21
+ RDF Statements are stored as individual documents within MONGO using the following BSON:
22
+
23
+ {
24
+ "s": RDF::Value
25
+ "st": one of :u or :n
26
+ "p": RDF::URI
27
+ "pt": must be :n
28
+ "o" RDF::Value
29
+ "ot" one of :u, :n, :l, :ll, or :lt
30
+ "ol" Language symbol or RDF::URI
31
+ "c" RDF::Value or false
32
+ "ct": one of :u, :n, :l, :ll, :lt or :default
33
+ }
34
+
35
+ An alternative that may be examined at a later point would be to use a representation based on RDF/JSON,
36
+ or JSON-LD. This would save documents based on a common subject with
37
+ one more more predicates having one or more types.
19
38
 
20
39
  ### Support
21
40
 
@@ -23,6 +42,7 @@ Please post questions or feedback to the [W3C-ruby-rdf mailing list][].
23
42
 
24
43
  ### Authors
25
44
  * [Pius Uzamere][] | <pius@alum.mit.edu> | <http://github.com/pius> | <http://pius.me>
45
+ * [Gregg Kellogg][] | <gregg@greggkellogg.net> | <http://github.com/gkellogg> | <http://greggkellogg.net>
26
46
 
27
47
  ### Thank you
28
48
 
@@ -34,3 +54,4 @@ MIT License
34
54
 
35
55
  [W3C-ruby-rdf mailing list]: http://lists.w3.org/Archives/Public/public-rdf-ruby/
36
56
  [Pius Uzamere]: http://pius.me
57
+ [Gregg Kellogg]: http://greggkellogg.net/me
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.9.1
1
+ 1.0.3
@@ -0,0 +1,20 @@
1
+ module RDF::Mongo
2
+ module VERSION
3
+ VERSION_FILE = File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "..", "VERSION")
4
+ MAJOR, MINOR, TINY, EXTRA = File.read(VERSION_FILE).chomp.split(".")
5
+
6
+ STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
7
+
8
+ ##
9
+ # @return [String]
10
+ def self.to_s() STRING end
11
+
12
+ ##
13
+ # @return [String]
14
+ def self.to_str() STRING end
15
+
16
+ ##
17
+ # @return [Array(Integer, Integer, Integer)]
18
+ def self.to_a() [MAJOR, MINOR, TINY] end
19
+ end
20
+ end
data/lib/rdf/mongo.rb CHANGED
@@ -2,26 +2,23 @@ require 'rdf'
2
2
  require 'enumerator'
3
3
  require 'mongo'
4
4
 
5
- module Mongo
6
- class Cursor
7
- def rdf_each(&block)
8
- if block_given?
9
- each {|statement| block.call(RDF::Statement.from_mongo(statement)) }
10
- else
11
- self
12
- end
13
- end
14
- end
15
- end
16
-
17
5
  module RDF
18
6
  class Statement
7
+ ##
8
+ # Creates a BSON representation of the statement.
9
+ # @return [Hash]
19
10
  def to_mongo
20
- self.to_hash.merge({:context => self.context}).inject({}) { |hash, (place_in_statement, entity)|
11
+ self.to_hash.inject({}) do |hash, (place_in_statement, entity)|
21
12
  hash.merge(RDF::Mongo::Conversion.to_mongo(entity, place_in_statement))
22
- }
13
+ end
23
14
  end
24
15
 
16
+ ##
17
+ # Create BSON for a statement representation. Note that if the statement has no context,
18
+ # a value of `false` will be used to indicate the default context
19
+ #
20
+ # @param [RDF::Statement] statement
21
+ # @return [Hash] Generated BSON representation of statement.
25
22
  def self.from_mongo(statement)
26
23
  RDF::Statement.new(
27
24
  :subject => RDF::Mongo::Conversion.from_mongo(statement['s'], statement['st'], statement['sl']),
@@ -31,21 +28,46 @@ module RDF
31
28
  end
32
29
  end
33
30
 
34
- module Mongo
31
+ module Mongo
32
+ autoload :VERSION, "rdf/mongo/version"
33
+
35
34
  class Conversion
36
- #TODO: Add support for other types of entities
37
-
35
+ ##
36
+ # Translate an RDF::Value type to BSON key/value pairs.
37
+ #
38
+ # @param [RDF::Value, Symbol, false, nil] value
39
+ # URI, BNode or Literal. May also be a Variable or Symbol to indicate
40
+ # a pattern for a named context, or `false` to indicate the default context.
41
+ # A value of `nil` indicates a pattern that matches any value.
42
+ # @param [:subject, :predicate, :object, :context] place_in_statement
43
+ # Position within statement.
44
+ # @return [Hash] BSON representation of the statement
38
45
  def self.to_mongo(value, place_in_statement)
39
46
  case value
40
47
  when RDF::URI
41
48
  v, k = value.to_s, :u
42
49
  when RDF::Literal
43
- v, k, ll = value.value, :l, value.language
50
+ if value.has_language?
51
+ v, k, ll = value.value, :ll, value.language.to_s
52
+ elsif value.has_datatype?
53
+ v, k, ll = value.value, :lt, value.datatype.to_s
54
+ else
55
+ v, k, ll = value.value, :l, nil
56
+ end
57
+ when RDF::Node
58
+ v, k = value.id.to_s, :n
59
+ when RDF::Query::Variable, Symbol
60
+ # Returns anything other than the default context
61
+ v, k = nil, {"$ne" => :default}
62
+ when false
63
+ # Used for the default context
64
+ v, k = false, :default
44
65
  when nil
45
66
  v, k = nil, nil
46
67
  else
47
68
  v, k = value.to_s, :u
48
69
  end
70
+ v = nil if v == ''
49
71
 
50
72
  case place_in_statement
51
73
  when :subject
@@ -57,49 +79,60 @@ module RDF
57
79
  when :context
58
80
  t, k1, lt = :ct, :c, :cl
59
81
  end
60
- h = {k1 => (v == '' ? nil : v), t => (k == '' ? nil : k), lt => ll}
82
+ h = {k1 => v, t => k, lt => ll}
61
83
  h.delete_if {|k,v| h[k].nil?}
62
84
  end
63
85
 
64
- def self.from_mongo(value, value_type = :u, lang = nil)
86
+ ##
87
+ # Translate an BSON positional reference to an RDF Value.
88
+ #
89
+ # @return [RDF::Value]
90
+ def self.from_mongo(value, value_type = :u, literal_extra = nil)
65
91
  case value_type
66
92
  when :u
67
- RDF::URI.new(value)
93
+ RDF::URI.intern(value)
94
+ when :ll
95
+ RDF::Literal.new(value, :language => literal_extra.to_sym)
96
+ when :lt
97
+ RDF::Literal.new(value, :datatype => RDF::URI.intern(literal_extra))
68
98
  when :l
69
- RDF::Literal.new(value, :language => lang)
99
+ RDF::Literal.new(value)
100
+ when :n
101
+ @nodes ||= {}
102
+ @nodes[value] ||= RDF::Node.new(value)
103
+ when :default
104
+ nil # The default context returns as nil, although it's queried as false.
70
105
  end
71
106
  end
72
107
  end
73
-
74
-
108
+
75
109
  class Repository < ::RDF::Repository
76
-
77
- def self.load(filenames, options = {:host => 'localhost', :port => 27017, :db => 'quadb'}, &block)
78
- self.new(options) do |repository|
79
- [filenames].flatten.each do |filename|
80
- repository.load(filename, options)
81
- end
110
+ # The Mongo database instance
111
+ # @!attribute [r] db
112
+ # @return [Mongo::DB]
113
+ attr_reader :db
82
114
 
83
- if block_given?
84
- case block.arity
85
- when 1 then block.call(repository)
86
- else repository.instance_eval(&block)
87
- end
88
- end
89
- end
90
- end
91
-
92
- def db
93
- @db
94
- end
115
+ # The collection used for storing quads
116
+ # @!attribute [r] coll
117
+ # @return [Mongo::Collection]
118
+ attr_reader :coll
95
119
 
96
- def coll
97
- @coll
98
- end
99
-
100
- def initialize(options = {:host => 'localhost', :port => 27017, :db => 'quadb'})
120
+ ##
121
+ # Initializes this repository instance.
122
+ #
123
+ # @param [Hash{Symbol => Object}] options
124
+ # @option options [URI, #to_s] :uri (nil)
125
+ # @option options [String, #to_s] :title (nil)
126
+ # @option options [String] :host
127
+ # @option options [Integer] :port
128
+ # @option options [String] :db
129
+ # @option options [String] :collection ('quads')
130
+ # @yield [repository]
131
+ # @yieldparam [Repository] repository
132
+ def initialize(options = {}, &block)
133
+ options = {:host => 'localhost', :port => 27017, :db => 'quadb', :collection => 'quads'}.merge(options)
101
134
  @db = ::Mongo::Connection.new(options[:host], options[:port]).db(options[:db])
102
- @coll = @db['quads']
135
+ @coll = @db[options[:collection]]
103
136
  @coll.create_index("s")
104
137
  @coll.create_index("p")
105
138
  @coll.create_index("o")
@@ -107,71 +140,104 @@ module RDF
107
140
  @coll.create_index([["s", ::Mongo::ASCENDING], ["p", ::Mongo::ASCENDING]])
108
141
  @coll.create_index([["s", ::Mongo::ASCENDING], ["o", ::Mongo::ASCENDING]])
109
142
  @coll.create_index([["p", ::Mongo::ASCENDING], ["o", ::Mongo::ASCENDING]])
110
- end
111
-
112
- # @see RDF::Enumerable#each.
113
- def each(&block)
114
- if block_given?
115
- statements = @coll.find()
116
- statements.each {|statement| block.call(RDF::Statement.from_mongo(statement)) }
117
- else
118
- statements = @coll.find()
119
- enumerator!.new(statements,:rdf_each)
120
- end
143
+ super(options, &block)
121
144
  end
122
145
 
123
146
  # @see RDF::Mutable#insert_statement
147
+ def supports?(feature)
148
+ case feature.to_sym
149
+ when :context then true
150
+ else false
151
+ end
152
+ end
153
+
124
154
  def insert_statement(statement)
125
- @coll.update(statement.to_mongo, statement.to_mongo, :upsert => true)
155
+ st_mongo = statement.to_mongo
156
+ st_mongo[:ct] ||= :default # Indicate statement is in the default context
157
+ #puts "insert statement: #{st_mongo.inspect}"
158
+ @coll.update(st_mongo, st_mongo, :upsert => true)
126
159
  end
127
160
 
128
161
  # @see RDF::Mutable#delete_statement
129
162
  def delete_statement(statement)
130
- @coll.remove(statement.to_mongo)
163
+ case statement.context
164
+ when nil
165
+ @coll.remove(statement.to_mongo.merge('ct'=>:default))
166
+ else
167
+ @coll.remove(statement.to_mongo)
168
+ end
131
169
  end
132
-
170
+
171
+ ##
172
+ # @private
173
+ # @see RDF::Durable#durable?
174
+ def durable?; true; end
175
+
176
+ ##
177
+ # @private
178
+ # @see RDF::Countable#empty?
179
+ def empty?; @coll.count == 0; end
180
+
181
+ ##
182
+ # @private
183
+ # @see RDF::Countable#count
133
184
  def count
134
185
  @coll.count
135
186
  end
136
-
137
- def query(pattern, &block)
138
- case pattern
139
- when RDF::Statement
140
- query(pattern.to_hash)
141
- when Array
142
- query(RDF::Statement.new(*pattern))
143
- when Hash
144
- statements = query_hash(pattern)
145
- the_statements = statements || []
146
- case block_given?
147
- when true
148
- the_statements.each {|s| block.call(RDF::Statement.from_mongo(s))}
149
- else
150
- def the_statements.each(&block)
151
- if block_given?
152
- super {|statement| block.call(RDF::Statement.from_mongo(statement)) }
153
- else
154
- enumerator!.new(the_statements,:rdf_each)
155
- end
156
- end
157
-
158
- def the_statements.size
159
- count
160
- end
161
- s = the_statements
187
+
188
+ def clear_statements
189
+ @coll.remove
190
+ end
191
+
192
+ ##
193
+ # @private
194
+ # @see RDF::Enumerable#has_statement?
195
+ def has_statement?(statement)
196
+ !!@coll.find_one(statement.to_mongo)
197
+ end
198
+ ##
199
+ # @private
200
+ # @see RDF::Enumerable#each_statement
201
+ def each_statement(&block)
202
+ @nodes = {} # reset cache. FIXME this should probably be in Node.intern
203
+ if block_given?
204
+ @coll.find() do |cursor|
205
+ cursor.each do |data|
206
+ block.call(RDF::Statement.from_mongo(data))
162
207
  end
163
- else
164
- super(pattern)
208
+ end
165
209
  end
210
+ enum_statement
166
211
  end
167
-
168
- def query_hash(hash)
169
- return @coll.find if hash.empty?
170
- h = RDF::Statement.new(hash).to_mongo
171
- @coll.find(h)
212
+ alias_method :each, :each_statement
213
+
214
+ ##
215
+ # @private
216
+ # @see RDF::Enumerable#has_context?
217
+ def has_context?(value)
218
+ !!@coll.find_one(RDF::Mongo::Conversion.to_mongo(value, :context))
172
219
  end
173
-
174
-
220
+
221
+ protected
222
+
223
+ ##
224
+ # @private
225
+ # @see RDF::Queryable#query_pattern
226
+ # @see RDF::Query::Pattern
227
+ def query_pattern(pattern, &block)
228
+ @nodes = {} # reset cache. FIXME this should probably be in Node.intern
229
+
230
+ # A pattern context of `false` is used to indicate the default context
231
+ pm = pattern.to_mongo
232
+ pm.merge!(:c => nil, :ct => :default) if pattern.context == false
233
+ #puts "query using #{pm.inspect}"
234
+ @coll.find(pm) do |cursor|
235
+ cursor.each do |data|
236
+ block.call(RDF::Statement.from_mongo(data))
237
+ end
238
+ end
239
+ end
240
+
175
241
  private
176
242
 
177
243
  def enumerator! # @private
metadata CHANGED
@@ -1,137 +1,149 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rdf-mongo
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 1
8
- - 9
9
- - 1
10
- version: 0.1.9.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.3
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Pius Uzamere
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2010-04-27 00:00:00 -04:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2013-01-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: rdf
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
22
+ type: :runtime
23
23
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
- - 1
31
- - 8
32
- version: 0.1.8
33
- type: :development
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: rdf-spec
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mongo
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 1.5.1
38
+ type: :runtime
37
39
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- segments:
43
- - 0
44
- - 1
45
- - 8
46
- version: 0.1.8
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.5.1
46
+ - !ruby/object:Gem::Dependency
47
+ name: rdf-spec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '1.0'
47
54
  type: :development
48
- version_requirements: *id002
49
- - !ruby/object:Gem::Dependency
50
- name: rspec
51
55
  prerelease: false
52
- requirement: &id003 !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- segments:
57
- - 1
58
- - 3
59
- - 0
60
- version: 1.3.0
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 2.12.0
61
70
  type: :development
62
- version_requirements: *id003
63
- - !ruby/object:Gem::Dependency
64
- name: yard
65
71
  prerelease: false
66
- requirement: &id004 !ruby/object:Gem::Requirement
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- segments:
71
- - 0
72
- - 5
73
- - 3
74
- version: 0.5.3
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 2.12.0
78
+ - !ruby/object:Gem::Dependency
79
+ name: yard
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 0.8.3
75
86
  type: :development
76
- version_requirements: *id004
77
- - !ruby/object:Gem::Dependency
78
- name: addressable
79
87
  prerelease: false
80
- requirement: &id005 !ruby/object:Gem::Requirement
81
- requirements:
82
- - - ">="
83
- - !ruby/object:Gem::Version
84
- segments:
85
- - 2
86
- - 1
87
- - 1
88
- version: 2.1.1
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 0.8.3
94
+ - !ruby/object:Gem::Dependency
95
+ name: addressable
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: 2.3.2
89
102
  type: :runtime
90
- version_requirements: *id005
91
- description: rdf-mongo is a storage adapter for integrating MongoDB and rdf.rb, a Ruby library for working with Resource Description Framework (RDF) data.
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: 2.3.2
110
+ description: rdf-mongo is a storage adapter for integrating MongoDB and rdf.rb, a
111
+ Ruby library for working with Resource Description Framework (RDF) data.
92
112
  email: pius@alum.mit.edu
93
113
  executables: []
94
-
95
114
  extensions: []
96
-
97
115
  extra_rdoc_files: []
98
-
99
- files:
116
+ files:
100
117
  - LICENSE
101
118
  - VERSION
102
119
  - README.md
120
+ - lib/rdf/mongo/version.rb
103
121
  - lib/rdf/mongo.rb
104
- has_rdoc: false
105
- homepage: http://github.com/pius/rdf-mongo
106
- licenses:
122
+ homepage: http://ruby-rdf.github.com/rdf-mongo
123
+ licenses:
107
124
  - MIT License
108
125
  post_install_message: Have fun! :)
109
126
  rdoc_options: []
110
-
111
- require_paths:
127
+ require_paths:
112
128
  - lib
113
- required_ruby_version: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- segments:
118
- - 1
119
- - 8
120
- - 6
121
- version: 1.8.6
122
- required_rubygems_version: !ruby/object:Gem::Requirement
123
- requirements:
124
- - - ">="
125
- - !ruby/object:Gem::Version
126
- segments:
127
- - 0
128
- version: "0"
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: 1.8.7
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
129
141
  requirements: []
130
-
131
142
  rubyforge_project:
132
- rubygems_version: 1.3.6
143
+ rubygems_version: 1.8.24
133
144
  signing_key:
134
145
  specification_version: 3
135
- summary: A storage adapter for integrating MongoDB and rdf.rb, a Ruby library for working with Resource Description Framework (RDF) data.
136
- test_files:
137
- - spec/mongo_repository.spec
146
+ summary: A storage adapter for integrating MongoDB and rdf.rb, a Ruby library for
147
+ working with Resource Description Framework (RDF) data.
148
+ test_files: []
149
+ has_rdoc: false
@@ -1,24 +0,0 @@
1
- $:.unshift File.dirname(__FILE__) + "/../lib/"
2
-
3
- require 'rdf'
4
- require 'rdf/spec/repository'
5
- require 'rdf/mongo'
6
- require 'enumerator'
7
-
8
- describe RDF::Mongo::Repository do
9
- context "Mongo RDF Repository" do
10
- before :each do
11
- @repository = RDF::Mongo::Repository.new() # TODO: Do you need constructor arguments?
12
- @repository.coll.drop
13
- end
14
-
15
- after :each do
16
- @repository.coll.drop
17
- end
18
-
19
- # @see lib/rdf/spec/repository.rb in RDF-spec
20
- it_should_behave_like RDF_Repository
21
- end
22
-
23
- end
24
-