redlander 0.2.2 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,18 +1,19 @@
1
- require 'redlander/statement'
2
-
3
1
  module Redlander
4
-
5
2
  class ParserProxy
6
-
7
- include StatementIterator
3
+ include StreamEnumerator
8
4
 
9
5
  def initialize(parser, content, options = {})
10
- @model = nil # the yielded statements will not be bound to a model
11
- @rdf_stream = Redland.librdf_parser_parse_string_as_stream(parser.rdf_parser, content, Redlander.to_rdf_uri(options[:base_uri]))
12
- raise RedlandError.new("Failed to create a new stream") unless @rdf_stream
13
- ObjectSpace.define_finalizer(@rdf_stream, proc { Redland.librdf_free_stream(@rdf_stream) })
6
+ # TODO: consider a streaming content, as it may be large to fit in memory
7
+ @parser = parser
8
+ @content = content
9
+ @options = options
14
10
  end
15
11
 
16
- end
17
12
 
13
+ private
14
+
15
+ def reset_stream
16
+ @stream = Stream.new(@parser, @content, @options)
17
+ end
18
+ end
18
19
  end
@@ -1,7 +1,5 @@
1
1
  module Redlander
2
-
3
2
  class Serializer
4
-
5
3
  # Create a new serializer.
6
4
  # Name can be either of [:rdfxml, :ntriples, :turtle, :json, :dot],
7
5
  # or nil, which defaults to :rdfxml.
@@ -10,8 +8,8 @@ module Redlander
10
8
  # because the rest seem to be very buggy.
11
9
  def initialize(name = :rdfxml)
12
10
  @rdf_serializer = Redland.librdf_new_serializer(Redlander.rdf_world, name.to_s, nil, nil)
13
- raise RedlandError.new("Failed to create a new serializer") unless @rdf_serializer
14
- ObjectSpace.define_finalizer(@rdf_serializer, proc { Redland.librdf_free_serializer(@rdf_serializer) })
11
+ raise RedlandError.new("Failed to create a new serializer") if @rdf_serializer.null?
12
+ ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_serializer(@rdf_serializer) })
15
13
  end
16
14
 
17
15
  # Serialize a model into a string.
@@ -19,7 +17,12 @@ module Redlander
19
17
  # Options are:
20
18
  # :base_uri base URI (String or URI)
21
19
  def to_string(model, options = {})
22
- Redland.librdf_serializer_serialize_model_to_string(@rdf_serializer, Redlander.to_rdf_uri(options[:base_uri]), model.rdf_model)
20
+ base_uri = if options.has_key?(:base_uri)
21
+ Uri.new(options[:base_uri]).rdf_uri
22
+ else
23
+ nil
24
+ end
25
+ Redland.librdf_serializer_serialize_model_to_string(@rdf_serializer, base_uri, model.rdf_model)
23
26
  end
24
27
 
25
28
  # Serializes a model and stores it in a file
@@ -31,14 +34,18 @@ module Redlander
31
34
  #
32
35
  # Returns true on success, or false.
33
36
  def to_file(model, filename, options = {})
34
- Redland.librdf_serializer_serialize_model_to_file(@rdf_serializer, filename, Redlander.to_rdf_uri(options[:base_uri]), model.rdf_model).zero?
37
+ base_uri = if options.has_key?(:base_uri)
38
+ Uri.new(options[:base_uri]).rdf_uri
39
+ else
40
+ nil
41
+ end
42
+ Redland.librdf_serializer_serialize_model_to_file(@rdf_serializer, filename, base_uri, model.rdf_model).zero?
35
43
  end
36
-
37
44
  end
38
45
 
39
46
 
47
+ # Applied to Model
40
48
  module SerializingInstanceMethods
41
-
42
49
  def to_rdfxml(options = {})
43
50
  serializer = Serializer.new(:rdfxml)
44
51
  serializer.to_string(self, options)
@@ -74,7 +81,5 @@ module Redlander
74
81
  serializer = Serializer.new(serializer_options.delete(:format) || :rdfxml)
75
82
  serializer.to_file(self, filename, serializer_options)
76
83
  end
77
-
78
84
  end
79
-
80
85
  end
@@ -1,105 +1,73 @@
1
1
  module Redlander
2
-
3
2
  class Statement
4
-
5
3
  include ErrorContainer
6
4
 
