activerdf_net7 1.6.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. data/CHANGELOG +79 -0
  2. data/LICENSE +504 -0
  3. data/README.rdoc +34 -0
  4. data/activerdf-jena/CHANGELOG +14 -0
  5. data/activerdf-jena/LICENSE +504 -0
  6. data/activerdf-jena/README +57 -0
  7. data/activerdf-jena/Rakefile +87 -0
  8. data/activerdf-jena/TODO +18 -0
  9. data/activerdf-jena/VERSION +1 -0
  10. data/activerdf-jena/ext/antlr-2.7.5.jar +0 -0
  11. data/activerdf-jena/ext/arq-extra.jar +0 -0
  12. data/activerdf-jena/ext/arq.jar +0 -0
  13. data/activerdf-jena/ext/aterm-java-1.6.jar +0 -0
  14. data/activerdf-jena/ext/commons-logging-1.1.jar +0 -0
  15. data/activerdf-jena/ext/concurrent.jar +0 -0
  16. data/activerdf-jena/ext/icu4j_3_4.jar +0 -0
  17. data/activerdf-jena/ext/iri.jar +0 -0
  18. data/activerdf-jena/ext/jena.jar +0 -0
  19. data/activerdf-jena/ext/jenatest.jar +0 -0
  20. data/activerdf-jena/ext/json.jar +0 -0
  21. data/activerdf-jena/ext/junit.jar +0 -0
  22. data/activerdf-jena/ext/log4j-1.2.12.jar +0 -0
  23. data/activerdf-jena/ext/lucene-core-2.0.0.jar +0 -0
  24. data/activerdf-jena/ext/ng4j.jar +0 -0
  25. data/activerdf-jena/ext/pellet.jar +0 -0
  26. data/activerdf-jena/ext/relaxngDatatype.jar +0 -0
  27. data/activerdf-jena/ext/stax-api-1.0.jar +0 -0
  28. data/activerdf-jena/ext/wstx-asl-3.0.0.jar +0 -0
  29. data/activerdf-jena/ext/xercesImpl.jar +0 -0
  30. data/activerdf-jena/ext/xml-apis.jar +0 -0
  31. data/activerdf-jena/ext/xsdlib.jar +0 -0
  32. data/activerdf-jena/lib/activerdf_jena/init.rb +26 -0
  33. data/activerdf-jena/lib/activerdf_jena/jena.rb +59 -0
  34. data/activerdf-jena/lib/activerdf_jena/jena_adapter.rb +515 -0
  35. data/activerdf-jena/lib/activerdf_jena/lucene.rb +22 -0
  36. data/activerdf-jena/lib/activerdf_jena/ng4j.rb +50 -0
  37. data/activerdf-jena/lib/activerdf_jena/ng4j_adapter.rb +379 -0
  38. data/activerdf-jena/lib/activerdf_jena/pellet.rb +25 -0
  39. data/activerdf-jena/test/bnode_org_rss.rdf +793 -0
  40. data/activerdf-jena/test/eyal-foaf.nt +39 -0
  41. data/activerdf-jena/test/fun_with_bnodes.nt +2 -0
  42. data/activerdf-jena/test/s1.n3 +18 -0
  43. data/activerdf-jena/test/test_data.nt +32 -0
  44. data/activerdf-jena/test/test_jena_adapter.rb +451 -0
  45. data/activerdf-jena/test/test_ng4j_adapter.rb +354 -0
  46. data/activerdf-rdflite/CHANGELOG +31 -0
  47. data/activerdf-rdflite/LICENSE +504 -0
  48. data/activerdf-rdflite/README +16 -0
  49. data/activerdf-rdflite/Rakefile +73 -0
  50. data/activerdf-rdflite/VERSION +1 -0
  51. data/activerdf-rdflite/lib/activerdf_rdflite/fetching.rb +34 -0
  52. data/activerdf-rdflite/lib/activerdf_rdflite/init.rb +13 -0
  53. data/activerdf-rdflite/lib/activerdf_rdflite/rdflite.rb +582 -0
  54. data/activerdf-rdflite/lib/activerdf_rdflite/suggesting.rb +87 -0
  55. data/activerdf-rdflite/test/test_bnode_data.nt +5 -0
  56. data/activerdf-rdflite/test/test_data.nt +32 -0
  57. data/activerdf-rdflite/test/test_escaped_data.nt +2 -0
  58. data/activerdf-rdflite/test/test_fetching.rb +33 -0
  59. data/activerdf-rdflite/test/test_rdflite.rb +277 -0
  60. data/activerdf-redland/CHANGELOG +12 -0
  61. data/activerdf-redland/LICENSE +504 -0
  62. data/activerdf-redland/README +9 -0
  63. data/activerdf-redland/Rakefile +72 -0
  64. data/activerdf-redland/VERSION +1 -0
  65. data/activerdf-redland/lib/activerdf_redland/init.rb +10 -0
  66. data/activerdf-redland/lib/activerdf_redland/redland.rb +362 -0
  67. data/activerdf-redland/test/test_person_data.nt +42 -0
  68. data/activerdf-redland/test/test_redland_adapter.rb +242 -0
  69. data/activerdf-sesame/CHANGELOG +6 -0
  70. data/activerdf-sesame/LICENSE +10 -0
  71. data/activerdf-sesame/LICENSE-aduna +10 -0
  72. data/activerdf-sesame/LICENSE-lgpl +504 -0
  73. data/activerdf-sesame/README +33 -0
  74. data/activerdf-sesame/Rakefile +77 -0
  75. data/activerdf-sesame/VERSION +1 -0
  76. data/activerdf-sesame/ext/commons-codec-1.3.jar +0 -0
  77. data/activerdf-sesame/ext/commons-dbcp-1.2.2.jar +0 -0
  78. data/activerdf-sesame/ext/commons-httpclient-3.1.jar +0 -0
  79. data/activerdf-sesame/ext/commons-logging-1.1.1.jar +0 -0
  80. data/activerdf-sesame/ext/commons-pool-1.3.jar +0 -0
  81. data/activerdf-sesame/ext/commons-pool-1.5.2.jar +0 -0
  82. data/activerdf-sesame/ext/junit-3.8.2.jar +0 -0
  83. data/activerdf-sesame/ext/openrdf-sesame-2.0-onejar.jar +0 -0
  84. data/activerdf-sesame/ext/openrdf-sesame-2.3-pr1-onejar.jar +0 -0
  85. data/activerdf-sesame/ext/slf4j-api-1.4.3.jar +0 -0
  86. data/activerdf-sesame/ext/slf4j-nop-1.4.3.jar +0 -0
  87. data/activerdf-sesame/ext/wrapper-sesame2.jar +0 -0
  88. data/activerdf-sesame/java/build.number +3 -0
  89. data/activerdf-sesame/java/build.xml +313 -0
  90. data/activerdf-sesame/java/javadoc/allclasses-frame.html +31 -0
  91. data/activerdf-sesame/java/javadoc/allclasses-noframe.html +31 -0
  92. data/activerdf-sesame/java/javadoc/constant-values.html +146 -0
  93. data/activerdf-sesame/java/javadoc/deprecated-list.html +146 -0
  94. data/activerdf-sesame/java/javadoc/help-doc.html +223 -0
  95. data/activerdf-sesame/java/javadoc/index-files/index-1.html +150 -0
  96. data/activerdf-sesame/java/javadoc/index-files/index-10.html +145 -0
  97. data/activerdf-sesame/java/javadoc/index-files/index-2.html +157 -0
  98. data/activerdf-sesame/java/javadoc/index-files/index-3.html +146 -0
  99. data/activerdf-sesame/java/javadoc/index-files/index-4.html +145 -0
  100. data/activerdf-sesame/java/javadoc/index-files/index-5.html +145 -0
  101. data/activerdf-sesame/java/javadoc/index-files/index-6.html +142 -0
  102. data/activerdf-sesame/java/javadoc/index-files/index-7.html +145 -0
  103. data/activerdf-sesame/java/javadoc/index-files/index-8.html +152 -0
  104. data/activerdf-sesame/java/javadoc/index-files/index-9.html +146 -0
  105. data/activerdf-sesame/java/javadoc/index.html +36 -0
  106. data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/WrapperForSesame2.html +665 -0
  107. data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/class-use/WrapperForSesame2.html +144 -0
  108. data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/package-frame.html +32 -0
  109. data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/package-summary.html +157 -0
  110. data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/package-tree.html +150 -0
  111. data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/package-use.html +144 -0
  112. data/activerdf-sesame/java/javadoc/overview-summary.html +156 -0
  113. data/activerdf-sesame/java/javadoc/overview-tree.html +152 -0
  114. data/activerdf-sesame/java/javadoc/package-list +1 -0
  115. data/activerdf-sesame/java/javadoc/resources/inherit.gif +0 -0
  116. data/activerdf-sesame/java/javadoc/stylesheet.css +29 -0
  117. data/activerdf-sesame/java/lib/commons-codec-1.3.jar +0 -0
  118. data/activerdf-sesame/java/lib/commons-dbcp-1.2.2.jar +0 -0
  119. data/activerdf-sesame/java/lib/commons-httpclient-3.1.jar +0 -0
  120. data/activerdf-sesame/java/lib/commons-logging-1.1.1.jar +0 -0
  121. data/activerdf-sesame/java/lib/commons-pool-1.3.jar +0 -0
  122. data/activerdf-sesame/java/lib/commons-pool-1.5.2.jar +0 -0
  123. data/activerdf-sesame/java/lib/junit-3.8.2.jar +0 -0
  124. data/activerdf-sesame/java/lib/openrdf-sesame-2.0-onejar.jar +0 -0
  125. data/activerdf-sesame/java/lib/openrdf-sesame-2.3-pr1-onejar.jar +0 -0
  126. data/activerdf-sesame/java/lib/slf4j-api-1.4.3.jar +0 -0
  127. data/activerdf-sesame/java/lib/slf4j-nop-1.4.3.jar +0 -0
  128. data/activerdf-sesame/java/manifest.mf +3 -0
  129. data/activerdf-sesame/java/settings.xml +135 -0
  130. data/activerdf-sesame/java/src/org/activerdf/wrapper/sesame2/WrapperForSesame2.java +145 -0
  131. data/activerdf-sesame/java/test-src/org/activerdf/wrapper/sesame2/TestWrapperForSesame2.java +41 -0
  132. data/activerdf-sesame/lib/activerdf_sesame/init.rb +11 -0
  133. data/activerdf-sesame/lib/activerdf_sesame/sesame.rb +400 -0
  134. data/activerdf-sesame/test/eyal-foaf.nt +39 -0
  135. data/activerdf-sesame/test/eyal-foaf.rdf +65 -0
  136. data/activerdf-sesame/test/test_sesame_adapter.rb +341 -0
  137. data/activerdf-sparql/CHANGELOG +35 -0
  138. data/activerdf-sparql/LICENSE +504 -0
  139. data/activerdf-sparql/README +10 -0
  140. data/activerdf-sparql/Rakefile +78 -0
  141. data/activerdf-sparql/VERSION +1 -0
  142. data/activerdf-sparql/lib/activerdf_sparql/init.rb +10 -0
  143. data/activerdf-sparql/lib/activerdf_sparql/sparql.rb +212 -0
  144. data/activerdf-sparql/lib/activerdf_sparql/sparql_result_parser.rb +55 -0
  145. data/activerdf-sparql/test/test_sparql_adapter.rb +108 -0
  146. data/activerdf-yars/LICENSE +504 -0
  147. data/activerdf-yars/README +10 -0
  148. data/activerdf-yars/Rakefile +38 -0
  149. data/activerdf-yars/lib/activerdf_yars/init.rb +10 -0
  150. data/activerdf-yars/lib/activerdf_yars/jars2.rb +119 -0
  151. data/lib/active_rdf.rb +85 -0
  152. data/lib/active_rdf/directaccess/direct_access.rb +49 -0
  153. data/lib/active_rdf/federation/active_rdf_adapter.rb +47 -0
  154. data/lib/active_rdf/federation/connection_pool.rb +156 -0
  155. data/lib/active_rdf/federation/federation_manager.rb +112 -0
  156. data/lib/active_rdf/instance_exec.rb +13 -0
  157. data/lib/active_rdf/objectmanager/bnode.rb +7 -0
  158. data/lib/active_rdf/objectmanager/literal.rb +71 -0
  159. data/lib/active_rdf/objectmanager/namespace.rb +106 -0
  160. data/lib/active_rdf/objectmanager/object_manager.rb +119 -0
  161. data/lib/active_rdf/objectmanager/ordered_set.rb +116 -0
  162. data/lib/active_rdf/objectmanager/property_list.rb +76 -0
  163. data/lib/active_rdf/objectmanager/resource.rb +609 -0
  164. data/lib/active_rdf/objectmanager/resource_like.rb +28 -0
  165. data/lib/active_rdf/queryengine/ntriples_parser.rb +90 -0
  166. data/lib/active_rdf/queryengine/query.rb +245 -0
  167. data/lib/active_rdf/queryengine/query2jars2.rb +22 -0
  168. data/lib/active_rdf/queryengine/query2sparql.rb +139 -0
  169. data/lib/active_rdf_helpers.rb +30 -0
  170. data/lib/active_rdf_log.rb +100 -0
  171. data/test/common.rb +119 -0
  172. data/test/directaccess/test_direct_access.rb +64 -0
  173. data/test/federation/test_connection_pool.rb +86 -0
  174. data/test/federation/test_federation_manager.rb +145 -0
  175. data/test/objectmanager/test_literal.rb +52 -0
  176. data/test/objectmanager/test_namespace.rb +83 -0
  177. data/test/objectmanager/test_object_manager.rb +96 -0
  178. data/test/objectmanager/test_ordered_set.rb +110 -0
  179. data/test/objectmanager/test_resource_reading.rb +150 -0
  180. data/test/objectmanager/test_resource_writing.rb +39 -0
  181. data/test/objectmanager/test_talia_syntax.rb +68 -0
  182. data/test/queryengine/my_external_resource.rb +24 -0
  183. data/test/queryengine/test_external_resource_class.rb +49 -0
  184. data/test/queryengine/test_ntriples_parser.rb +71 -0
  185. data/test/queryengine/test_query.rb +55 -0
  186. data/test/queryengine/test_query2jars2.rb +51 -0
  187. data/test/queryengine/test_query2sparql.rb +76 -0
  188. data/test/queryengine/test_query_engine.rb +52 -0
  189. data/test/test_adapters.rb +58 -0
  190. metadata +266 -0
