rdf-4store 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/AUTHORS ADDED
@@ -0,0 +1 @@
1
+ Fumihiro Kato <fumi@fumi.me>
data/README ADDED
@@ -0,0 +1,43 @@
1
+ # 4store Storage Adapter for RDF.rb
2
+
3
+ This is an [RDF.rb][] storage adapter that allows you to use the [4store][] RDF Database.
4
+
5
+ See <http://blog.datagraph.org/2010/04/rdf-repository-howto> for an overview.
6
+
7
+ ## Status
8
+
9
+ This is still in alpha status, don't use in production environment.
10
+
11
+ ## Requirements
12
+
13
+ This plugin depends on the unsafe mode of 4s-httpd.
14
+
15
+ $ 4s-backend demo
16
+ $ 4s-httpd -U -s -1 demo
17
+
18
+ ## Resources
19
+
20
+ * <http://rdf.rubyforge.org> - RDF.rb's home page
21
+ * <http://rdf.rubyforge.org/RDF/Repository.html> - RDF.rb's Repository documentation
22
+ * <http://4store.org> - 4store's home page
23
+ * <http://github.com/fumi/rdf-4store>
24
+
25
+ ### Support
26
+
27
+ Please post questions or feedback to the [W3C-ruby-rdf mailing list][].
28
+
29
+ ### Author
30
+
31
+ * Fumihiro Kato <fumi@fumi.me> | <http://github.com/fumi> | <http://fumi.me>
32
+
33
+ ### 'License'
34
+
35
+ This is free and unemcumbered software released into the public domain. For
36
+ more information, see the accompanying UNLICENSE file.
37
+
38
+ If you're unfamiliar with public domain, that means it's perfectly fine to
39
+ start with this skeleton and code away, later relicensing as you see fit.
40
+
41
+ [RDF.rb]: http://rdf.rubyforge.org/
42
+ [4store]: http://4store.org/
43
+ [W3C-ruby-rdf mailing list]: http://lists.w3.org/Archives/Public/public-rdf-ruby/
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <http://unlicense.org/>
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,9 @@
1
+ require 'rdf'
2
+
3
+ module RDF
4
+ module FourStore
5
+ autoload :Repository, 'rdf/four_store/repository'
6
+ autoload :VERSION, 'rdf/four_store/version'
7
+ end
8
+ end
9
+
@@ -0,0 +1,296 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'open-uri'
4
+ require 'enumerator'
5
+ require 'rdf'
6
+ require 'sparql/client'
7
+ require 'nokogiri'
8
+
9
+ module RDF::FourStore
10
+
11
+ ##
12
+ # RDF::Repository backend for 4store
13
+ #
14
+ # @see http://4store.org
15
+ # @see
16
+ class Repository < ::SPARQL::Client::Repository
17
+
18
+ attr_reader :endpointURI, :dataURI, :updateURI, :statusURI, :sizeURI
19
+
20
+ DEFAULT_CONTEXT = "local:".freeze
21
+
22
+ ##
23
+ # Constructor of RDF::FourStore::Repository
24
+ #
25
+ # @param [String] uri
26
+ # @param [Hash] options
27
+ # @return [RDF::FourStore::Repository]
28
+ # @example
29
+ # RDF::FourStore::Respository.new('http://localhost:8080')
30
+ #
31
+ def initialize(uri_or_options = {})
32
+ case uri_or_options
33
+ when String
34
+ @options = {}
35
+ @uri = uri_or_options.to_s
36
+ when Hash
37
+ @options = uri_or_options.dup
38
+ @uri = @options.delete([:uri])
39
+ else
40
+ raise ArgumentError, "expected String or Hash, but got #{uri_or_options.inspect}"
41
+ end
42
+ @uri.sub!(/\/$/, '')
43
+ @endpointURI = @uri + "/sparql/"
44
+ @dataURI = @uri + "/data/"
45
+ @updateURI = @uri + "/update/"
46
+ @statusURI = @uri + "/status/"
47
+ @sizeURI = @statusURI + "size/"
48
+
49
+ super(@endpointURI, options)
50
+ end
51
+
52
+ ##
53
+ # Loads RDF statements from the given file or URL into `self`.
54
+ #
55
+ # @see RDF::Mutable#load
56
+ # @param [String, #to_s] filename
57
+ # @param [Hash{Symbol => Object}] options
58
+ # @return [void]
59
+ def load(filename, options = {})
60
+ return super(filename, options) if /^https?:\/\//.match(filename)
61
+
62
+ uri = nil
63
+
64
+ if options[:context]
65
+ uri = @dataURI + options[:context]
66
+ else
67
+ uri = @dataURI + 'file://' + File.expand_path(filename)
68
+ end
69
+
70
+ uri = URI.parse(uri)
71
+ content = open(filename).read
72
+ begin
73
+ req = Net::HTTP::Put.new(uri.path)
74
+ Net::HTTP.start(uri.host, uri.port) do |http|
75
+ http.request(req, content)
76
+ end
77
+ rescue Errno::ECONNREFUSED, Errno::ECONNRESET, TimeoutError
78
+ retry
79
+ end
80
+ end
81
+
82
+ alias_method :load!, :load
83
+
84
+ ##
85
+ # Returns the number of statements in this repository.
86
+ # @see RDF::Repository#count
87
+ # @return [Integer]
88
+ def count
89
+ c = 0
90
+ doc = Nokogiri::HTML(open(@sizeURI))
91
+ doc.search('tr').each do |tr|
92
+ td = tr.search('td')
93
+ c = td[0].content if td[0]
94
+ end
95
+ c.to_i # the last one is the total number
96
+ end
97
+ alias_method :size, :count
98
+ alias_method :length, :count
99
+
100
+ ##
101
+ # Enumerates each RDF statement in this repository.
102
+ #
103
+ # @yield [statement]
104
+ # @yieldparam [RDF::Statement] statement
105
+ # @return [Enumerator]
106
+ # @see RDF::Repository#each
107
+ # @see SPARQL::Client::Rpository#each
108
+ def each(&block)
109
+ unless block_given?
110
+ RDF::Enumerator.new(self, :each)
111
+ else
112
+ # TODO: check why @client.construct does not work here.
113
+ statements = @client.query("CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }")
114
+ statements.each_statement(&block) if statements
115
+ end
116
+ end
117
+
118
+ ##
119
+ # @private
120
+ # @see RDF::Enumerable#has_triple?
121
+ def has_triple?(triple)
122
+ has_statement?(RDF::Statement.from(triple))
123
+ end
124
+
125
+ ##
126
+ # @private
127
+ # @see RDF::Enumerable#has_quad?
128
+ def has_quad?(quad)
129
+ has_statement?(RDF::Statement.new(quad[0], quad[1], quad[2], :context => quad[3]))
130
+ end
131
+
132
+ ##
133
+ # @private
134
+ # @see RDF::Enumerable#has_statement?
135
+ def has_statement?(statement)
136
+ context = statement.context
137
+ dump = dump_statement(statement)
138
+ if context
139
+ @client.query("ASK { GRAPH <#{context}> { #{dump} } } ")
140
+ else
141
+ @client.query("ASK { #{dump} } ")
142
+ end
143
+ end
144
+
145
+ ##
146
+ # @see RDF::Mutable#insert_statement
147
+ # @private
148
+ def insert_statement(statement)
149
+ #TODO: save the given RDF::Statement. Don't save duplicates.
150
+ #
151
+ #unless has_statement?(statement)
152
+ dump = dump_statement(statement)
153
+ post_data(dump, statement.context)
154
+ #end
155
+ end
156
+
157
+ ##
158
+ # @see RDF::Mutable#delete_statement
159
+ # @private
160
+ def delete_statement(statement)
161
+ if has_statement?(statement)
162
+ context = statement.context || DEFAULT_CONTEXT
163
+ dump = dump_statement(statement)
164
+ q = "DELETE DATA { GRAPH <#{context}> { #{dump} } }"
165
+ post_update(q, context)
166
+ end
167
+ end
168
+
169
+ ##
170
+ # @private
171
+ # @see RDF::Mutable#clear
172
+ def clear_statements
173
+ q = "SELECT ?g WHERE { GRAPH ?g { ?s ?p ?o . } FILTER (?g != <#{DEFAULT_CONTEXT}>) }"
174
+ @client.query(q).each do |solution|
175
+ post_update("CLEAR GRAPH <#{solution[:g]}>")
176
+ end
177
+ post_update("CLEAR GRAPH <#{DEFAULT_CONTEXT}>")
178
+ end
179
+
180
+ ##
181
+ # Queries `self` for RDF statements matching the given `pattern`.
182
+ #
183
+ # @param [Query, Statement, Array(Value), Hash] pattern
184
+ # @yield [statement]
185
+ # @yieldparam [Statement]
186
+ # @return [Enumerable<Statement>]
187
+ def query(pattern, &block)
188
+ case pattern
189
+ when RDF::Statement
190
+ h = {
191
+ :subject => pattern.subject || :s,
192
+ :predicate => pattern.predicate || :p,
193
+ :object => pattern.object || :o,
194
+ :context => pattern.context || nil
195
+ }
196
+ super(RDF::Query::Pattern.new(h), &block)
197
+ when Array
198
+ h = {
199
+ :subject => pattern[0] || :s,
200
+ :predicate => pattern[1] || :p,
201
+ :object => pattern[2] || :o,
202
+ :context => pattern[3] || nil
203
+ }
204
+ super(RDF::Query::Pattern.new(h), &block)
205
+ when Hash
206
+ pattern[:subject] ||= :s
207
+ pattern[:predicate] ||= :p
208
+ pattern[:object] ||= :o
209
+ super(RDF::Query::Pattern.new(pattern), &block)
210
+ else
211
+ super(pattern, &block)
212
+ end
213
+ end
214
+
215
+ def query_pattern(pattern, &block)
216
+ context = pattern.context || DEFAULT_CONTEXT
217
+ str = pattern.to_s
218
+ q = "CONSTRUCT { #{str} } WHERE { GRAPH <#{context}> { #{str} } } "
219
+ result = @client.query(q)
220
+ if result
221
+ if block_given?
222
+ result.each_statement(&block)
223
+ else
224
+ result
225
+ end
226
+ end
227
+ end
228
+
229
+ def dump_statement(statement)
230
+ dump_statements([statement])
231
+ end
232
+
233
+ def dump_statements(statements)
234
+ graph = RDF::Graph.new
235
+ graph.insert_statements(statements)
236
+ RDF::Writer.for(:ntriples).dump(graph)
237
+ end
238
+
239
+ def post_data(content, context = nil)
240
+ context ||= DEFAULT_CONTEXT
241
+ uri = URI.parse(@dataURI)
242
+
243
+ req = Net::HTTP::Post.new(uri.path)
244
+ req.form_data = {
245
+ 'data' => content,
246
+ 'graph' => context,
247
+ 'mime-type' => 'application/x-turtle'
248
+ }
249
+
250
+ Net::HTTP.start(uri.host, uri.port) do |http|
251
+ http.request(req)
252
+ end
253
+ end
254
+
255
+ def post_update(content, context = nil)
256
+ context ||= DEFAULT_CONTEXT
257
+ uri = URI.parse(@updateURI)
258
+
259
+ req = Net::HTTP::Post.new(uri.path)
260
+ req.form_data = {
261
+ 'update' => content,
262
+ 'graph' => context,
263
+ 'content-type' => 'triples',
264
+ }
265
+
266
+ Net::HTTP.start(uri.host, uri.port) do |http|
267
+ http.request(req)
268
+ end
269
+ end
270
+
271
+ ##
272
+ # @private
273
+ # @see RDF::Writable#writable?
274
+ # @return [Boolean]
275
+ def writable?
276
+ true
277
+ end
278
+
279
+ ##
280
+ # @private
281
+ # @see RDF::Durable#durable?
282
+ # @return [Boolean]
283
+ def durable?
284
+ true
285
+ end
286
+
287
+ ##
288
+ # @private
289
+ # @see RDF::Countable#empty?
290
+ # @return [Boolean]
291
+ def empty?
292
+ count.zero?
293
+ end
294
+
295
+ end
296
+ end
@@ -0,0 +1,23 @@
1
+ module RDF::FourStore
2
+ module VERSION
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+ EXTRA = nil
7
+
8
+ STRING = [MAJOR, MINOR, TINY].join('.')
9
+ STRING << ".#{EXTRA}" if EXTRA
10
+
11
+ ##
12
+ # @return [String]
13
+ def self.to_s() STRING end
14
+
15
+ ##
16
+ # @return [String]
17
+ def self.to_str() STRING end
18
+
19
+ ##
20
+ # @return [Array(Integer, Integer, Integer)]
21
+ def self.to_a() [MAJOR, MINOR, TINY] end
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rdf-4store
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Fumihiro Kato
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-15 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rdf-spec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 0
32
+ - 2
33
+ - 0
34
+ version: 0.2.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rspec
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 27
46
+ segments:
47
+ - 1
48
+ - 3
49
+ - 0
50
+ version: 1.3.0
51
+ type: :development
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: rdf
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 19
62
+ segments:
63
+ - 0
64
+ - 2
65
+ - 2
66
+ version: 0.2.2
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: nokogiri
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 5
78
+ segments:
79
+ - 1
80
+ - 4
81
+ - 1
82
+ version: 1.4.1
83
+ type: :runtime
84
+ version_requirements: *id004
85
+ - !ruby/object:Gem::Dependency
86
+ name: sparql-client
87
+ prerelease: false
88
+ requirement: &id005 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 23
94
+ segments:
95
+ - 0
96
+ - 0
97
+ - 4
98
+ version: 0.0.4
99
+ type: :runtime
100
+ version_requirements: *id005
101
+ description: RDF.rb plugin providing 4store storage adapter.
102
+ email: fumi@fumi.me
103
+ executables: []
104
+
105
+ extensions: []
106
+
107
+ extra_rdoc_files: []
108
+
109
+ files:
110
+ - AUTHORS
111
+ - README
112
+ - UNLICENSE
113
+ - VERSION
114
+ - lib/rdf/4store.rb
115
+ - lib/rdf/four_store/repository.rb
116
+ - lib/rdf/four_store/version.rb
117
+ has_rdoc: true
118
+ homepage: http://github.com/fumi/rdf-4store
119
+ licenses:
120
+ - Public Domain
121
+ post_install_message:
122
+ rdoc_options: []
123
+
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ hash: 57
132
+ segments:
133
+ - 1
134
+ - 8
135
+ - 7
136
+ version: 1.8.7
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ hash: 3
143
+ segments:
144
+ - 0
145
+ version: "0"
146
+ requirements:
147
+ - 4store 1.0.3 or greater
148
+ rubyforge_project: rdf
149
+ rubygems_version: 1.3.7
150
+ signing_key:
151
+ specification_version: 3
152
+ summary: 4store adapter for RDF.rb.
153
+ test_files: []
154
+