activerdf 1.6.2 → 1.6.3

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.
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