7
5
  attr_reader :rdf_statement
8
6
 
9
7
  # Create an RDF statement.
10
- # Options are:
11
- # :subject
12
- # :predicate
13
- # :object
14
- def initialize(options = {})
15
- @rdf_statement = if options.is_a?(SWIG::TYPE_p_librdf_statement_s)
16
- # A special case, where you can pass an instance of SWIG::TYPE_p_librdf_statement_s
17
- # in order to create a Statement from an internal RDF statement representation.
18
- options
19
- else
20
- s = options[:subject] && Node.new(options[:subject]).rdf_node
21
- p = options[:predicate] && Node.new(options[:predicate]).rdf_node
22
- o = options[:object] && Node.new(options[:object]).rdf_node
8
+ # Source can be:
9
+ # Hash, where
10
+ # :subject
11
+ # :predicate
12
+ # :object
13
+ # Stream, so that a statement is extracted from its current position
14
+ def initialize(source = {})
15
+ @rdf_statement = case source
16
+ when Stream
17
+ # Pull a (current) statement from the stream
18
+ Redland.librdf_stream_get_object(source.rdf_stream)
19
+ when Hash
20
+ # Create a new statement from nodes
21
+ s = source[:subject] && Node.new(source[:subject]).rdf_node
22
+ p = source[:predicate] && Node.new(source[:predicate]).rdf_node
23
+ o = source[:object] && Node.new(source[:object]).rdf_node
23
24
  Redland.librdf_new_statement_from_nodes(Redlander.rdf_world, s, p, o)
25
+ else
26
+ # TODO
27
+ raise NotImplementedError.new
24
28
  end
25
-
26
- raise RedlandError.new("Failed to create a new statement") unless @rdf_statement
27
- ObjectSpace.define_finalizer(@rdf_statement, proc { Redland.librdf_free_statement(@rdf_statement) })
29
+ raise RedlandError.new("Failed to create a new statement") if @rdf_statement.null?
30
+ ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_statement(@rdf_statement) })
28
31
  end
29
32
 
30
33
  def subject
31
- rdf_node = Redland.librdf_statement_get_subject(@rdf_statement)
32
- rdf_node && Node.new(rdf_node)
34
+ node = Node.new(self, :subject)
35
+ node.rdf_node.null? ? nil : node
33
36
  end
34
37
 
35
38
  def predicate
36
- rdf_node = Redland.librdf_statement_get_predicate(@rdf_statement)
37
- rdf_node && Node.new(rdf_node)
39
+ node = Node.new(self, :predicate)
40
+ node.rdf_node.null? ? nil : node
38
41
  end
39
42
 
40
43
  def object
41
- rdf_node = Redland.librdf_statement_get_object(@rdf_statement)
42
- rdf_node && Node.new(rdf_node)
44
+ node = Node.new(self, :object)
45
+ node.rdf_node.null? ? nil : node
43
46
  end
44
47
 
45
48
  # set the subject of the statement
46
49
  def subject=(node)
47
- Redland.librdf_statement_set_subject(@rdf_statement, rdf_node_from(node))
50
+ binding_to_statement(node) {
51
+ Redland.librdf_statement_set_subject(@rdf_statement, node.rdf_node)
52
+ }
48
53
  end
49
54
 
50
55
  # set the predicate of the statement
51
56
  def predicate=(node)
52
- Redland.librdf_statement_set_predicate(@rdf_statement, rdf_node_from(node))
57
+ binding_to_statement(node) {
58
+ Redland.librdf_statement_set_predicate(@rdf_statement, node.rdf_node)
59
+ }
53
60
  end
54
61
 
55
62
  # set the object of the statement
56
63
  def object=(node)
57
- Redland.librdf_statement_set_object(@rdf_statement, rdf_node_from(node))
58
- end
59
-
60
- def model
61
- @model
62
- end
63
-
64
- # Add the statement to the given model.
65
- #
66
- # Returns the model on success, or nil.
67
- # NOTE: Duplicate statements are not added to the model.
68
- # However, this doesn't result in an error here.
69
- def model=(model)
70
- if model.nil?
71
- @model = nil
72
- else
73
- if self.valid?
74
- if Redland.librdf_model_add_statement(model.rdf_model, @rdf_statement).zero?
75
- @model = model
76
- else
77
- nil
78
- end
79
- end
80
- end
81
- end
82
-
83
- # Destroy the statement (remove it from the model, if possible).
84
- #
85
- # Returns true if successfully removed from the model, or false.
86
- # If the statement is not bound to a model, false is returned.
87
- def destroy
88
- if @model
89
- if Redland.librdf_model_remove_statement(@model.rdf_model, @rdf_statement).zero?
90
- self.model = nil
91
- true
92
- else
93
- false
94
- end
95
- else
96
- false
97
- end
64
+ binding_to_statement(node) {
65
+ Redland.librdf_statement_set_object(@rdf_statement, node.rdf_node)
66
+ }
98
67
  end
