rdf-agraph 0.3.1 → 0.4

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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NWJmZDg2YzkwZGE0OTkyZWZkMzYyNjI4NjFjYjkxMjZiZDY2OGQ1MA==
5
+ data.tar.gz: !binary |-
6
+ OGRmMjMwZmJiYTc3NTNiMTk5Zjc2MjlhYjhjN2ViNTYwNDdlNjAxNw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ YTUxYzNlY2EzOTE2NjY5NDNhZmM2NjgzNjE4YWIyMzk4ZGU0ZGE5N2MyZWNh
10
+ NDcwZmM4YmI0ZTlhNDIyZjNlMDBhZDQ4ZDY1Yzk3ZWJmOWIwZWIyNDUxN2Vl
11
+ NDUyYjY0ZjE5Y2M1ZjU3ZTA5NTdiMDJlMTUyMjUxMmY4Njc0YmQ=
12
+ data.tar.gz: !binary |-
13
+ ZGYwMjIxOWU4YWM3YzA2MTJhNWI0NmQ4NzMwM2NmNjI5YWFiYTM5NTZjMjgz
14
+ ZWMyMDUxM2U0NmY1Nzg0ZjMwNzAyZGI3N2FlMDY5YjNjYjA4ZmViNTYzYmM4
15
+ MWQ4OTU0MmFiYjQ2MjQ5MTU1MjJiNDQ5NTgyYTA4N2M0YzU1YmQ=
data/AUTHORS CHANGED
@@ -1 +1,2 @@
1
- * Eric Kidd <git@randomhacks.net>
1
+ * Eric Kidd <https://github.com/emk>
2
+ * Aymeric Brisse <https://github.com/abrisse>
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.4
@@ -1,4 +1,5 @@
1
1
  require 'rdf'
2
+ require 'rdf/ntriples'
2
3
  require 'agraph'
3
4
  require 'enumerator'
4
5
 
@@ -6,9 +7,11 @@ require 'enumerator'
6
7
  module RDF::AllegroGraph
7
8
  autoload :Query, 'rdf/allegro_graph/query'
8
9
  autoload :Server, 'rdf/allegro_graph/server'
10
+ autoload :Catalog, 'rdf/allegro_graph/catalog'
9
11
  autoload :AbstractRepository, 'rdf/allegro_graph/abstract_repository'
10
12
  autoload :Repository, 'rdf/allegro_graph/repository'
11
13
  autoload :SnaGenerator, 'rdf/allegro_graph/sna_generator'
12
14
  autoload :Functors, 'rdf/allegro_graph/functors'
15
+ autoload :Parser, 'rdf/allegro_graph/parser'
13
16
  autoload :Session, 'rdf/allegro_graph/session'
14
17
  end
@@ -23,6 +23,8 @@ module RDF::AllegroGraph
23
23
  #
24
24
  # We actually stack up pretty well against this list.
25
25
 
26
+ attr_reader :resource, :resource_writable
27
+ attr_reader :global_query_options
26
28
 
27
29
  #--------------------------------------------------------------------
28
30
  # @group RDF::Repository methods
@@ -32,12 +34,14 @@ module RDF::AllegroGraph
32
34
  # @param [AllegroGraph::Resource] resource
33
35
  # The underlying 'agraph'-based implementation to wrap.
34
36
  # @private
35
- def initialize(resource)
36
- @repo = resource
37
+ def initialize(resource, options={})
38
+ @resource = resource
39
+ @resource_writable = options[:writable_repository] || resource
37
40
  @blank_nodes = []
38
41
  @blank_nodes_to_generate = 8
39
42
  @blank_nodes_local_to_server = {}
40
43
  @blank_nodes_server_to_local = {}
44
+ self.global_query_options = options[:query]
41
45
  end
42
46
 
43
47
  # Returns true if `feature` is supported.
@@ -50,7 +54,23 @@ module RDF::AllegroGraph
50
54
  else super
51
55
  end
52
56
  end
53
-
57
+
58
+ # Set the global query options that will be used at each request.
59
+ # Current supported options are :offset, :limit and :infer.
60
+ #
61
+ # @param [Hash] options the options to set
62
+ #
63
+ # http://www.franz.com/agraph/support/documentation/current/http-protocol.html#get-post-repo
64
+ def global_query_options=(options)
65
+ @global_query_options = filter_query_options(options)
66
+ end
67
+
68
+ # Returns the amount of statements in the repository, as an integer
69
+ #
70
+ # @return [Integer] the number of statements
71
+ def size
72
+ @resource.size
73
+ end
54
74
 
55
75
  #--------------------------------------------------------------------
56
76
  # @group RDF::Transaction support
@@ -85,7 +105,7 @@ module RDF::AllegroGraph
85
105
  # @param [RDF::Statement] statement
86
106
  # @return [Boolean]
87
107
  def has_statement?(statement)
88
- found = @repo.statements.find(statement_to_dict(statement))
108
+ found = @resource.statements.find(statement_to_dict(statement))
89
109
  !found.empty?
90
110
  end
