activerdf_net7 1.6.16 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +63 -0
- data/activerdf-jena/lib/activerdf_jena/jena.rb +4 -4
- data/activerdf-jena/lib/activerdf_jena/jena_adapter.rb +55 -55
- data/activerdf-jena/lib/activerdf_jena/lucene.rb +1 -1
- data/activerdf-jena/lib/activerdf_jena/ng4j.rb +7 -7
- data/activerdf-jena/lib/activerdf_jena/ng4j_adapter.rb +47 -47
- data/activerdf-jena/lib/activerdf_jena/pellet.rb +1 -1
- data/activerdf-jena/test/test_jena_adapter.rb +121 -120
- data/activerdf-jena/test/test_ng4j_adapter.rb +111 -110
- data/activerdf-rdflite/lib/activerdf_rdflite/fetching.rb +23 -19
- data/activerdf-rdflite/lib/activerdf_rdflite/rdflite.rb +153 -277
- data/activerdf-rdflite/lib/activerdf_rdflite/suggesting.rb +2 -2
- data/activerdf-rdflite/test/test_fetching.rb +7 -22
- data/activerdf-rdflite/test/test_rdflite.rb +44 -257
- data/activerdf-redland/lib/activerdf_redland/redland.rb +246 -282
- data/activerdf-redland/test/test_redland_adapter.rb +62 -224
- data/activerdf-sesame/ext/wrapper-sesame2.jar +0 -0
- data/activerdf-sesame/java/build.number +2 -2
- data/activerdf-sesame/java/build.xml +0 -0
- data/activerdf-sesame/java/lib/junit-3.8.2.jar +0 -0
- data/activerdf-sesame/java/settings.xml +0 -0
- data/activerdf-sesame/java/src/org/activerdf/wrapper/sesame2/WrapperForSesame2.java +0 -0
- data/activerdf-sesame/java/temp/build/org/activerdf/wrapper/sesame2/WrapperForSesame2.class +0 -0
- data/activerdf-sesame/java/temp/manifest/MANIFEST.MF +2 -2
- data/activerdf-sesame/java/test-src/org/activerdf/wrapper/sesame2/TestWrapperForSesame2.java +0 -0
- data/activerdf-sesame/lib/activerdf_sesame/sesame.rb +360 -364
- data/activerdf-sesame/test/test_sesame_adapter.rb +85 -83
- data/activerdf-sparql/lib/activerdf_sparql/sparql.rb +147 -148
- data/activerdf-sparql/lib/activerdf_sparql/sparql_result_parser.rb +5 -5
- data/activerdf-sparql/test/test_sparql_adapter.rb +2 -0
- data/activerdf-yars/lib/activerdf_yars/jars2.rb +85 -83
- data/lib/active_rdf/federation/active_rdf_adapter.rb +26 -39
- data/lib/active_rdf/federation/connection_pool.rb +119 -110
- data/lib/active_rdf/federation/federation_manager.rb +51 -51
- data/lib/active_rdf/objectmanager/bnode.rb +8 -2
- data/lib/active_rdf/objectmanager/literal.rb +81 -50
- data/lib/active_rdf/objectmanager/namespace.rb +117 -84
- data/lib/active_rdf/objectmanager/object_manager.rb +101 -96
- data/lib/active_rdf/objectmanager/ordered_set.rb +1 -1
- data/lib/active_rdf/objectmanager/property.rb +345 -0
- data/lib/active_rdf/objectmanager/property_list.rb +4 -4
- data/lib/active_rdf/objectmanager/property_lookup.rb +57 -0
- data/lib/active_rdf/objectmanager/resource.rb +293 -501
- data/lib/active_rdf/objectmanager/resource_like.rb +2 -2
- data/lib/active_rdf/objectmanager/resource_query.rb +85 -0
- data/lib/active_rdf/queryengine/ntriples_parser.rb +75 -68
- data/lib/active_rdf/queryengine/query.rb +237 -183
- data/lib/active_rdf/queryengine/query2jars2.rb +17 -15
- data/lib/active_rdf/queryengine/query2sparql.rb +107 -101
- data/lib/active_rdf.rb +28 -17
- data/lib/active_rdf_helpers.rb +37 -5
- data/lib/active_rdf_log.rb +11 -11
- data/test/adapters/test_activerdf_adapter.rb +138 -0
- data/test/{test_adapters.rb → adapters/test_adapters.rb} +6 -24
- data/test/adapters/test_bnode_capable_adapter.rb +31 -0
- data/test/adapters/test_context_aware_adapter.rb +31 -0
- data/test/adapters/test_network_aware_adapter.rb +29 -0
- data/test/adapters/test_persistent_adapter.rb +21 -0
- data/test/adapters/test_read_only_adapter.rb +15 -0
- data/test/adapters/test_reasoning_adapter.rb +11 -0
- data/test/adapters/test_writable_adapter.rb +163 -0
- data/test/common.rb +78 -96
- data/test/federation/test_connection_pool.rb +25 -44
- data/test/federation/test_federation_manager.rb +45 -45
- data/test/objectmanager/test_literal.rb +47 -26
- data/test/objectmanager/test_namespace.rb +3 -1
- data/test/objectmanager/test_object_manager.rb +35 -45
- data/test/objectmanager/test_ordered_set.rb +1 -1
- data/test/objectmanager/test_property.rb +261 -0
- data/test/objectmanager/test_resource_reading.rb +196 -104
- data/test/objectmanager/test_resource_reasoning.rb +26 -0
- data/test/objectmanager/test_resource_writing.rb +34 -25
- data/test/queryengine/my_external_resource.rb +5 -1
- data/test/queryengine/test_external_resource_class.rb +1 -8
- data/test/queryengine/test_ntriples_parser.rb +5 -3
- data/test/queryengine/test_query.rb +3 -3
- data/test/queryengine/test_query2jars2.rb +2 -2
- data/test/queryengine/test_query2sparql.rb +2 -2
- data/test/queryengine/test_query_engine.rb +46 -28
- metadata +16 -8
- data/activerdf-rdflite/test/test_bnode_data.nt +0 -5
- data/activerdf-rdflite/test/test_data.nt +0 -32
- data/activerdf-rdflite/test/test_escaped_data.nt +0 -2
- data/activerdf-redland/test/test_person_data.nt +0 -42
- data/test/objectmanager/test_talia_syntax.rb +0 -68
@@ -5,208 +5,207 @@ require 'cgi'
|
|
5
5
|
require 'rexml/document'
|
6
6
|
require "#{File.dirname(__FILE__)}/sparql_result_parser"
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
module ActiveRDF
|
9
|
+
# SPARQL adapter
|
10
|
+
class SparqlAdapter < ActiveRdfAdapter
|
10
11
|
ActiveRdfLogger::log_info "Loading SPARQL adapter", self
|
11
|
-
|
12
|
+
ConnectionPool.register_adapter(:sparql, self)
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
attr_reader :engine
|
15
|
+
attr_reader :caching
|
15
16
|
|
16
|
-
|
17
|
+
@@sparql_cache = {}
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
def SparqlAdapter.get_cache
|
20
|
+
return @@sparql_cache
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
23
|
+
# Instantiate the connection with the SPARQL Endpoint.
|
24
|
+
# available parameters:
|
25
|
+
# * :url => url: endpoint location e.g. "http://m3pe.org:8080/repositories/test-people"
|
26
|
+
# * :results => one of :xml, :json, :sparql_xml
|
27
|
+
# * :request_method => :get (default) or :post
|
28
|
+
# * :timeout => timeout in seconds to wait for endpoint response
|
29
|
+
# * :auth => [user, pass]
|
30
|
+
def initialize(params = {})
|
31
|
+
super()
|
32
|
+
@reads = true
|
33
|
+
@writes = false
|
34
|
+
|
35
|
+
@url = params[:url] || ''
|
36
|
+
@caching = params[:caching] || false
|
37
|
+
@timeout = params[:timeout] || 50
|
38
|
+
@auth = params[:auth] || nil
|
39
|
+
|
40
|
+
@result_format = params[:results] || :json
|
41
|
+
raise ActiveRdfError, "Result format unsupported" unless [:xml, :json, :sparql_xml].include? @result_format
|
42
|
+
|
43
|
+
@engine = params[:engine]
|
44
|
+
raise ActiveRdfError, "SPARQL engine unsupported" unless [:yars2, :sesame2, :joseki, :virtuoso].include? @engine
|
45
|
+
|
46
|
+
@request_method = params[:request_method] || :get
|
47
|
+
raise ActiveRdfError, "Request method unsupported" unless [:get,:post].include? @request_method
|
47
48
|
ActiveRdfLogger::log_info(self) { "Sparql adapter initialised #{inspect}" }
|
48
|
-
|
49
|
+
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
def size
|
52
|
+
query(Query.new.select(:s,:p,:o).where(:s,:p,:o)).size
|
53
|
+
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
# query datastore with query string (SPARQL), returns array with query results
|
56
|
+
# may be called with a block
|
57
|
+
def execute(query, &block)
|
58
|
+
qs = Query2SPARQL.translate(query)
|
58
59
|
ActiveRdfLogger::log_debug(self) { "Executing sparql query #{query}" }
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
|
61
|
+
if @caching
|
62
|
+
result = query_cache(qs)
|
63
|
+
if result.nil?
|
63
64
|
ActiveRdfLogger.log_debug(self) { "Cache miss for query #{qs}" }
|
64
|
-
|
65
|
+
else
|
65
66
|
ActiveRdfLogger.log_debug(self) { "Cache hit for query #{qs}" }
|
66
|
-
|
67
|
+
return result
|
68
|
+
end
|
67
69
|
end
|
68
|
-
end
|
69
70
|
|
70
71
|
result = execute_sparql_query(qs, query.resource_class, header(query), &block)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
72
|
+
add_to_cache(qs, result) if @caching
|
73
|
+
result = [] if result == "timeout"
|
74
|
+
return result
|
75
|
+
end
|
75
76
|
|
76
|
-
|
77
|
+
# do the real work of executing the sparql query
|
77
78
|
def execute_sparql_query(qs, resource_type, header=nil, &block)
|
78
79
|
ActiveRdfLogger::log_debug(self) { "Executing query #{qs} on url #@url" }
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
80
|
+
header = header(nil) if header.nil?
|
81
|
+
|
82
|
+
# querying sparql endpoint
|
83
|
+
require 'timeout'
|
84
|
+
response = ''
|
85
|
+
begin
|
86
|
+
case @request_method
|
87
|
+
when :get
|
88
|
+
# encoding query string in URL
|
89
|
+
url = "#@url?query=#{CGI.escape(qs)}"
|
89
90
|
ActiveRdfLogger.log_debug(self) { "GET #{url}" }
|
90
|
-
|
91
|
-
|
92
|
-
|
91
|
+
timeout(@timeout) do
|
92
|
+
open(url, header) do |f|
|
93
|
+
response = f.read
|
94
|
+
end
|
93
95
|
end
|
94
|
-
|
95
|
-
when :post
|
96
|
+
when :post
|
96
97
|
ActiveRdfLogger.log_debug(self) { "POST #@url with #{qs}" }
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
98
|
+
response = Net::HTTP.post_form(URI.parse(@url),{'query'=>qs}).body
|
99
|
+
end
|
100
|
+
rescue Timeout::Error
|
101
|
+
raise ActiveRdfError, "timeout on SPARQL endpoint"
|
102
|
+
rescue OpenURI::HTTPError => e
|
103
|
+
raise ActiveRdfError, "error on SPARQL endpoint, server said: \n%s:\n%s" % [e,e.io.read]
|
104
|
+
rescue Errno::ECONNREFUSED
|
105
|
+
raise ActiveRdfError, "connection refused on SPARQL endpoint #@url"
|
106
|
+
end
|
107
|
+
|
108
|
+
# we parse content depending on the result format
|
109
|
+
results = case @result_format
|
110
|
+
when :json
|
110
111
|
parse_json(response, resource_type)
|
111
|
-
|
112
|
+
when :xml, :sparql_xml
|
112
113
|
parse_xml(response, resource_type)
|
113
|
-
|
114
|
+
end
|
114
115
|
|
115
|
-
|
116
|
-
|
117
|
-
|
116
|
+
if block_given?
|
117
|
+
results.each do |*clauses|
|
118
|
+
yield(*clauses)
|
119
|
+
end
|
120
|
+
else
|
121
|
+
results
|
118
122
|
end
|
119
|
-
else
|
120
|
-
results
|
121
123
|
end
|
122
|
-
end
|
123
124
|
|
124
|
-
|
125
|
-
|
126
|
-
|
125
|
+
def close
|
126
|
+
ConnectionPool.remove_data_source(self)
|
127
|
+
end
|
127
128
|
|
128
|
-
|
129
|
+
private
|
129
130
|
# FIXME: Cache not primed for handling res classes!
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
131
|
+
def add_to_cache(query_string, result)
|
132
|
+
unless result.nil? or result.empty?
|
133
|
+
if result == "timeout"
|
134
|
+
@@sparql_cache.store(query_string, [])
|
135
|
+
else
|
135
136
|
ActiveRdfLogger.log_debug(self) { "Adding to sparql cache - query: #{query_string}" }
|
136
|
-
|
137
|
+
@@sparql_cache.store(query_string, result)
|
138
|
+
end
|
137
139
|
end
|
138
140
|
end
|
139
|
-
end
|
140
141
|
|
141
142
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
143
|
+
def query_cache(query_string)
|
144
|
+
if @@sparql_cache.include?(query_string)
|
145
|
+
return @@sparql_cache.fetch(query_string)
|
146
|
+
else
|
147
|
+
return nil
|
148
|
+
end
|
147
149
|
end
|
148
|
-
end
|
149
150
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
151
|
+
# constructs correct HTTP header for selected query-result format
|
152
|
+
def header(query)
|
153
|
+
header = case @result_format
|
154
|
+
when :json
|
155
|
+
{ 'accept' => 'application/sparql-results+json' }
|
156
|
+
when :xml
|
157
|
+
{ 'accept' => 'application/rdf+xml' }
|
158
|
+
when :sparql_xml
|
159
|
+
{ 'accept' => 'application/sparql-results+xml' }
|
160
|
+
end
|
161
|
+
if @auth
|
162
|
+
header.merge( :http_basic_authentication => @auth )
|
163
|
+
else
|
164
|
+
header
|
165
|
+
end
|
164
166
|
end
|
165
|
-
end
|
166
167
|
|
167
168
|
# parse json query results into array. resource_type is the type to be used
|
168
169
|
# for "resource" objects.
|
169
170
|
def parse_json(s, resource_type)
|
170
|
-
|
171
|
+
require 'json'
|
171
172
|
|
172
|
-
|
173
|
-
|
173
|
+
parsed_object = JSON.parse(s)
|
174
|
+
return [] if parsed_object.nil?
|
174
175
|
|
175
|
-
|
176
|
-
|
177
|
-
|
176
|
+
results = []
|
177
|
+
vars = parsed_object['head']['vars']
|
178
|
+
objects = parsed_object['results']['bindings']
|
178
179
|
|
179
|
-
|
180
|
-
|
181
|
-
|
180
|
+
objects.each do |obj|
|
181
|
+
result = []
|
182
|
+
vars.each do |v|
|
182
183
|
result << create_node( obj[v]['type'], obj[v]['value'], resource_type)
|
184
|
+
end
|
185
|
+
results << result
|
183
186
|
end
|
184
|
-
results << result
|
185
|
-
end
|
186
187
|
|
187
|
-
|
188
|
-
|
188
|
+
results
|
189
|
+
end
|
189
190
|
|
190
|
-
|
191
|
+
# parse xml stream result into array
|
191
192
|
def parse_xml(s, resource_type)
|
192
193
|
parser = SparqlResultParser.new(resource_type)
|
193
|
-
|
194
|
-
|
195
|
-
|
194
|
+
REXML::Document.parse_stream(s, parser)
|
195
|
+
parser.result
|
196
|
+
end
|
196
197
|
|
197
198
|
# create ruby objects for each RDF node. resource_type is the class to be used
|
198
199
|
# for "resource" objects.
|
199
200
|
def create_node(type, value, resource_type)
|
200
|
-
|
201
|
-
|
201
|
+
case type
|
202
|
+
when 'uri'
|
202
203
|
resource_type.new(value)
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
204
|
+
when 'bnode'
|
205
|
+
BNode.new(value)
|
206
|
+
when 'literal','typed-literal'
|
207
|
+
value.to_s
|
208
|
+
end
|
207
209
|
end
|
208
210
|
end
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
end
|
211
|
+
end
|
@@ -9,7 +9,7 @@ class SparqlResultParser
|
|
9
9
|
@current_type = nil
|
10
10
|
@resource_type = resource_type
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def tag_start(name, attrs)
|
14
14
|
case name
|
15
15
|
when 'variable'
|
@@ -22,7 +22,7 @@ class SparqlResultParser
|
|
22
22
|
@current_type = name
|
23
23
|
end
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def tag_end(name)
|
27
27
|
if name == "result"
|
28
28
|
@result << @current_result
|
@@ -31,10 +31,10 @@ class SparqlResultParser
|
|
31
31
|
elsif name == "sparql"
|
32
32
|
end
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def text(text)
|
36
36
|
if !@current_type.nil?
|
37
|
-
@current_result[@index] = create_node(@current_type, text)
|
37
|
+
@current_result[@index] = create_node(@current_type, text)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -49,7 +49,7 @@ class SparqlResultParser
|
|
49
49
|
value.to_s
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def method_missing (*args)
|
54
54
|
end
|
55
55
|
end
|
@@ -9,111 +9,113 @@ require 'cgi'
|
|
9
9
|
|
10
10
|
# Read-only adapter to jars2
|
11
11
|
# (experimental YARS branch for SWSE engine)
|
12
|
-
|
12
|
+
module ActiveRDF
|
13
|
+
class Jars2Adapter < ActiveRdfAdapter
|
13
14
|
ActiveRdfLogger::log_info "Loading Jars2 adapter", self
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
15
|
+
ConnectionPool.register_adapter(:jars2, self)
|
16
|
+
|
17
|
+
# initialises connection to jars2 datastore
|
18
|
+
# available parameters are:
|
19
|
+
# * :host (default 'm3pe.org')
|
20
|
+
# * :port (default 2020)
|
21
|
+
def initialize(params = {})
|
22
|
+
super()
|
23
|
+
@reads = true
|
24
|
+
@writes = false
|
25
|
+
|
26
|
+
@host = params[:host] || 'm3pe.org'
|
27
|
+
@port = params[:port] || 2020
|
27
28
|
ActiveRdfLogger::log_info(self) { "Initializing new instance with host: #{@host} port: #{@port}" }
|
28
|
-
|
29
|
-
|
29
|
+
@yars = Net::HTTP.new(@host, @port)
|
30
|
+
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
def translate query
|
33
|
+
Query2Jars2.translate(query)
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
# executes query on jars2 datastore
|
37
|
+
def execute(query)
|
38
|
+
qs = Query2Jars2.translate(query)
|
39
|
+
header = { 'Accept' => 'application/rdf+n3' }
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
# querying Jars2, adding 'eyal' parameter to get all variable bindings in
|
42
|
+
# the result
|
43
|
+
response = @yars.get("/?q=#{CGI.escape(qs)}&eyal", header)
|
43
44
|
|
44
45
|
ActiveRdfLogger::log_debug(self) { "Jars2Adapter: query executed: #{qs}" }
|
45
46
|
|
46
|
-
|
47
|
-
|
47
|
+
# return empty array if no content
|
48
|
+
return [] if response.is_a?(Net::HTTPNoContent)
|
48
49
|
|
49
|
-
|
50
|
-
|
50
|
+
# return false unless HTTP OK returned
|
51
|
+
return false unless response.is_a?(Net::HTTPOK)
|
51
52
|
|
52
|
-
|
53
|
-
|
53
|
+
# parse the result
|
54
|
+
results = parse_result(response.body, query)
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
# remove duplicates if asked for distinct results
|
57
|
+
if query.distinct?
|
58
|
+
final_results = results.uniq
|
59
|
+
else
|
60
|
+
final_results = results
|
61
|
+
end
|
61
62
|
|
62
63
|
ActiveRdfLogger::log_debug_pp "Query returned %s", final_results if ActiveRdfLogger::log_level == Logger::DEBUG
|
63
|
-
|
64
|
-
|
64
|
+
final_results
|
65
|
+
end
|
65
66
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
67
|
+
private
|
68
|
+
Resource = /<[^>]*>/
|
69
|
+
Literal = /"[^"]*"/
|
70
|
+
Node = Regexp.union(Resource,Literal)
|
71
|
+
|
72
|
+
# parses Jars2 results into array of ActiveRDF objects
|
73
|
+
def parse_result(response, query)
|
74
|
+
# Jars2 responses contain one result per line
|
75
|
+
results = response.split("\n")
|
76
|
+
|
77
|
+
# the first line of the response contains the variable bindings of the
|
78
|
+
# results: we look at that line to figure out which column contains the
|
79
|
+
# data we are looking for (which is the variables mentioned in the select
|
80
|
+
# clauses of the query
|
81
|
+
bindings = results[0].split(' ')
|
82
|
+
|
83
|
+
# array of found answers, will be filled by iterating over the results and
|
84
|
+
# only including the requested (i.e. selected) clauses
|
85
|
+
answers = []
|
86
|
+
|
87
|
+
# we iterate over the real results, and extract the clauses that we're
|
88
|
+
# looking for (i.e. the select clauses from the query)
|
89
|
+
results[1..-1].each do |result|
|
90
|
+
|
91
|
+
# scan row for occurence of nodes (either resources or literals)
|
92
|
+
row = result.scan(Node)
|
93
|
+
|
94
|
+
# for each select clause, we find its index, and add the value at that
|
95
|
+
# location in the result row to our answer
|
96
|
+
row = query.select_clauses.collect do |clause|
|
97
|
+
clause_index = bindings.index(clause)
|
97
98
|
convert_into_activerdf(row[clause_index], query.resource_class)
|
99
|
+
end
|
100
|
+
answers << row
|
98
101
|
end
|
99
|
-
answers << row
|
100
|
-
end
|
101
102
|
|
102
|
-
|
103
|
-
|
103
|
+
answers
|
104
|
+
end
|
104
105
|
|
105
106
|
# converts ntriples serialisation of resource or literal into ActiveRDF object.
|
106
107
|
#
|
107
108
|
# resource_type is the class to be used for "resource" objects.
|
108
109
|
def convert_into_activerdf(string, resource_type)
|
109
|
-
|
110
|
-
|
111
|
-
|
110
|
+
case string
|
111
|
+
when /<(.*)>/
|
112
|
+
# <http://foaf/Person> is a resource
|
112
113
|
resource_type.new($1)
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
114
|
+
when /"(.*)"/
|
115
|
+
# "30" is a literal
|
116
|
+
# TODO: handle datatypes
|
117
|
+
String.new($1)
|
118
|
+
end
|
117
119
|
end
|
118
120
|
end
|
119
|
-
end
|
121
|
+
end
|