99
68
 
100
69
  def eql?(other_statement)
101
- model == other_statement.model &&
102
- subject == other_statement.subject &&
70
+ subject == other_statement.subject &&
103
71
  predicate == other_statement.predicate &&
104
72
  object == other_statement.object
105
73
  end
@@ -116,38 +84,26 @@ module Redlander
116
84
  # A valid statement satisfies the following:
117
85
  # URI or blank subject, URI predicate and URI or blank or literal object (i.e. anything).
118
86
  def valid?
119
- if is_valid = attributes_satisfy?
120
- errors.clear
121
- else
122
- errors.add("is invalid")
123
- end
124
- is_valid
87
+ attributes_satisfy? ? errors.clear : errors.add("is invalid")
88
+ errors.empty?
125
89
  end
126
90
 
127
91
 
128
92
  private
129
93
 
130
- def rdf_node_from(node)
131
- if node.nil?
132
- nil
133
- else
134
- # According to Redland docs,
135
- # the node here becomes a part of the statement
136
- # and must not be used by the caller!
137
- if node.frozen?
138
- raise RedlandError.new("The node is already bound to a statement and cannot be added.")
139
- else
140
- node.freeze.rdf_node
141
- end
142
- end
143
- end
144
-
145
94
  def attributes_satisfy?
146
95
  !subject.nil? && (subject.resource? || subject.blank?) &&
147
96
  !predicate.nil? && predicate.resource? &&
148
97
  !object.nil?
149
98
  end
150
99
 
100
+ def binding_to_statement(node)
101
+ if node.frozen?
102
+ raise RedlandError.new("Cannot assign a bound node")
103
+ else
104
+ node.freeze
105
+ yield
106
+ end
107
+ end
151
108
  end
152
-
153
109
  end
@@ -1,9 +1,9 @@
1
1
  module Redlander
2
-
3
- module Storage
4
-
2
+ class Storage
5
3
  VALID_STORAGE_TYPES = [:memory, :hashes, :file, :uri, :tstore, :mysql, :sqlite, :postgresql]
6
4
 
5
+ attr_reader :rdf_storage
6
+
7
7
  # Creates a store of the given type
8
8
  #
9
9
  # Store types (:storage option) are:
@@ -31,49 +31,27 @@ module Redlander
31
31
  #
32
32
  # NOTE: When dealing with databases,
33
33
  # Redland (1.0.7) just crashes when the required tables aren't available!
34
- def self.initialize_storage(options = {})
35
- storage_type, storage_options = split_options(options)
36
- storage_type ||= :memory
34
+ def initialize(options = {})
35
+ storage_type, storage_options = split_options(options.dup)
37
36
 
38
37
  unless VALID_STORAGE_TYPES.include?(storage_type)
39
38
  raise RedlandError.new("Unknown storage type: #{storage_type}")
40
39
  end
41
40
 
42
- rdf_storage = Redland.librdf_new_storage(Redlander.rdf_world,
43
- storage_type.to_s,
44
- storage_options.delete(:name).to_s,
45
- Redlander.to_rdf_options(storage_options))
46
- raise RedlandError.new("Failed to initialize storage") unless rdf_storage
47
- ObjectSpace.define_finalizer(rdf_storage, proc { Redland.librdf_free_storage(rdf_storage) })
48
-
49
- rdf_storage
50
- end
51
-
52
- # Wrap changes to the given model in a transaction.
53
- # If an exception is raised in the block, the transaction is rolled back.
54
- # (Does not work for all storages, in which case the changes are instanteous).
55
- def self.transaction(model, &block)
56
- Redland.librdf_model_transaction_start(model.rdf_model).zero? || RedlandError.new("Failed to initialize a transaction")
57
- block.call
58
- Redland.librdf_model_transaction_commit(model.rdf_model).zero? || RedlandError.new("Failed to commit the transaction")
59
- rescue
60
- rollback(model)
61
- end
62
-
63
- # Rollback a latest transaction for the given model.
64
- def self.rollback(model)
65
- Redland.librdf_model_transaction_rollback(model.rdf_model).zero? || RedlandError.new("Failed to rollback the latest transaction")
41
+ @rdf_storage = Redland.librdf_new_storage(Redlander.rdf_world,
42
+ storage_type.to_s,
43
+ storage_options.delete(:name).to_s,
44
+ Redlander.to_rdf_options(storage_options))
45
+ raise RedlandError.new("Failed to initialize storage") if @rdf_storage.null?
46
+ ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_storage(@rdf_storage) })
66
47
  end