91
111
 
@@ -110,7 +130,7 @@ module RDF::AllegroGraph
110
130
 
111
131
  # How many statements are in this repository?
112
132
  #def count
113
- # @repo.request_http(:get, path(:statements),
133
+ # @resource.request_http(:get, path(:statements),
114
134
  # :headers => { 'Accept' => 'text/integer' },
115
135
  # :expected_status_code => 200).chomp.to_i
116
136
  #end
@@ -137,7 +157,7 @@ module RDF::AllegroGraph
137
157
  seen = {}
138
158
  dict = statement_to_dict(pattern)
139
159
  dict.delete(:context) if dict[:context] == 'null'
140
- @repo.statements.find(dict).each do |statement|
160
+ @resource.statements.find(dict).each do |statement|
141
161
  unless seen.has_key?(statement)
142
162
  seen[statement] = true
143
163
  s,p,o,c = statement.map {|v| unserialize(v) }
@@ -167,7 +187,7 @@ module RDF::AllegroGraph
167
187
  # @see RDF::Queryable#query
168
188
  # @see RDF::Query#execute
169
189
  def query_execute(query, &block)
170
- query_options =
190
+ query_options =
171
191
  if query.respond_to?(:query_options)
172
192
  query.query_options
173
193
  else
@@ -207,6 +227,7 @@ module RDF::AllegroGraph
207
227
  #
208
228
  # @see #build_query
209
229
  def sparql_query(query, query_options={}, &block)
230
+ query_options[:type] = query.split(' ').first.downcase.to_sym unless query.empty?
210
231
  raw_query(:sparql, query, query_options, &block)
211
232
  end
212
233
 
@@ -241,17 +262,23 @@ module RDF::AllegroGraph
241
262
  params = {
242
263
  :query => query,
243
264
  :queryLn => language.to_s
244
- }
245
- params[:infer] = query_options[:infer].to_s if query_options[:infer]
265
+ }.merge!(@global_query_options).merge!(filter_query_options(query_options))
246
266
 
247
267
  # Run the query and process the results.