@@ -0,0 +1,28 @@
1
+ module RDFS
2
+
3
+ # Helper Module that contains same additional methods that
4
+ # are expected from classes that want to behave like
5
+ # RDFS::Resource.
6
+ #
7
+ # The module expects that the including class has an uri
8
+ # method or property.
9
+ module ResourceLike
10
+
11
+ # returns uri of resource, can be overridden in subclasses
12
+ def to_s
13
+ "<#{uri}>"
14
+ end
15
+
16
+ # overriding sort based on uri
17
+ def <=>(other)
18
+ uri <=> other.uri
19
+ end
20
+
21
+ # NTriple representation of element
22
+ def to_ntriple
23
+ "<#{uri}>"
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,90 @@
1
+ # Author:: Eyal Oren
2
+ # Copyright:: (c) 2005-2006 Eyal Oren
3
+ # License:: LGPL
4
+ # require 'active_rdf'
5
+ require 'uuidtools'
6
+ require 'strscan'
7
+
8
+ # ntriples parser
9
+ class NTriplesParser
10
+ def self.parse_node(input, resource_class = RDFS::Resource)
11
+ case input
12
+ when MatchBNode
13
+ resource_class.new("http://www.activerdf.org/bnode/#{UUID.random_create}/#$1")
14
+ when MatchLiteral
15
+ value = fix_unicode($1)
16
+ if $2
17
+ Literal.typed(value, resource_class.new($2))
18
+ else
19
+ value
20
+ end
21
+ when MatchResource
22
+ resource_class.new($1)
23
+ else
24
+ nil
25
+ end
26
+ end
27
+
28
+ # parses an input string of ntriples and returns a nested array of [s, p, o]
29
+ # (which are in turn ActiveRDF objects)
30
+ def self.parse(input)
31
+ # need unique identifier for this batch of triples (to detect occurence of
32
+ # same bnodes _:#1
33
+ uuid = UUID.random_create.to_s
34
+
35
+ input.collect do |triple|
36
+ nodes = []
37
+ scanner = StringScanner.new(triple)
38
+ scanner.skip(/\s+/)
39
+ while not scanner.eos?
40
+ nodes << scanner.scan(MatchNode)
41
+ scanner.skip(/\s+/)
42
+ scanner.terminate if nodes.size == 3
43
+ end
44
+
45
+ # handle bnodes if necessary (bnodes need to have uri generated)
46
+ subject = case nodes[0]
47
+ when MatchBNode
48
+ RDFS::Resource.new("http://www.activerdf.org/bnode/#{uuid}/#$1")
49
+ when MatchResource
50
+ RDFS::Resource.new($1)
51
+ end
52
+
53
+ predicate = case nodes[1]
54
+ when MatchResource
55
+ RDFS::Resource.new($1)
56
+ end
57
+
58
+ # handle bnodes and literals if necessary (literals need unicode fixing)
59
+ object = case nodes[2]
60
+ when MatchBNode
61
+ RDFS::Resource.new("http://www.activerdf.org/bnode/#{uuid}/#$1")
62
+ when MatchLiteral
63
+ value = fix_unicode($1)
64
+ if $2
65
+ Literal.typed(value, RDFS::Resource.new($2))
66
+ else
67
+ value
68
+ end
69
+ when MatchResource
70
+ RDFS::Resource.new($1)
71
+ end
72
+
73
+ # collect s, p, o into array to be returned
74
+ [subject, predicate, object]
75
+ end
76
+ end
77
+
78
+ private
79
+ # constants for extracting resources/literals from sql results
80
+ MatchNode = Regexp.union(/"(?:\\"|[^"])*"(?:\^\^\S+)?/,/_:\S*/,/<[^>]*>/)
81
+ MatchBNode = /_:(\S*)/
82
+ MatchResource = /<([^>]*)>/
83
+ MatchLiteral = /"((?:\\"|[^"])*)"(?:\^\^<(\S+)>)?/
84
+
85
+ # fixes unicode characters in literals (because we parse them wrongly somehow)
86
+ def self.fix_unicode(str)
87
+ tmp = str.gsub(/\\\u([0-9a-fA-F]{4,4})/u){ "U+#$1" }
88
+ tmp.gsub(/U\+([0-9a-fA-F]{4,4})/u){["#$1".hex ].pack('U*')}
89
+ end
90
+ end
@@ -0,0 +1,245 @@
1
+ # require 'active_rdf'
2
+ require 'federation/federation_manager'
3
+ require 'queryengine/query2sparql'
4
+
5
+ require 'rubygems'
6
+
7
+ # Represents a query on a datasource, abstract representation of SPARQL
8
+ # features. Query is passed to federation manager or adapter for execution on
9
+ # data source. In all clauses symbols represent variables:
10
+ # Query.new.select(:s).where(:s,:p,:o).
11
+ class Query
12
+ attr_reader :select_clauses, :where_clauses, :sort_clauses, :keywords, :limits, :offsets, :reverse_sort_clauses, :filter_clauses
13
+
14
+ bool_accessor :distinct, :ask, :select, :count, :keyword, :reasoning
15
+
16
+ # Creates a new query. You may pass a different class that is used for "resource"
17
+ # type objects instead of RDFS::Resource
18
+ def initialize(resource_type = RDFS::Resource)
19
+ @distinct = false
20
+ @limits = nil
21
+ @offsets = nil
22
+ @select_clauses = []
23
+ @where_clauses = []
24
+ @sort_clauses = []
25
+ @filter_clauses = []
26
+ @keywords = {}
27
+ @reasoning = true
28
+ @reverse_sort_clauses = []
29
+ set_resource_class(resource_type)
30
+ end
31
+
32
+ # This returns the class that is be used for resources, by default this
33
+ # is RDFS::Resource
34
+ def resource_class
35
+ @resource_class ||= RDFS::Resource
36
+ end
37
+
38
+ # Sets the resource_class. Any class may be used, however it is required
39
+ # that it can be created using the uri of the resource as it's only
40
+ # parameter and that it has an 'uri' property
41
+ def set_resource_class(resource_class)
42
+ raise(ArgumentError, "resource_class must be a class") unless(resource_class.is_a?(Class))
43
+
44
+ test = resource_class.new("http://uri")
45
+ raise(ArgumentError, "Must have an uri property") unless(test.respond_to?(:uri))
46
+ @resource_class = resource_class
47
+ end
48
+
49
+ # Clears the select clauses
50
+ def clear_select
51
+ ActiveRdfLogger::log_debug "Cleared select clause"
52
+ @select_clauses = []
53
+ @distinct = false
54
+ end
55
+
56
+ # Adds variables to select clause
57
+ def select *s
58
+ @select = true
59
+ s.each do |e|
60
+ @select_clauses << parametrise(e)
61
+ end
62
+ # removing duplicate select clauses
63
+ @select_clauses.uniq!
64
+ self
65
+ end
66
+
67
+ # Adds variables to ask clause (see SPARQL specification)
68
+ def ask
69
+ @ask = true
70
+ self
71
+ end
72
+
73
+ # Adds variables to select distinct clause
74
+ def distinct *s
75
+ @distinct = true
76
+ select(*s)
77
+ end
78
+ alias_method :select_distinct, :distinct
79
+
80
+ # Adds variables to count clause
81
+ def count *s
82
+ @count = true
83
+ select(*s)
84
+ end
85
+
86
+ # Adds sort predicates
87
+ def sort *s
88
+ # add sort clauses without duplicates
89
+ s.each { |clause| @sort_clauses << parametrise(clause) }
90
+ @sort_clauses.uniq!
91
+
92
+ self
93
+ end
94
+
95
+ # adds one or more generic filters
96
+ # NOTE: you have to use SPARQL syntax for variables, eg. regex(?s, 'abc')
97
+ def filter *s
98
+ # add filter clauses
99
+ @filter_clauses << s
100
+ @filter_clauses.uniq!
101
+
102
+ self
103
+ end
104
+
105
+ # adds regular expression filter on one variable
106
+ # variable is Ruby symbol that appears in select/where clause, regex is Ruby
107
+ # regular expression
108
+ def filter_regexp(variable, regexp)
109
+ raise(ActiveRdfError, "variable must be a symbol") unless variable.is_a? Symbol
110
+ raise(ActiveRdfError, "regexp must be a ruby regexp") unless regexp.is_a? Regexp
111
+
112
+ filter "regex(str(?#{variable}), #{regexp.inspect.gsub('/','"')})"
113
+ end
114
+ alias :filter_regex :filter_regexp
115
+
116
+ # adds operator filter one one variable
117
+ # variable is a Ruby symbol that appears in select/where clause, operator is a
118
+ # SPARQL operator (e.g. '>'), operand is a SPARQL value (e.g. 15)
119
+ def filter_operator(variable, operator, operand)
120
+ raise(ActiveRdfError, "variable must be a Symbol") unless variable.is_a? Symbol
121
+
122
+ filter "?#{variable} #{operator} #{operand}"
123
+ end
124
+
125
+ # filter variable on specified language tag, e.g. lang(:o, 'en')
126
+ # optionally matches exactly on language dialect, otherwise only
127
+ # language-specifier is considered
128
+ def lang variable, tag, exact=false
129
+ if exact
130
+ filter "lang(?#{variable} = '#{tag}'"
131
+ else
132
+ filter "regex(lang(?#{variable}), '^#{tag.gsub(/_.*/,'')}$')"
133
+ end
134
+ end
135
+
136
+ # adds reverse sorting predicates
137
+ def reverse_sort *s
138
+ # add sort clauses without duplicates
139
+ s.each { |clause| @reverse_sort_clauses << parametrise(clause) }
140
+ @reverse_sort_clauses.uniq!
141
+
142
+ self
143
+ end
144
+
145
+ # Adds limit clause (maximum number of results to return)
146
+ def limit(i)
147
+ @limits = i.to_i
148
+ self
149
+ end
150
+
151
+ # Add offset clause (ignore first n results)
152
+ def offset(i)
153
+ @offsets = i.to_i
154
+ self
155
+ end
156
+
157
+ # Adds where clauses (s,p,o) where each constituent is either variable (:s) or
158
+ # an RDFS::Resource (or equivalent class). Keyword queries are specified with the special :keyword
159
+ # symbol: Query.new.select(:s).where(:s, :keyword, 'eyal')
160
+ def where s,p,o,c=nil
161
+ case p
162
+ when :keyword
163
+ # treat keywords in where-clauses specially
164
+ keyword_where(s,o)
165
+ else
166
+ # remove duplicate variable bindings, e.g.
167
+ # where(:s,type,:o).where(:s,type,:oo) we should remove the second clause,
168
+ # since it doesn't add anything to the query and confuses the query
169
+ # generator.
170
+ # if you construct this query manually, you shouldn't! if your select
171
+ # variable happens to be in one of the removed clauses: tough luck.
172
+
173
+ unless (s.respond_to?(:uri) or s.is_a?(Symbol)) and (!s.is_a?(RDFS::BNode))
174
+ raise(ActiveRdfError, "Cannot add a where clause with s #{s}: s must be a resource or a variable")
175
+ end
176
+ unless (p.respond_to?(:uri) or p.is_a?(Symbol)) and (!s.is_a?(RDFS::BNode))
177
+ raise(ActiveRdfError, "Cannot add a where clause with p #{p}: p must be a resource or a variable, is a #{p.class.name}")
178
+ end
179
+ raise(ActiveRdfErrror, "Cannot add a where clause where o is a blank node") if(o.is_a?(RDFS::BNode))
180
+
181
+ @where_clauses << [s,p,o,c].collect{|arg| parametrise(arg)}
182
+ end
183
+ self
184
+ end
185
+
186
+ # Adds keyword constraint to the query. You can use all Ferret query syntax in
187
+ # the constraint (e.g. keyword_where(:s,'eyal|benjamin')
188
+ def keyword_where s,o
189
+ @keyword = true
190
+ s = parametrise(s)
191
+ if @keywords.include?(s)
192
+ @keywords[s] = @keywords[s] + ' ' + o
193
+ else
194
+ @keywords[s] = o
195
+ end
196
+ self
197
+ end
198
+
199
+ # Executes query on data sources. Either returns result as array
200
+ # (flattened into single value unless specified otherwise)
201
+ # or executes a block (number of block variables should be
202
+ # same as number of select variables)
203
+ #
204
+ # usage:: results = query.execute
205
+ # usage:: query.execute do |s,p,o| ... end
206
+ def execute(options={:flatten => false}, &block)
207
+ options = {:flatten => true} if options == :flatten
208
+
209
+ if block_given?
210
+ for result in FederationManager.query(self, options)
211
+ yield result
212
+ end
213
+ else
214
+ FederationManager.query(self, options)
215
+ end
216
+ end
217
+
218
+ # Returns query string depending on adapter (e.g. SPARQL, N3QL, etc.)
219
+ def to_s
220
+ if ConnectionPool.read_adapters.empty?
221
+ inspect
222
+ else
223
+ ConnectionPool.read_adapters.first.translate(self)
224
+ end
225
+ end
226
+
227
+ # Returns SPARQL serialisation of query
228
+ def to_sp
229
+ Query2SPARQL.translate(self)
230
+ end
231
+
232
+ private
233
+ def parametrise s
234
+ case s
235
+ when Symbol, Literal, Class, nil
236
+ s
237
+ else
238
+ if(s.respond_to?(:uri))
239
+ s
240
+ else
241
+ '"' + s.to_s + '"'
242
+ end
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,22 @@
1
+ # require 'active_rdf'
2
+
3
+ # Translates abstract query into jars2 query.
4
+ # (ignores ASK queries)
5
+ class Query2Jars2
6
+ def self.translate(query)
7
+ str = ""
8
+ if query.select?
9
+ # concatenate each where clause using space: s p o
10
+ # and then concatenate the clauses using dot: s p o . s2 p2 o2 .
11
+ str << "#{query.where_clauses.collect{|w| w.collect{|w| '?'+w.to_s}.join(' ')}.join(" .\n")} ."
12
+ # TODO: should we maybe reverse the order on the where_clauses? it depends
13
+ # on Andreas' answer of the best order to give to jars2. Users would
14
+ # probably put the most specific stuff first, and join to get the
15
+ # interesting information. Maybe we should not touch it and let the user
16
+ # figure it out.
17
+ end
18
+
19
+ ActiveRdfLogger::log_debug(self) { "Query2Jars2: translated #{query} to #{str}" }
20
+ return str
21
+ end
22
+ end
@@ -0,0 +1,139 @@
1
+ # require 'active_rdf'
2
+
3
+ # TODO: support limit and offset
4
+
5
+ # Translates abstract query into SPARQL that can be executed on SPARQL-compliant
6
+ # data source.
7
+ class Query2SPARQL
8
+ Engines_With_Keyword = [:yars2, :virtuoso]
9
+ def self.translate(query, engine=nil)
10
+ str = ""
11
+ if query.select?
12
+ distinct = query.distinct? ? "DISTINCT " : ""
13
+ select_clauses = query.select_clauses.collect{|s| construct_clause(s)}
14
+
15
+ str << "SELECT #{distinct}#{select_clauses.join(' ')} "
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
19
+ if (!query.sort_clauses.empty? || !query.reverse_sort_clauses.empty?)
20
+ str << "ORDER BY "
21
+ str << "#{sort_clauses(query)} " if !query.sort_clauses.empty?
22
+ str << "#{reverse_sort_clauses(query)} " if !query.reverse_sort_clauses.empty?
23
+ end
24
+ elsif query.ask?
25
+ str << "ASK { #{where_clauses(query)} } "
26
+ end
27
+
28
+ return str
29
+ end
30
+
31
+ # concatenate each from clause using space
32
+ def self.from_clauses(query)
33
+ params = []
34
+ # construct single context clauses if context is present
35
+ query.where_clauses.each {|s,p,o,c|
36
+ params << "FROM #{construct_clause(c)}" unless c.nil?
37
+ }
38
+
39
+ # return FROM sintax or "" if no context is speficied
40
+ if (params.empty?)
41
+ ""
42
+ else
43
+ "#{params.join(' ')} "
44
+ end
45
+ end
46
+
47
+ # concatenate filters in query
48
+ def self.filter_clauses(query)
49
+ "FILTER (#{query.filter_clauses.join(" && ")})" unless query.filter_clauses.empty?
50
+ end
51
+
52
+ def self.sort_clauses(query)
53
+ sort_clauses = query.sort_clauses.collect do |term|
54
+ "ASC(#{construct_clause(term)})"
55
+ end
56
+
57
+ sort_clauses.join(' ')
58
+ end
59
+
60
+ def self.reverse_sort_clauses(query)
61
+ reverse_sort_clauses = query.reverse_sort_clauses.collect do |term|
62
+ "DESC(#{construct_clause(term)})"
63
+ end
64
+
65
+ "#{reverse_sort_clauses.join(' ')}"
66
+ end
67
+
68
+ # concatenate each where clause using space (e.g. 's p o')
69
+ # and concatenate the clauses using dot, e.g. 's p o . s2 p2 o2 .'
70
+ def self.where_clauses(query)
71
+ if query.keyword?
72
+ case sparql_engine
73
+ when :yars2
74
+ query.keywords.each do |term, keyword|
75
+ query.where(term, keyword_predicate, keyword)
76
+ end
77
+ when :virtuoso
78
+ query.keywords.each do |term, keyword|
79
+ query.filter("#{keyword_predicate}(#{construct_clause(term)}, '#{keyword}')")
80
+ end
81
+ end
82
+ end
83
+
84
+ where_clauses = query.where_clauses.collect do |s,p,o,c|
85
+ # does there where clause use a context ?
86
+ if c.nil?
87
+ [s,p,o].collect {|term| construct_clause(term) }.join(' ')
88
+ else
89
+ "GRAPH #{construct_clause(c)} { #{construct_clause(s)} #{construct_clause(p)} #{construct_clause(o)} }"
90
+ end
91
+ end
92
+
93
+ "#{where_clauses.join(' . ')} ."
94
+ end
95
+
96
+ def self.construct_clause(term)
97
+ if term.is_a?(Symbol)
98
+ "?#{term}"
99
+ else
100
+ term.to_ntriple
101
+ end
102
+ end
103
+
104
+ def self.sparql_engine
105
+ sparql_adapters = ConnectionPool.read_adapters.select{|adp| adp.is_a? SparqlAdapter}
106
+ engines = sparql_adapters.collect {|adp| adp.engine}.uniq
107
+
108
+ unless engines.all?{|eng| Engines_With_Keyword.include?(eng)}
109
+ raise ActiveRdfError, "one or more of the specified SPARQL engines do not support keyword queries"
110
+ end
111
+
112
+ if engines.size > 1
113
+ raise ActiveRdfError, "we currently only support keyword queries for one type of SPARQL engine (e.g. Yars2 or Virtuoso) at a time"
114
+ end
115
+
116
+ return engines.first
117
+ end
118
+
119
+ def self.keyword_predicate
120
+ case sparql_engine
121
+ when :yars, :yars2
122
+ RDFS::Resource.new("http://sw.deri.org/2004/06/yars#keyword")
123
+ when :virtuoso
124
+ VirtuosoBIF.new("bif:contains")
125
+ else
126
+ raise ActiveRdfError, "default SPARQL does not support keyword queries, remove the keyword clause or specify the type of SPARQL engine used"
127
+ end
128
+ end
129
+
130
+ private_class_method :where_clauses, :construct_clause, :keyword_predicate, :sparql_engine
131
+ end
132
+
133
+ # treat virtuoso built-ins slightly different: they are URIs but without <>
134
+ # surrounding them
135
+ class VirtuosoBIF < RDFS::Resource
136
+ def to_s
137
+ uri
138
+ end
139
+ end