67
48
 
68
49
 
69
50
  private
70
51
 
71
- def self.split_options(options = {})
72
- storage_options = options.dup
73
- storage_type = storage_options.delete(:storage)
74
- [storage_type, storage_options]
52
+ def split_options(options)
53
+ storage_type = options.delete(:storage) || :memory
54
+ [storage_type, options]
75
55
  end
76
-
77
56
  end
78
-
79
57
  end
@@ -0,0 +1,57 @@
1
+ module Redlander
2
+ class Stream
3
+ attr_reader :rdf_stream
4
+
5
+ # Convert something to an RDF stream.
6
+ # Source can be:
7
+ # Parser - to parse content into a stream
8
+ # Model - to convert a model to an RDF stream, or
9
+ # if content (Statement) supplied,
10
+ # produce a stream of statements from the given model,
11
+ # matching the non-empty nodes of the given statement.
12
+ def initialize(source, content = nil, options = {})
13
+ @rdf_stream = case source
14
+ when Model
15
+ if content.is_a?(Statement)
16
+ Redland.librdf_model_find_statements(source.rdf_model, content.rdf_statement)
17
+ else
18
+ Redland.librdf_model_as_stream(source.rdf_model)
19
+ end
20
+ when Parser
21
+ base_uri = options[:base_uri] ? Uri.new(options[:base_uri]).rdf_uri : nil
22
+ Redland.librdf_parser_parse_string_as_stream(source.rdf_parser, content, base_uri)
23
+ else
24
+ # TODO
25
+ raise NotImplementedError.new
26
+ end
27
+ raise RedlandError.new("Failed to create a new stream") if @rdf_stream.null?
28
+ ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_stream(@rdf_stream) })
29
+ end
30
+
31
+ # End-of-stream?
32
+ def eos?
33
+ Redland.librdf_stream_end(@rdf_stream) != 0
34
+ end
35
+
36
+ # Move stream pointer forward
37
+ def succ
38
+ Redland.librdf_stream_next(@rdf_stream).zero?
39
+ end
40
+
41
+ # Current statement in the stream, or nil
42
+ def current
43
+ Statement.new(self) unless eos?
44
+ end
45
+
46
+ # Return all the remaining statements in the stream
47
+ # from the current position.
48
+ def tail
49
+ [].tap do |all|
50
+ while !eos?
51
+ all << current
52
+ succ
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,43 @@
1
+ module Redlander
2
+ class Stream
3
+ attr_reader :rdf_stream
4
+
5
+ def initialize(source)
6
+ @rdf_stream = case source
7
+ when Statement
8
+ Redland.librdf_model_find_statements(source.model.rdf_model, source.rdf_statement)
9
+ when Model
10
+ Redland.librdf_model_as_stream(source.rdf_model)
11
+ else
12
+ # TODO
13
+ raise NotImplementedError.new
14
+ end
15
+ raise RedlandError.new("Failed to create a new stream") if @rdf_stream.null?
16
+ ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_stream(@rdf_stream) })
17
+ end
18
+
19
+ # End-of-stream?
20
+ def eos?
21
+ Redland.librdf_stream_end(@rdf_stream) != 0
22
+ end
23
+
24
+ def succ
25
+ Redland.librdf_stream_next(@rdf_stream).zero?
26
+ end
27
+
28
+ def current
29
+ Statement.new(self)
30
+ end
31
+
32
+ # Return all the remaining statements in the stream
33
+ # from the current position.
34
+ def tail
35
+ [].tap do |all|
36
+ while !eos?
37
+ all << current
38
+ succ
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end