248
- json = @repo.request_json(:get, path, :parameters => params,
268
+ json = @resource.request_json(:get, path, :parameters => params,
249
269
  :expected_status_code => 200)
250
- results = json_to_query_solutions(json)
270
+
271
+ # Parse the result (depends on the type of the query)
272
+ if language == :sparql and query_options[:type] == :construct
273
+ results = json_to_graph(json)
274
+ else
275
+ results = json_to_query_solutions(json)
276
+ results = enum_for(:raw_query, language, query) unless block_given?
277
+ end
251
278
  if block_given?
252
279
  results.each {|s| yield s }
253
280
  else
254
- enum_for(:raw_query, language, query)
281
+ results
255
282
  end
256
283
  end
257
284
  protected :raw_query
@@ -304,7 +331,7 @@ module RDF::AllegroGraph
304
331
  # Note that specifying deleteDuplicates on repository creation doesn't
305
332
  # seem to affect this.
306
333
  json = statements_to_json(statements)
307
- @repo.request_json(:post, path(:statements), :body => json,
334
+ @resource_writable.request_json(:post, path_writable(:statements), :body => json,
308
335
  :expected_status_code => 204)
309
336
  end
310
337
  protected :insert_statements
@@ -326,7 +353,7 @@ module RDF::AllegroGraph
326
353
  # @return [void]
327
354
  def delete_statements(statements)
328
355
  json = statements_to_json(statements)
329
- @repo.request_json(:post, path('statements/delete'),
356
+ @resource_writable.request_json(:post, path_writable('statements/delete'),
330
357
  :body => json, :expected_status_code => 204)
331
358
  end
332
359
  protected :delete_statements
@@ -336,9 +363,14 @@ module RDF::AllegroGraph
336
363
 
337
364
  # Clear all statements from the repository.
338
365
  #
366
+ # @param [Hash] options
367
+ # @option options [String] :subject Match a specific subject
368
+ # @option options [String] :predicate Match a specific predicate
369
+ # @option options [String] :object Match a specific object
370
+ # @option options [String] :context Match a specific graph name.
339
371
  # @return [void]
340
- def clear
341
- @repo.statements.delete
372
+ def clear(options = {})
373
+ @resource_writable.statements.delete(options)
342
374
  end
343
375
 
344
376
 
@@ -356,6 +388,7 @@ module RDF::AllegroGraph
356
388
  def serialize(value)
357
389
  case value
358
390
  when RDF::Query::Variable then value.to_s
391
+ when false then nil
359
392
  else RDF::NTriples::Writer.serialize(map_to_server(value))
360
393
  end
361
394
  end
@@ -380,9 +413,18 @@ module RDF::AllegroGraph
380
413
  # Build a repository-relative path.
381
414
  def path(relative_path=nil)
382
415
  if relative_path
383
- "#{@repo.path}/#{relative_path}"
416
+ "#{@resource.path}/#{relative_path}"
384
417
  else
385
- @repo.path
418
+ @resource.path
419
+ end
420
+ end
421
+
422
+ # Build a repository-relative path for the writable mirror
423
+ def path_writable(relative_path=nil)
424
+ if relative_path
425
+ "#{@resource_writable.path}/#{relative_path}"
426
+ else
427
+ @resource_writable.path
386
428
  end
387
429
  end
388
430
 
@@ -406,7 +448,7 @@ module RDF::AllegroGraph
406
448
  tuple = [s.subject, s.predicate, s.object]
407
449
  tuple << s.context if s.context
408
450
  tuple.map {|v| serialize(v) }
409
- end
451
+ end
410
452
  end
411
453
 
412
454
  # Translate a RDF::Statement into a dictionary the we can pass
@@ -420,7 +462,7 @@ module RDF::AllegroGraph
420
462
  # to operate a single statement. Otherwise, we will operate
421
463
  # on all matching s,p,o triples regardless of context.
422
464
  :context => serialize(statement.context) || 'null'
423
- }
465
+ }.merge!(@global_query_options)
424
466
  end
425
467
 
426
468
  # Convert a query to SPARQL.
@@ -428,7 +470,7 @@ module RDF::AllegroGraph
428
470
  variables = []
429
471
  patterns = []
430
472
  query.patterns.each do |p|
431
- p.variables.each {|_,v| variables << v unless variables.include?(v) }
473
+ variables.concat(p.variables.values)
432
474
  triple = [p.subject, p.predicate, p.object]
433
475
  str = triple.map {|v| serialize(v) }.join(" ")
434
476
  # TODO: Wrap in graph block for context!
@@ -437,7 +479,7 @@ module RDF::AllegroGraph
437
479
  end
438
480
  patterns << "#{str} ."
439
481
  end
440
- "SELECT #{variables.join(" ")}\nWHERE {\n #{patterns.join("\n ")} }"
482
+ "SELECT #{variables.uniq.join(" ")}\nWHERE {\n #{patterns.join("\n ")} }"
441
483
  end
442
484
 
443
485
  # Convert a JSON query solution to a list of RDF::Query::Solution
@@ -453,7 +495,15 @@ module RDF::AllegroGraph
453
495
  hash[name] = unserialize(match[i]) unless match[i].nil?
454
496
  end
455
497
  RDF::Query::Solution.new(hash)
456
- end
498
+ end
499
+ end
500
+
501
+ # Convert a JSON triples list to a RDF::Graph object.
502
+ def json_to_graph(json)
503
+ statements = json.map {|t| RDF::Statement.new(unserialize(t[0]), unserialize(t[1]), unserialize(t[2]))}
504
+ graph = RDF::Graph.new
505
+ graph.insert_statements(statements)
506
+ graph
457
507
  end
458
508
 
459
509
  # Return true if this a blank RDF node.
@@ -463,7 +513,7 @@ module RDF::AllegroGraph
463
513
 
464
514
  # Ask AllegroGraph to generate a series of blank node IDs.
465
515
  def generate_blank_nodes(amount)
466
- response = @repo.request_http(:post, path(:blankNodes),
516
+ response = @resource.request_http(:post, path(:blankNodes),
467
517
  :parameters => { :amount => amount },
468
518
  :expected_status_code => 200)
469
519
  response.chomp.split("\n").map {|i| i.gsub(/^_:/, '') }
@@ -511,5 +561,21 @@ module RDF::AllegroGraph
511
561
  value
512
562
  end
513
563
  end
564
+
565
+ # Set queries/statements options that will be used at each request
566
+ #
567
+ # @param [Hash] options options to use. Currently :limit and :infer are supported.
568
+ # @return [Hash] the options
569
+
570
+ # @private
571
+ def filter_query_options(options)
572
+ options ||= {}
573
+ filtered_options = {}
574
+ [ :limit, :infer, :offset ].each do |key|
575
+ filtered_options.merge! key => options[key] if options.has_key?(key)
576
+ end
577
+ filtered_options
578
+ end
579
+ protected :filter_query_options
514
580
  end
515
581
  end
@@ -0,0 +1,89 @@
1
+ require 'pathname'
2
+
3
+ module RDF::AllegroGraph
4
+ # An AllegroGraph catalog containing several repositories.
5
+ class Catalog
6
+ attr_reader :catalog
7
+
8
+ # Create a new Catalog object.
9
+ #
10
+ # @param [String] url The Sesame URL of the AllegroGraph server.
11
+ def initialize(url_or_hash, options={})
12
+ url_or_hash = Parser::parse_uri(url_or_hash) if url_or_hash.is_a?(String)
13
+ server = url_or_hash[:server].server
14
+ id = url_or_hash[:id]
15
+
16
+ @name = id
17
+ @catalog = AllegroGraph::Catalog.new(server, id)
18
+ @catalog.create_if_missing! if options[:create]
19
+ end
20
+
21
+ # Delete this catalog if it exists.
22
+ #
23
+ # @return [void]
24
+ def delete!
25
+ @catalog.delete!
26
+ end
27
+
28
+ # Return a hash table of all repositories in this catalog.
29
+ #
30
+ # @return [Hash<String,Repository>]
31
+ def repositories
32
+ result = {}
33
+ repositories = @catalog.server.request_json(:get, self.path(:repositories),
34
+ :expected_status_code => 200).each do |repo|
35
+ result[repo['id']] = Repository.new(:catalog => self, :id => repo['id'])
36
+ end
37
+ result
38
+ end
39
+
40
+ # Return true if the specified repository exists in the catalog.
41
+ #
42
+ # @param [String] id The name of the repository.
43
+ # @return [Boolean]
44
+ def has_repository?(id)
45
+ repositories.has_key?(id)
46
+ end
47
+
48
+ # Iterate over all repositories.
49
+ #
50
+ # @yield repository
51
+ # @yieldparam [Repository] repository
52
+ # @yieldreturn [void]
53
+ # @return [void]
54
+ def each_repository(&block)
55
+ repositories.values.each(&block)
56
+ end
57
+ alias_method :each, :each_repository
58
+
59
+ # Look up a specific repository by name, and optionally create it.
60
+ #
61
+ # @param [String] id The name of the repository.
62
+ # @param [Hash] options
63
+ # @option options [Boolean] :create
64
+ # If true, and the repository does not exist, create it.
65
+ # @return [Repository,nil]
66
+ # The repository, if it exists or was created, or nil otherwise.
67
+ def repository(id, options={})
68
+ result = repositories[id]
69
+ if result.nil? && options[:create]
70
+ result = Repository.new({:catalog => self, :id => id}, :create => true)
71
+ end
72
+ result
73
+ end
74
+ alias_method :[], :repository
75
+
76
+ protected
77
+
78
+ # Generate a path to a resource on the catalog.
79
+ def path(relativate_path=nil)
80
+ if relativate_path
81
+ "/catalogs/#{@name}/#{relativate_path}"
82
+ else
83
+ "/catalogs/#{@name}"
84
+ end
85
+ end
86
+
87
+ end
88
+
89
+ end
@@ -0,0 +1,35 @@
1
+ module RDF::AllegroGraph
2
+ # A module containg the URL parser of AllegroGraph objects such as :
3
+ # - servers
4
+ # - catalogs
5
+ # - repositories
6
+ module Parser
7
+
8
+ # Parse a full URI and extract the server/catalog and the repository ID.
9
+ #
10
+ # The parsing uses the default AllegroGraph URI schema :
11
+ # http://server:port/catalogs/catalog_name/repositories/repository_name
12
+ # This function can be overwritten to parse a custom URI schema system.
13
+ #
14
+ # @param [String] uri the uri the parse
15
+ # @return [Array]
16
+ def parse_uri(url)
17
+ hash = {}
18
+ url = URI.parse(url)
19
+ path = Pathname.new(url.path)
20
+
21
+ hash[:id] = path.basename.to_s
22
+ path = path.parent.parent
23
+ url.path = path.to_s
24
+
25
+ if path.parent.basename.to_s == 'catalogs'
26
+ hash[:catalog] = Catalog.new(url.to_s)
27
+ else
28
+ hash[:server] = Server.new(url.to_s)
29
+ end
30
+
31
+ hash
32
+ end
33
+ module_function :parse_uri
34
+ end
35
+ end
@@ -102,10 +102,10 @@ module RDF::AllegroGraph
102
102
  functors = []
103
103
  patterns.each do |p|
104
104
  # Extract any new variables we see in the query.
105
- p.variables.each {|_,v| variables << v unless variables.include?(v) }
105
+ variables.concat(p.variables.values)
106
106
  functors << convert_to_functor(p).to_prolog(repository)
107
107
  end
108
- "(select (#{variables.join(" ")})\n #{functors.join("\n ")})"
108
+ "(select (#{variables.uniq.join(" ")})\n #{functors.join("\n ")})"
109
109
  end
110
110
 
111
111
  protected
@@ -6,11 +6,13 @@ module RDF::AllegroGraph
6
6
  # Note that this class does not interoperate well with the Unix `fork`
7
7
  # command if you're using blank nodes. See README.md for details.
8
8
  class Repository < AbstractRepository
9
+
9
10
  # Create a new AllegroGraph repository adapter.
10
11
  #
11
12
  # @overload initialize(options)
12
13
  # @param [Hash{Symbol => Object}] options
13
14
  # @option options [Server] :server The server hosting the repository.
15
+ # @option options [Catalog] :catalog The catalog hosting the repository.
14
16
  # @option options [String] :id The name of the repository.
15
17
  # @option options [Boolean] :create Create the repository if necessary?
16
18
  #
@@ -18,37 +20,37 @@ module RDF::AllegroGraph
18
20
  # @param [String] url The URL of the repository.
19
21
  # @param [Hash{Symbol => Object}] options
20
22
  # @option options [Boolean] :create Create the repository if necessary?
21
- def initialize(url_or_options, options={})
22
- case url_or_options
23
- when String
24
- # TODO: Clean this up.
25
- url = URI.parse(url_or_options)
26
- path = Pathname.new(url.path)
27
- url.path = path.parent.parent.to_s
28
- server = Server.new(url.to_s).server
29
- id = path.basename
23
+ def initialize(url_or_hash, options={})
24
+ url_or_hash = Parser::parse_uri(url_or_hash) if url_or_hash.is_a?(String)
25
+
26
+ if url_or_hash.has_key?(:catalog)
27
+ server_or_catalog = url_or_hash[:catalog].catalog
28
+ elsif url_or_hash.has_key?(:server)
29
+ server_or_catalog = url_or_hash[:server].server
30
30
  else
31
- server = url_or_options[:server].server
32
- id = url_or_options[:id]
33
- options = url_or_options
31
+ raise ArgumentError.new('Server or Catalog required')
34
32
  end
35
- super(::AllegroGraph::Repository.new(server, id))
36
- @repo.create_if_missing! if options[:create]
33
+
34
+ id = url_or_hash[:id]
35
+ opt_create = options.delete(:create)
36
+ super(::AllegroGraph::Repository.new(server_or_catalog, id), options)
37
+ @resource.create_if_missing! if opt_create
37
38
  end
38
39
 
39
40
  # Delete this repository if it exists.
40
41
  #
41
42
  # @return [void]
42
43
  def delete!
43
- @repo.delete!
44
+ @resource.delete!
44
45
  end
45
46
 
46
- # Create a new, persistent AllegroGraph session. If called without a
47
- # block, simply returns the new session (and expects the caller to
48
- # close it). If called with a block, automatically commits or rolls
49
- # back the transaction, and closes the session.
47
+ # Create a new, persistent AllegroGraph session on a given repository.
48
+ # If called without a block, simply returns the new session (and expects
49
+ # the caller to close it). If called with a block, automatically commits
50
+ # or rolls back the transaction, and closes the session.
50
51
  #
51
52
  # @overload session
53
+ # @param [Repository] the repository on which to open the session
52
54
  # @return [Session] The newly created session. It's a good idea to
53
55
  # close this manually; doing so frees up server resources.
54
56
  # @see Session#commit
@@ -56,13 +58,14 @@ module RDF::AllegroGraph
56
58
  # @see Session#close
57
59
  #
58
60
  # @overload session
61
+ # @param [Repository] the repository on which to open the session
59
62
  # @yield session
60
63
  # @yieldparam [Session] session
61
64
  # @yieldreturn [Object]
62
65
  # @return [Object] The result returned from the block.
63
- def session
66
+ def self.session(repository, options={})
64
67
  if block_given?
65
- session = Session.new(@repo)
68
+ session = Session.new(repository, options)
66
69
  begin
67
70
  result = yield session
68
71
  session.commit
@@ -74,8 +77,29 @@ module RDF::AllegroGraph
74
77
  session.close
75
78
  end
76
79
  else
77
- Session.new(@repo)
80
+ Session.new(repository, options)
78
81
  end
79
82
  end
83
+
84
+ # Create a new, persistent AllegroGraph session. If called without a
85
+ # block, simply returns the new session (and expects the caller to
86
+ # close it). If called with a block, automatically commits or rolls
87
+ # back the transaction, and closes the session.
88
+ #
89
+ # @overload session
90
+ # @return [Session] The newly created session. It's a good idea to
91
+ # close this manually; doing so frees up server resources.
92
+ # @see Session#commit
93
+ # @see Session#rollback
94
+ # @see Session#close
95
+ #
96
+ # @overload session
97
+ # @yield session
98
+ # @yieldparam [Session] session
99
+ # @yieldreturn [Object]
100
+ # @return [Object] The result returned from the block.
101
+ def session(options={}, &block)
102
+ self.class.session self, &block
103
+ end
80
104
  end
81
105
  end
@@ -7,7 +7,7 @@ module RDF::AllegroGraph
7
7
  #
8
8
  # @see RDF::Sesame::Server
9
9
  class Server
10
- attr_reader :server # @private
10
+ attr_reader :server
11
11
 
12
12
  # Create a new Server object.
13
13
  #
@@ -15,11 +15,11 @@ module RDF::AllegroGraph
15
15
  def initialize(url="http://localhost:10035")
16
16
  parsed = URI.parse(url)
17
17
  options = {
18
- :host => parsed.host, :post => parsed.port,
18
+ :host => parsed.host, :port => parsed.port,
19
19
  :username => parsed.user, :password => parsed.password
20
20
  }
21
21
  @server = AllegroGraph::Server.new(options)
22
-
22
+
23
23
  unless parsed.path.nil? || parsed.path.empty? || parsed.path == "/"
24
24
  err = "AllegroGraph URLs with paths not supported: #{url}"
25
25
  raise ArgumentError.new(err)
@@ -77,12 +77,128 @@ module RDF::AllegroGraph
77
77
  def repository(id, options={})
78
78
  result = repositories[id]
79
79
  if result.nil? && options[:create]
80
- result = Repository.new(:server => self, :id => id, :create => true)
80
+ result = Repository.new({:server => self, :id => id}, :create => true)
81
81
  end
82
82
  result
83
83
  end
84
84
  alias_method :[], :repository
85
85
 
86
+ # Return a hash table of all catalogs on this server.
87
+ #
88
+ # @return [Hash<String,Catalog>]
89
+ def catalogs
90
+ result = {}
91
+ @server.request_json(:get, path(:catalogs),
92
+ :expected_status_code => 200).each do |catalog|
93
+ result[catalog['id']] = Catalog.new(:server => self, :id => catalog['id'])
94
+ end
95
+ result
96
+ end
97
+
98
+ # Return true if the specified catalog exists on the server.
99
+ #
100
+ # @param [String] id The name of the catalog.
101
+ # @return [Boolean]
102
+ def has_catalog?(id)
103
+ catalogs.has_key?(id)
104
+ end
105
+
106
+ # Iterate over all catalogs.
107
+ #
108
+ # @yield catalog
109
+ # @yieldparam [Catalog] catalog
110
+ # @yieldreturn [void]
111
+ # @return [void]
112
+ def each_catalog(&block)
113
+ catalogs.values.each(&block)
114
+ end
115
+
116
+ # Look up a specific catalog by name, and optionally create it.
117
+ #
118
+ # @param [String] id The name of the catalog.
119
+ # @param [Hash] options
120
+ # @option options [Boolean] :create
121
+ # If true, and the catalog does not exist, create it.
122
+ # @return [Repository,nil]
123
+ # The catalog, if it exists or was created, or nil otherwise.
124
+ def catalog(id, options={})
125
+ result = catalogs[id]
126
+ if result.nil? && options[:create]
127
+ result = Catalog.new({:server => self, :id => id}, :create => true)
128
+ end
129
+ result
130
+ end
131
+
132
+ # An initialization-file can be specified for a server, which is a collection of Common Lisp code
133
+ # that is executed in every shared back-end as it is created. This retrieves that file.
134
+ # If no initfile has been defined, nil is returned.
135
+ #
136
+ # @return [String] the content of the file
137
+ def initfile
138
+ if (content = @server.request_http(:get, '/initfile')) == "No initfile defined."
139
+ content = nil
140
+ end
141
+ content
142
+ end
143
+
144
+ # A set of scripts, which are Common Lisp programs, can be stored in a server.
145
+ # When a user creates a session, they can choose to load one or more of these scripts into the session.
146
+ # This service returns a list of names, representing the scripts that are currently present.
147
+ #
148
+ # @param [String] path a filter on the subfolder to look scripts into
149
+ # @return [Array] the scripts list
150
+ def scripts(path=nil)
151
+ full_path = "/scripts"
152
+ full_path = "#{full_path}/#{path}" if path
153
+
154
+ @server.request_json(:get, full_path,
155
+ :expected_status_code => 200)
156
+ end
157
+
158
+ # Get a script content
159
+ #
160
+ # @param [String] path the name of the script
161
+ # @return [String] the script
162
+ def script(path)
163
+ full_path = "/scripts/#{path}"
164
+
165
+ begin
166
+ @server.request_http(:get, full_path,
167
+ :expected_status_code => 200)
168
+ rescue Transport::UnexpectedStatusCodeError => error
169
+ if /No script '[^']+' found./ =~ error.message
170
+ nil
171
+ else
172
+ raise error
173
+ end
174
+ end
175
+ end
176
+
177
+ alias_method :get_script, :script
178
+
179
+ # Replace the named script with a new one (or creates a new script).
180
+ # Scripts whose name ends in .fasl are assumed to be compiled Lisp code (you are responsible for ensuring that it is compatible with the server),
181
+ # anything else is assumed to be raw Common Lisp code, which the server will compile.
182
+ #
183
+ # @param [String] path the name of the script
184
+ # @param [String] content the script content
185
+ # @return [void]
186
+ def save_script(path, content)
187
+ full_path = "/scripts/#{path}"
188
+
189
+ @server.request_http(:put, full_path, :body => content, :expected_status_code => 204)
190
+ end
191
+
192
+ # Delete the script with the given path
193
+ #
194
+ # @param [String] path the name of the script
195
+ # @return [void]
196
+ def remove_script(path)
197
+ full_path = "/scripts/#{path}"
198
+
199
+ @server.request_http(:delete, full_path, :expected_status_code => 204)
200
+ end
201
+
86
202
  protected
87
203
 
88
204
  # Generate a path to a resource on the server.
@@ -9,13 +9,35 @@ module RDF::AllegroGraph
9
9
  #
10
10
  # @see Repository#session
11
11
  class Session < AbstractRepository
12
- # Create a new session. This parameter takes an
13
- # ::AllegroGraph::Repository object as an argument, so we've not going
14
- # to document it publically.
12
+ # Create a new session. This function takes a ::AllegroGraph::Repository or
13
+ # a ::AllegroGraph::Server object as first argument, and options as second
14
+ # parameter, which is optional.
15
15
  #
16
16
  # @private
17
- def initialize(agraph_repo)
18
- super(::AllegroGraph::Session.create(agraph_repo))
17
+ def initialize(repository_or_server, options={})
18
+ # Use of the AllegroGraph wrapped entity
19
+ agraph_repository_or_server = case repository_or_server
20
+ when Repository
21
+ repository_or_server.resource
22
+ when Server
23
+ repository_or_server.server
24
+ else
25
+ Server.new(repository_or_server.to_s).server
26
+ end
27
+ opt_session = options.delete(:session) || {}
28
+ opt_writable_mirror = options.delete(:writable_mirror)
29
+
30
+ if opt_writable_mirror
31
+ options[:writable_repository] =
32
+ case opt_writable_mirror
33
+ when Repository
34
+ opt_writable_mirror.resource
35
+ else
36
+ Repository.new(opt_writable_mirror).resource
37
+ end
38
+ end
39
+
40
+ super(::AllegroGraph::Session.create(agraph_repository_or_server, opt_session), options)
19
41
  @last_unique_id = 0
20
42
  end
21
43
 
@@ -26,7 +48,7 @@ module RDF::AllegroGraph
26
48
  # @see #commit
27
49
  # @see #rollback
28
50
  def close
29
- @repo.request_http(:post, path('session/close'),
51
+ @resource.request_http(:post, path('session/close'),
30
52
  :expected_status_code => 204)
31
53
  end
32
54
 
@@ -35,7 +57,7 @@ module RDF::AllegroGraph
35
57
  # @return [void]
36
58
  # @see #rollback
37
59
  def commit
38
- @repo.commit
60
+ @resource.commit
39
61
  end
40
62
 
41
63
  # Roll back the changes made since the last commit.
@@ -43,7 +65,28 @@ module RDF::AllegroGraph
43
65
  # @return [void]
44
66
  # @see #commit
45
67
  def rollback
46
- @repo.rollback
68
+ @resource.rollback
69
+ end
70
+
71
+ # Let the session know you still want to keep it alive. (Any other request to the session will have the same effect.)
72
+ #
73
+ # @return [Boolean] returns true if the operation was sucessful
74
+ def ping
75
+ @resource.request_http(:get, path('session/ping'),
76
+ :expected_status_code => 200) == 'pong'
77
+ end
78
+
79
+ # Returns true if the session is still alive.
80
+ # Basically it pings the session. If the TCP connection is refused,
81
+ # it means that the session has been closed.
82
+ #
83
+ # @return [Boolean] returns the status of the session
84
+ def still_alive?
85
+ begin
86
+ ping
87
+ rescue Errno::ECONNREFUSED
88
+ false
89
+ end
47
90
  end
48
91
 
49
92
  # Define an SNA generator.
@@ -63,7 +106,7 @@ module RDF::AllegroGraph
63
106
  def generator(options)
64
107
  id = unique_id
65
108
  generator = SnaGenerator.new(self, options)
66
- @repo.request_json(:put, path("snaGenerators/#{id}"),
109
+ @resource.request_json(:put, path("snaGenerators/#{id}"),
67
110
  :parameters => generator.to_params,
68
111
  :expected_status_code => 204)
69
112
  Query::PrologLiteral.new(id.to_sym)
metadata CHANGED
@@ -1,227 +1,174 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rdf-agraph
3
- version: !ruby/object:Gem::Version
4
- hash: 17
5
- prerelease:
6
- segments:
7
- - 0
8
- - 3
9
- - 1
10
- version: 0.3.1
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.4'
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Eric Kidd
14
8
  autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
-
18
- date: 2011-05-19 00:00:00 -04:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
11
+ date: 2013-03-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
22
14
  name: rdf
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ~>
28
- - !ruby/object:Gem::Version
29
- hash: 17
30
- segments:
31
- - 0
32
- - 3
33
- - 1
34
- version: 0.3.1
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
35
20
  type: :runtime
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: agraph
39
21
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ~>
44
- - !ruby/object:Gem::Version
45
- hash: 19
46
- segments:
47
- - 0
48
- - 1
49
- - 4
50
- version: 0.1.4
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: agraph
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '0.2'
51
34
  type: :runtime
52
- version_requirements: *id002
53
- - !ruby/object:Gem::Dependency
54
- name: json
55
35
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 9
62
- segments:
63
- - 0
64
- - 5
65
- - 1
66
- version: 0.5.1
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '0.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
67
48
  type: :runtime
68
- version_requirements: *id003
69
- - !ruby/object:Gem::Dependency
70
- name: rdf-spec
71
49
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ~>
76
- - !ruby/object:Gem::Version
77
- hash: 17
78
- segments:
79
- - 0
80
- - 3
81
- - 1
82
- version: 0.3.1
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rdf-spec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
83
62
  type: :development
84
- version_requirements: *id004
85
- - !ruby/object:Gem::Dependency
86
- name: yard
87
63
  prerelease: false
88
- requirement: &id005 !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ">="
92
- - !ruby/object:Gem::Version
93
- hash: 7
94
- segments:
95
- - 0
96
- - 6
97
- - 0
98
- version: 0.6.0
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '0.8'
99
76
  type: :development
100
- version_requirements: *id005
101
- - !ruby/object:Gem::Dependency
102
- name: BlueCloth
103
77
  prerelease: false
104
- requirement: &id006 !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- hash: 21
110
- segments:
111
- - 1
112
- - 0
113
- - 1
114
- version: 1.0.1
115
- type: :development
116
- version_requirements: *id006
117
- - !ruby/object:Gem::Dependency
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '0.8'
83
+ - !ruby/object:Gem::Dependency
118
84
  name: rspec
119
- prerelease: false
120
- requirement: &id007 !ruby/object:Gem::Requirement
121
- none: false
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- hash: 27
126
- segments:
127
- - 2
128
- - 5
129
- - 0
130
- version: 2.5.0
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 2.12.0
131
90
  type: :development
132
- version_requirements: *id007
133
- - !ruby/object:Gem::Dependency
134
- name: rcov
135
91
  prerelease: false
136
- requirement: &id008 !ruby/object:Gem::Requirement
137
- none: false
138
- requirements:
139
- - - ">="
140
- - !ruby/object:Gem::Version
141
- hash: 41
142
- segments:
143
- - 0
144
- - 9
145
- - 9
146
- version: 0.9.9
147
- type: :development
148
- version_requirements: *id008
149
- - !ruby/object:Gem::Dependency
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 2.12.0
97
+ - !ruby/object:Gem::Dependency
150
98
  name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 10.0.0
104
+ type: :development
151
105
  prerelease: false
152
- requirement: &id009 !ruby/object:Gem::Requirement
153
- none: false
154
- requirements:
155
- - - ">="
156
- - !ruby/object:Gem::Version
157
- hash: 49
158
- segments:
159
- - 0
160
- - 8
161
- - 7
162
- version: 0.8.7
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 10.0.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: dotenv
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '0.5'
163
118
  type: :development
164
- version_requirements: *id009
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: '0.5'
165
125
  description: An AllegroGraph adapter for use with RDF.rb.
166
126
  email: rdf-agraph@kiddsoftware.com
167
127
  executables: []
168
-
169
128
  extensions: []
170
-
171
129
  extra_rdoc_files: []
172
-
173
- files:
130
+ files:
174
131
  - AUTHORS
175
132
  - README.md
176
133
  - UNLICENSE
177
134
  - VERSION
178
- - lib/rdf-agraph.rb
179
135
  - lib/rdf/allegro_graph.rb
180
- - lib/rdf/allegro_graph/server.rb
181
- - lib/rdf/allegro_graph/functors.rb
136
+ - lib/rdf/allegro_graph/parser.rb
182
137
  - lib/rdf/allegro_graph/functors/sna_functors.rb
183
- - lib/rdf/allegro_graph/repository.rb
138
+ - lib/rdf/allegro_graph/server.rb
184
139
  - lib/rdf/allegro_graph/query.rb
140
+ - lib/rdf/allegro_graph/sna_generator.rb
141
+ - lib/rdf/allegro_graph/catalog.rb
185
142
  - lib/rdf/allegro_graph/abstract_repository.rb
186
143
  - lib/rdf/allegro_graph/query/functor_expression.rb
187
144
  - lib/rdf/allegro_graph/query/prolog_literal.rb
188
- - lib/rdf/allegro_graph/sna_generator.rb
145
+ - lib/rdf/allegro_graph/repository.rb
189
146
  - lib/rdf/allegro_graph/session.rb
190
- has_rdoc: false
147
+ - lib/rdf/allegro_graph/functors.rb
148
+ - lib/rdf-agraph.rb
191
149
  homepage: http://rdf-agraph.rubyforge.org/
192
- licenses:
150
+ licenses:
193
151
  - Public Domain
152
+ metadata: {}
194
153
  post_install_message:
195
154
  rdoc_options: []
196
-
197
- require_paths:
155
+ require_paths:
198
156
  - lib
199
- required_ruby_version: !ruby/object:Gem::Requirement
200
- none: false
201
- requirements:
202
- - - ">="
203
- - !ruby/object:Gem::Version
204
- hash: 57
205
- segments:
206
- - 1
207
- - 8
208
- - 7
157
+ required_ruby_version: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ! '>='
160
+ - !ruby/object:Gem::Version
209
161
  version: 1.8.7
210
- required_rubygems_version: !ruby/object:Gem::Requirement
211
- none: false
212
- requirements:
213
- - - ">="
214
- - !ruby/object:Gem::Version
215
- hash: 3
216
- segments:
217
- - 0
218
- version: "0"
162
+ required_rubygems_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ! '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
219
167
  requirements: []
220
-
221
168
  rubyforge_project: rdf-agraph
222
- rubygems_version: 1.4.1
169
+ rubygems_version: 2.0.1
223
170
  signing_key:
224
- specification_version: 3
171
+ specification_version: 4
225
172
  summary: AllegroGraph adapter for RDF.rb
226
173
  test_files: []
227
-
174
+ has_rdoc: false