redlander 0.3.6 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/ChangeLog +19 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +30 -0
- data/LICENSE +7 -0
- data/README.rdoc +85 -12
- data/Rakefile +5 -4
- data/lib/redland.rb +6 -2
- data/lib/redlander.rb +5 -3
- data/lib/redlander/model.rb +98 -16
- data/lib/redlander/model_proxy.rb +115 -58
- data/lib/redlander/node.rb +62 -59
- data/lib/redlander/parsing.rb +123 -0
- data/lib/redlander/serializing.rb +89 -0
- data/lib/redlander/statement.rb +61 -60
- data/lib/redlander/uri.rb +20 -13
- data/lib/redlander/version.rb +2 -1
- data/redlander.gemspec +28 -0
- data/spec/fixtures/doap.nt +62 -0
- data/spec/fixtures/doap.rdf +189 -0
- data/spec/fixtures/doap.ttl +53 -0
- data/spec/lib/redlander/model_spec.rb +304 -0
- data/spec/{redlander → lib/redlander}/node_spec.rb +26 -12
- data/spec/lib/redlander/statement_spec.rb +56 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +15 -4
- metadata +49 -37
- data/lib/redlander/error_container.rb +0 -42
- data/lib/redlander/parser.rb +0 -92
- data/lib/redlander/parser_proxy.rb +0 -22
- data/lib/redlander/serializer.rb +0 -85
- data/lib/redlander/storage.rb +0 -56
- data/lib/redlander/stream.rb +0 -57
- data/lib/redlander/stream_enumerator.rb +0 -17
- data/spec/redlander/model_spec.rb +0 -255
- data/spec/redlander/parser_spec.rb +0 -96
- data/spec/redlander/serializer_spec.rb +0 -52
- data/spec/redlander/statement_spec.rb +0 -77
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'redlander/stream'
|
2
|
-
require 'redlander/stream_enumerator'
|
3
|
-
|
4
|
-
module Redlander
|
5
|
-
class ParserProxy
|
6
|
-
include StreamEnumerator
|
7
|
-
|
8
|
-
def initialize(parser, content, options = {})
|
9
|
-
# TODO: consider a streaming content, as it may be large to fit in memory
|
10
|
-
@parser = parser
|
11
|
-
@content = content
|
12
|
-
@options = options
|
13
|
-
end
|
14
|
-
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def reset_stream
|
19
|
-
@stream = Stream.new(@parser, @content, @options)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/lib/redlander/serializer.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
module Redlander
|
2
|
-
class Serializer
|
3
|
-
# Create a new serializer.
|
4
|
-
# Name can be either of [:rdfxml, :ntriples, :turtle, :json, :dot],
|
5
|
-
# or nil, which defaults to :rdfxml.
|
6
|
-
#
|
7
|
-
# TODO: Only a small subset of parsers is implemented,
|
8
|
-
# because the rest seem to be very buggy.
|
9
|
-
def initialize(name = :rdfxml)
|
10
|
-
@rdf_serializer = Redland.librdf_new_serializer(Redlander.rdf_world, name.to_s, nil, nil)
|
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) })
|
13
|
-
end
|
14
|
-
|
15
|
-
# Serialize a model into a string.
|
16
|
-
#
|
17
|
-
# Options are:
|
18
|
-
# :base_uri base URI (String or URI)
|
19
|
-
def to_string(model, options = {})
|
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)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Serializes a model and stores it in a file
|
29
|
-
# filename - the name of the file to serialize to
|
30
|
-
# model - model instance
|
31
|
-
#
|
32
|
-
# Options are:
|
33
|
-
# :base_uri base URI (String or URI)
|
34
|
-
#
|
35
|
-
# Returns true on success, or false.
|
36
|
-
def to_file(model, filename, options = {})
|
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?
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
# Applied to Model
|
48
|
-
module SerializingInstanceMethods
|
49
|
-
def to_rdfxml(options = {})
|
50
|
-
serializer = Serializer.new(:rdfxml)
|
51
|
-
serializer.to_string(self, options)
|
52
|
-
end
|
53
|
-
|
54
|
-
def to_ntriples(options = {})
|
55
|
-
serializer = Serializer.new(:ntriples)
|
56
|
-
serializer.to_string(self, options)
|
57
|
-
end
|
58
|
-
|
59
|
-
def to_turtle(options = {})
|
60
|
-
serializer = Serializer.new(:turtle)
|
61
|
-
serializer.to_string(self, options)
|
62
|
-
end
|
63
|
-
|
64
|
-
def to_json(options = {})
|
65
|
-
serializer = Serializer.new(:json)
|
66
|
-
serializer.to_string(self, options)
|
67
|
-
end
|
68
|
-
|
69
|
-
def to_dot(options = {})
|
70
|
-
serializer = Serializer.new(:dot)
|
71
|
-
serializer.to_string(self, options)
|
72
|
-
end
|
73
|
-
|
74
|
-
# Serialize the model into a file.
|
75
|
-
#
|
76
|
-
# Options are:
|
77
|
-
# :format - output format [:rdfxml (default), :ntriples, :turtle, :json, :dot]
|
78
|
-
# :base_uri - base URI
|
79
|
-
def to_file(filename, options = {})
|
80
|
-
serializer_options = options.dup
|
81
|
-
serializer = Serializer.new(serializer_options.delete(:format) || :rdfxml)
|
82
|
-
serializer.to_file(self, filename, serializer_options)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
data/lib/redlander/storage.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
module Redlander
|
2
|
-
class Storage
|
3
|
-
attr_reader :rdf_storage
|
4
|
-
|
5
|
-
# Creates a store of the given type
|
6
|
-
#
|
7
|
-
# Store types (:storage option) are:
|
8
|
-
# :memory
|
9
|
-
# :hashes
|
10
|
-
# :file - memory model initialized from RDF/XML file
|
11
|
-
# :uri - read-only memory model with URI provided in 'name' arg
|
12
|
-
# :mysql
|
13
|
-
# :sqlite
|
14
|
-
# :postgresql
|
15
|
-
# :tstore
|
16
|
-
# :virtuoso
|
17
|
-
# ... anything else that Redland can handle.
|
18
|
-
#
|
19
|
-
# Options are storage-specific.
|
20
|
-
# Read the documentation for the appropriate Redland Storage module.
|
21
|
-
#
|
22
|
-
# :name - ?
|
23
|
-
# :host - database host name (for store types: :postgres, :mysql, :tstore)
|
24
|
-
# :port - database host port (for store types: :postgres, :mysql, :tstore)
|
25
|
-
# :database - database name (for store types: :postgres, :mysql, :tstore)
|
26
|
-
# :user - database user name (for store types: :postgres, :mysql, :tstore)
|
27
|
-
# :password - database user password (for store types: :postgres, :mysql, :tstore)
|
28
|
-
# :hash_type - hash type (for store types: :bdb)
|
29
|
-
# can be either 'memory' or 'bdb'
|
30
|
-
# :new - force creation of a new store
|
31
|
-
# :dir - directory path (for store types: :hashes)
|
32
|
-
# :contexts - support contexts (for store types: :hashes, :memory)
|
33
|
-
# :write - allow writing data to the store (for store types: :hashes)
|
34
|
-
#
|
35
|
-
# NOTE: When dealing with databases,
|
36
|
-
# Redland (1.0.7) just crashes when the required tables aren't available!
|
37
|
-
def initialize(options = {})
|
38
|
-
storage_type, storage_options = split_options(options.dup)
|
39
|
-
|
40
|
-
@rdf_storage = Redland.librdf_new_storage(Redlander.rdf_world,
|
41
|
-
storage_type.to_s,
|
42
|
-
storage_options.delete(:name).to_s,
|
43
|
-
Redlander.to_rdf_options(storage_options))
|
44
|
-
raise RedlandError.new("Failed to initialize '#{storage_type}' storage") if @rdf_storage.null?
|
45
|
-
ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_storage(@rdf_storage) })
|
46
|
-
end
|
47
|
-
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def split_options(options)
|
52
|
-
storage_type = options.delete(:storage) || :memory
|
53
|
-
[storage_type, options]
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
data/lib/redlander/stream.rb
DELETED
@@ -1,57 +0,0 @@
|
|
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
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Redlander
|
2
|
-
module StreamEnumerator
|
3
|
-
include Enumerable
|
4
|
-
|
5
|
-
def each
|
6
|
-
if block_given?
|
7
|
-
reset_stream
|
8
|
-
while !@stream.eos?
|
9
|
-
yield @stream.current
|
10
|
-
@stream.succ
|
11
|
-
end
|
12
|
-
else
|
13
|
-
raise ::LocalJumpError.new("no block given")
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,255 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe Model do
|
4
|
-
|
5
|
-
before { @model = Model.new }
|
6
|
-
|
7
|
-
describe "statements" do
|
8
|
-
|
9
|
-
it { @model.statements.should be_an_instance_of(ModelProxy) }
|
10
|
-
|
11
|
-
it "should be created in the model" do
|
12
|
-
lambda {
|
13
|
-
@model.statements.create(statement_attributes)
|
14
|
-
}.should change(@model.statements, :size).by(1)
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should be iterated over" do
|
18
|
-
statement = @model.statements.create(statement_attributes)
|
19
|
-
statements = []
|
20
|
-
lambda {
|
21
|
-
@model.statements.each do |s|
|
22
|
-
statements << s
|
23
|
-
end
|
24
|
-
}.should change(statements, :size).by(1)
|
25
|
-
statements.first.should eql(statement)
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should be added to the model" do
|
29
|
-
statement = Statement.new(statement_attributes)
|
30
|
-
lambda {
|
31
|
-
@model.statements.add(statement)
|
32
|
-
}.should change(@model.statements, :size).by(1)
|
33
|
-
@model.statements.should include(statement)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should be found without a block" do
|
37
|
-
statement = @model.statements.create(statement_attributes)
|
38
|
-
@model.statements.find(:first).should eql(statement)
|
39
|
-
@model.statements.first.should eql(statement)
|
40
|
-
@model.statements.all.should eql([statement])
|
41
|
-
end
|
42
|
-
|
43
|
-
it "should be found with a block" do
|
44
|
-
statements = []
|
45
|
-
statement = @model.statements.create(statement_attributes)
|
46
|
-
lambda {
|
47
|
-
@model.statements.each do |st|
|
48
|
-
statements << st
|
49
|
-
end
|
50
|
-
}.should change(statements, :size).by(1)
|
51
|
-
statements.first.should eql(statement)
|
52
|
-
end
|
53
|
-
|
54
|
-
it "should be found by an attribute" do
|
55
|
-
statements = []
|
56
|
-
statement = @model.statements.create(statement_attributes)
|
57
|
-
lambda {
|
58
|
-
@model.statements.find(:all, :object => statement.object).each do |st|
|
59
|
-
statements << st
|
60
|
-
end
|
61
|
-
}.should change(statements, :size).by(1)
|
62
|
-
statements.first.should eql(statement)
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should not be found with a block" do
|
66
|
-
statements = []
|
67
|
-
statement = @model.statements.create(statement_attributes)
|
68
|
-
lambda {
|
69
|
-
@model.statements.find(:all, :object => "another object").each do |st|
|
70
|
-
statements << st
|
71
|
-
end
|
72
|
-
}.should_not change(statements, :size)
|
73
|
-
end
|
74
|
-
|
75
|
-
it "should be removed from the model" do
|
76
|
-
statement = @model.statements.create(statement_attributes)
|
77
|
-
lambda {
|
78
|
-
@model.statements.delete(statement)
|
79
|
-
}.should change(@model.statements, :size).by(-1)
|
80
|
-
@model.statements.should_not include(statement)
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
private
|
85
|
-
|
86
|
-
def statement_attributes
|
87
|
-
s = URI.parse('http://example.com/concepts#subject')
|
88
|
-
p = URI.parse('http://example.com/concepts#label')
|
89
|
-
o = "subject!"
|
90
|
-
{
|
91
|
-
:subject => s,
|
92
|
-
:predicate => p,
|
93
|
-
:object => o
|
94
|
-
}
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
98
|
-
|
99
|
-
describe "serialization" do
|
100
|
-
|
101
|
-
before :each do
|
102
|
-
s = URI.parse("http://example.com/concepts#two-dimensional_seismic_imaging")
|
103
|
-
p = URI.parse("http://www.w3.org/2000/01/rdf-schema#label")
|
104
|
-
o = "2-D seismic imaging@en"
|
105
|
-
@model.statements.create(:subject => s, :predicate => p, :object => o)
|
106
|
-
end
|
107
|
-
|
108
|
-
it "should produce RDF/XML content" do
|
109
|
-
content = @model.to_rdfxml
|
110
|
-
content.should be_an_instance_of(String)
|
111
|
-
content.should include('2-D seismic imaging')
|
112
|
-
end
|
113
|
-
|
114
|
-
it "should produce N-Triples content" do
|
115
|
-
content = @model.to_ntriples
|
116
|
-
content.should be_an_instance_of(String)
|
117
|
-
content.should include('2-D seismic imaging@en')
|
118
|
-
end
|
119
|
-
|
120
|
-
it "should produce Turtle content" do
|
121
|
-
content = @model.to_turtle
|
122
|
-
content.should be_an_instance_of(String)
|
123
|
-
content.should include('2-D seismic imaging@en')
|
124
|
-
end
|
125
|
-
|
126
|
-
it "should produce JSON content" do
|
127
|
-
content = @model.to_json
|
128
|
-
content.should be_an_instance_of(String)
|
129
|
-
content.should include('2-D seismic imaging@en')
|
130
|
-
end
|
131
|
-
|
132
|
-
it "should produce DOT content" do
|
133
|
-
content = @model.to_dot
|
134
|
-
content.should be_an_instance_of(String)
|
135
|
-
content.should include('2-D seismic imaging@en')
|
136
|
-
end
|
137
|
-
|
138
|
-
describe "file source" do
|
139
|
-
|
140
|
-
before :each do
|
141
|
-
content = '<?xml version="1.0" encoding="utf-8"?><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="http://example.com/concepts#two-dimensional_seismic_imaging"><ns0:label xmlns:ns0="http://www.w3.org/2000/01/rdf-schema#" xml:lang="en">2-D seismic imaging</ns0:label></rdf:Description></rdf:RDF>'
|
142
|
-
reference_model = Model.new
|
143
|
-
reference_model.from_rdfxml(content, :base_uri => 'http://example.com/concepts')
|
144
|
-
reference_model.to_file(filename)
|
145
|
-
end
|
146
|
-
|
147
|
-
after :each do
|
148
|
-
cleanup
|
149
|
-
end
|
150
|
-
|
151
|
-
it "should be loaded from a file" do
|
152
|
-
lambda {
|
153
|
-
@model.from_file(filename, :base_uri => 'http://example.com/concepts')
|
154
|
-
}.should change(@model.statements, :size).by(1)
|
155
|
-
end
|
156
|
-
|
157
|
-
end
|
158
|
-
|
159
|
-
describe "file destination" do
|
160
|
-
|
161
|
-
before :each do
|
162
|
-
cleanup
|
163
|
-
end
|
164
|
-
|
165
|
-
after :each do
|
166
|
-
cleanup
|
167
|
-
end
|
168
|
-
|
169
|
-
it "should produce a file" do
|
170
|
-
@model.to_file(filename)
|
171
|
-
File.should be_exists(filename)
|
172
|
-
File.size(filename).should_not be_zero
|
173
|
-
end
|
174
|
-
|
175
|
-
end
|
176
|
-
|
177
|
-
private
|
178
|
-
|
179
|
-
def cleanup
|
180
|
-
File.delete(filename) if File.exists?(filename)
|
181
|
-
end
|
182
|
-
|
183
|
-
def filename
|
184
|
-
"test_model.rdf"
|
185
|
-
end
|
186
|
-
|
187
|
-
end
|
188
|
-
|
189
|
-
describe "deserialization" do
|
190
|
-
|
191
|
-
it "should be successful for RDF/XML data" do
|
192
|
-
content = '<?xml version="1.0" encoding="utf-8"?><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="http://example.com/concepts#two-dimensional_seismic_imaging"><ns0:label xmlns:ns0="http://www.w3.org/2000/01/rdf-schema#" xml:lang="en">2-D seismic imaging</ns0:label></rdf:Description></rdf:RDF>'
|
193
|
-
lambda {
|
194
|
-
@model.from_rdfxml(content, :base_uri => 'http://example.com/concepts')
|
195
|
-
}.should change(@model.statements, :size).by(1)
|
196
|
-
end
|
197
|
-
|
198
|
-
it "should be successful for N-Triples data" do
|
199
|
-
content = '<http://example.org/ns/a2> <http://example.org/ns/b2> <http://example.org/ns/c2> .'
|
200
|
-
lambda {
|
201
|
-
@model.from_ntriples(content)
|
202
|
-
}.should change(@model.statements, :size).by(1)
|
203
|
-
end
|
204
|
-
|
205
|
-
it "should be successful for Turtle data" do
|
206
|
-
content = '# this is a complete turtle document
|
207
|
-
@prefix foo: <http://example.org/ns#> .
|
208
|
-
@prefix : <http://other.example.org/ns#> .
|
209
|
-
foo:bar foo: : .'
|
210
|
-
lambda {
|
211
|
-
@model.from_turtle(content, :base_uri => 'http://example.com/concepts')
|
212
|
-
}.should change(@model.statements, :size).by(1)
|
213
|
-
end
|
214
|
-
|
215
|
-
end
|
216
|
-
|
217
|
-
describe "transactions" do
|
218
|
-
before do
|
219
|
-
Redland.stub(:librdf_model_transaction_start => 0,
|
220
|
-
:librdf_model_transaction_commit => 0,
|
221
|
-
:librdf_model_transaction_rollback => 0)
|
222
|
-
end
|
223
|
-
|
224
|
-
context "when start fails" do
|
225
|
-
before { Redland.stub(:librdf_model_transaction_start => -1) }
|
226
|
-
|
227
|
-
it "should raise RedlandError" do
|
228
|
-
lambda {
|
229
|
-
@model.transaction { true }
|
230
|
-
}.should raise_exception RedlandError
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
context "when commit fails" do
|
235
|
-
before { Redland.stub(:librdf_model_transaction_commit => -1) }
|
236
|
-
|
237
|
-
it "should raise RedlandError" do
|
238
|
-
lambda {
|
239
|
-
@model.transaction { true }
|
240
|
-
}.should raise_exception RedlandError
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
context "when rollback fails" do
|
245
|
-
before { Redland.stub(:librdf_model_transaction_rollback => -1) }
|
246
|
-
|
247
|
-
it "should raise RedlandError" do
|
248
|
-
lambda {
|
249
|
-
@model.rollback
|
250
|
-
}.should raise_exception RedlandError
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
end
|