activerdf 1.6.2 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,6 @@
1
+ == activerdf (1.6.3) Thu, 09 Aug 2007 15:11:15 +0100
2
+ * added support for LANG filters and engine-specific keyword search in SPARQL
3
+
1
4
  == activerdf (1.6.2) Fri, 03 Aug 2007 14:07:54 +0100
2
5
  * initial support for FILTERs in SPARQL
3
6
 
@@ -322,7 +322,11 @@ module RDFS
322
322
  end
323
323
  end
324
324
 
325
- def add_predicate localname, fulluri
325
+ # define a localname for a predicate URI
326
+ #
327
+ # localname should be a Symbol or String, fulluri a Resource or String, e.g.
328
+ # add_predicate(:name, FOAF::lastName)
329
+ def add_predicate localname, fulluri
326
330
  localname = localname.to_s
327
331
  fulluri = RDFS::Resource.new(fulluri) if fulluri.is_a? String
328
332
 
@@ -90,12 +90,21 @@ class Query
90
90
  end
91
91
  alias :filter_regex :filter_regexp
92
92
 
93
+ # adds operator filter one one variable
94
+ # variable is a Ruby symbol that appears in select/where clause, operator is a
95
+ # SPARQL operator (e.g. '>'), operand is a SPARQL value (e.g. 15)
93
96
  def filter_operator(variable, operator, operand)
94
97
  raise(ActiveRdfError, "variable must be a Symbol") unless variable.is_a? Symbol
95
98
 
96
- filter "(?#{variable} #{operator} #{operand}"
99
+ filter "?#{variable} #{operator} #{operand}"
97
100
  end
98
101
 
102
+ # filter variable on specified language tag, e.g. lang(:o, 'en')
103
+ def lang variable, tag
104
+ #filter "regex(lang(?#{variable}), '^#{tag}(-|$)', 'i')"
105
+ filter "lang(?#{variable}) = '#{tag}'"
106
+ #filter "langMatches(lang(?#{variable}), '#{tag}')"
107
+ end
99
108
 
100
109
  # adds reverse sorting predicates
101
110
  def reverse_sort *s
@@ -168,11 +177,11 @@ class Query
168
177
  # usage:: query.execute do |s,p,o| ... end
169
178
  def execute(options={:flatten => false}, &block)
170
179
  options = {:flatten => true} if options == :flatten
180
+ $activerdflog.debug("executing: #{self.to_sp}")
171
181
 
172
- $activerdflog.debug("query: #{self.to_sp}")
173
182
  if block_given?
174
- FederationManager.query(self) do |*clauses|
175
- block.call(*clauses)
183
+ for result in FederationManager.query(self, options)
184
+ yield result
176
185
  end
177
186
  else
178
187
  FederationManager.query(self, options)
@@ -1,16 +1,21 @@
1
1
  require 'active_rdf'
2
2
 
3
+ # TODO: support limit and offset
4
+
3
5
  # Translates abstract query into SPARQL that can be executed on SPARQL-compliant
4
6
  # data source.
5
7
  class Query2SPARQL
6
- def self.translate(query)
8
+ Engines_With_Keyword = [:yars2, :virtuoso]
9
+ def self.translate(query, engine=nil)
7
10
  str = ""
8
11
  if query.select?
9
12
  distinct = query.distinct? ? "DISTINCT " : ""
10
13
  select_clauses = query.select_clauses.collect{|s| construct_clause(s)}
11
14
 
12
15
  str << "SELECT #{distinct}#{select_clauses.join(' ')} "
13
- str << "WHERE { #{where_clauses(query)} #{filter_clauses(query)}}"
16
+ str << "WHERE { #{where_clauses(query)} #{filter_clauses(query)}} "
17
+ str << "LIMIT #{query.limits}" if query.limits
18
+ str << "OFFSET #{query.offsets}" if query.offsets
14
19
  elsif query.ask?
15
20
  str << "ASK { #{where_clauses(query)} }"
16
21
  end
@@ -20,22 +25,36 @@ class Query2SPARQL
20
25
 
21
26
  # concatenate filters in query
22
27
  def self.filter_clauses(query)
23
- "FILTER #{query.filter_clauses.join(" ")}" unless query.filter_clauses.empty?
28
+ "FILTER (#{query.filter_clauses.join(" && ")})" unless query.filter_clauses.empty?
24
29
  end
25
30
 
26
31
  # concatenate each where clause using space (e.g. 's p o')
27
32
  # and concatenate the clauses using dot, e.g. 's p o . s2 p2 o2 .'
28
33
  def self.where_clauses(query)
34
+ if query.keyword?
35
+ case sparql_engine
36
+ when :yars2
37
+ query.keywords.each do |term, keyword|
38
+ query.where(term, keyword_predicate, keyword)
39
+ end
40
+ when :virtuoso
41
+ query.keywords.each do |term, keyword|
42
+ query.filter("#{keyword_predicate}(#{construct_clause(term)}, '#{keyword}')")
43
+ end
44
+ end
45
+ end
46
+
29
47
  where_clauses = query.where_clauses.collect do |s,p,o,c|
30
48
  # ignore context parameter
31
49
  [s,p,o].collect {|term| construct_clause(term) }.join(' ')
32
50
  end
51
+
33
52
  "#{where_clauses.join('. ')} ."
34
53
  end
35
54
 
36
55
  def self.construct_clause(term)
37
56
  if term.respond_to? :uri
38
- '<' + term.uri + '>'
57
+ term.to_s
39
58
  else
40
59
  case term
41
60
  when Symbol
@@ -45,6 +64,40 @@ class Query2SPARQL
45
64
  end
46
65
  end
47
66
  end
67
+
68
+ def self.sparql_engine
69
+ sparql_adapters = ConnectionPool.read_adapters.select{|adp| adp.is_a? SparqlAdapter}
70
+ engines = sparql_adapters.collect {|adp| adp.engine}.uniq
71
+
72
+ unless engines.all?{|eng| Engines_With_Keyword.include?(eng)}
73
+ raise ActiveRdfError, "one or more of the specified SPARQL engines do not support keyword queries"
74
+ end
75
+
76
+ if engines.size > 1
77
+ raise ActiveRdfError, "we currently only support keyword queries for one type of SPARQL engine (e.g. Yars2 or Virtuoso) at a time"
78
+ end
79
+
80
+ return engines.first
81
+ end
82
+
83
+ def self.keyword_predicate
84
+ case sparql_engine
85
+ when :yars
86
+ RDFS::Resource.new("http://sw.deri.org/2004/06/yars#keyword")
87
+ when :virtuoso
88
+ VirtuosoBIF.new("bif:contains")
89
+ else
90
+ raise ActiveRdfError, "default SPARQL does not support keyword queries, remove the keyword clause or specify the type of SPARQL engine used"
91
+ end
92
+ end
48
93
 
49
- private_class_method :where_clauses, :construct_clause
94
+ private_class_method :where_clauses, :construct_clause, :keyword_predicate, :sparql_engine
95
+ end
96
+
97
+ # treat virtuoso built-ins slightly different: they are URIs but without <>
98
+ # surrounding them
99
+ class VirtuosoBIF < RDFS::Resource
100
+ def to_s
101
+ uri
102
+ end
50
103
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: activerdf
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.6.2
7
- date: 2007-08-03 00:00:00 +01:00
6
+ version: 1.6.3
7
+ date: 2007-08-09 00:00:00 +01:00
8
8
  summary: Offers object-oriented access to RDF (with adapters to several datastores).
9
9
  require_paths:
10
10
  - lib