activerdf_net7 1.6.11
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +79 -0
- data/LICENSE +504 -0
- data/README.rdoc +34 -0
- data/activerdf-jena/CHANGELOG +14 -0
- data/activerdf-jena/LICENSE +504 -0
- data/activerdf-jena/README +57 -0
- data/activerdf-jena/Rakefile +87 -0
- data/activerdf-jena/TODO +18 -0
- data/activerdf-jena/VERSION +1 -0
- data/activerdf-jena/ext/antlr-2.7.5.jar +0 -0
- data/activerdf-jena/ext/arq-extra.jar +0 -0
- data/activerdf-jena/ext/arq.jar +0 -0
- data/activerdf-jena/ext/aterm-java-1.6.jar +0 -0
- data/activerdf-jena/ext/commons-logging-1.1.jar +0 -0
- data/activerdf-jena/ext/concurrent.jar +0 -0
- data/activerdf-jena/ext/icu4j_3_4.jar +0 -0
- data/activerdf-jena/ext/iri.jar +0 -0
- data/activerdf-jena/ext/jena.jar +0 -0
- data/activerdf-jena/ext/jenatest.jar +0 -0
- data/activerdf-jena/ext/json.jar +0 -0
- data/activerdf-jena/ext/junit.jar +0 -0
- data/activerdf-jena/ext/log4j-1.2.12.jar +0 -0
- data/activerdf-jena/ext/lucene-core-2.0.0.jar +0 -0
- data/activerdf-jena/ext/ng4j.jar +0 -0
- data/activerdf-jena/ext/pellet.jar +0 -0
- data/activerdf-jena/ext/relaxngDatatype.jar +0 -0
- data/activerdf-jena/ext/stax-api-1.0.jar +0 -0
- data/activerdf-jena/ext/wstx-asl-3.0.0.jar +0 -0
- data/activerdf-jena/ext/xercesImpl.jar +0 -0
- data/activerdf-jena/ext/xml-apis.jar +0 -0
- data/activerdf-jena/ext/xsdlib.jar +0 -0
- data/activerdf-jena/lib/activerdf_jena/init.rb +26 -0
- data/activerdf-jena/lib/activerdf_jena/jena.rb +59 -0
- data/activerdf-jena/lib/activerdf_jena/jena_adapter.rb +515 -0
- data/activerdf-jena/lib/activerdf_jena/lucene.rb +22 -0
- data/activerdf-jena/lib/activerdf_jena/ng4j.rb +50 -0
- data/activerdf-jena/lib/activerdf_jena/ng4j_adapter.rb +379 -0
- data/activerdf-jena/lib/activerdf_jena/pellet.rb +25 -0
- data/activerdf-jena/test/bnode_org_rss.rdf +793 -0
- data/activerdf-jena/test/eyal-foaf.nt +39 -0
- data/activerdf-jena/test/fun_with_bnodes.nt +2 -0
- data/activerdf-jena/test/s1.n3 +18 -0
- data/activerdf-jena/test/test_data.nt +32 -0
- data/activerdf-jena/test/test_jena_adapter.rb +451 -0
- data/activerdf-jena/test/test_ng4j_adapter.rb +354 -0
- data/activerdf-rdflite/CHANGELOG +31 -0
- data/activerdf-rdflite/LICENSE +504 -0
- data/activerdf-rdflite/README +16 -0
- data/activerdf-rdflite/Rakefile +73 -0
- data/activerdf-rdflite/VERSION +1 -0
- data/activerdf-rdflite/lib/activerdf_rdflite/fetching.rb +34 -0
- data/activerdf-rdflite/lib/activerdf_rdflite/init.rb +13 -0
- data/activerdf-rdflite/lib/activerdf_rdflite/rdflite.rb +582 -0
- data/activerdf-rdflite/lib/activerdf_rdflite/suggesting.rb +87 -0
- data/activerdf-rdflite/test/test_bnode_data.nt +5 -0
- data/activerdf-rdflite/test/test_data.nt +32 -0
- data/activerdf-rdflite/test/test_escaped_data.nt +2 -0
- data/activerdf-rdflite/test/test_fetching.rb +33 -0
- data/activerdf-rdflite/test/test_rdflite.rb +277 -0
- data/activerdf-redland/CHANGELOG +12 -0
- data/activerdf-redland/LICENSE +504 -0
- data/activerdf-redland/README +9 -0
- data/activerdf-redland/Rakefile +72 -0
- data/activerdf-redland/VERSION +1 -0
- data/activerdf-redland/lib/activerdf_redland/init.rb +10 -0
- data/activerdf-redland/lib/activerdf_redland/redland.rb +362 -0
- data/activerdf-redland/test/test_person_data.nt +42 -0
- data/activerdf-redland/test/test_redland_adapter.rb +242 -0
- data/activerdf-sesame/CHANGELOG +6 -0
- data/activerdf-sesame/LICENSE +10 -0
- data/activerdf-sesame/LICENSE-aduna +10 -0
- data/activerdf-sesame/LICENSE-lgpl +504 -0
- data/activerdf-sesame/README +33 -0
- data/activerdf-sesame/Rakefile +77 -0
- data/activerdf-sesame/VERSION +1 -0
- data/activerdf-sesame/ext/commons-codec-1.3.jar +0 -0
- data/activerdf-sesame/ext/commons-dbcp-1.2.2.jar +0 -0
- data/activerdf-sesame/ext/commons-httpclient-3.1.jar +0 -0
- data/activerdf-sesame/ext/commons-logging-1.1.1.jar +0 -0
- data/activerdf-sesame/ext/commons-pool-1.3.jar +0 -0
- data/activerdf-sesame/ext/commons-pool-1.5.2.jar +0 -0
- data/activerdf-sesame/ext/junit-3.8.2.jar +0 -0
- data/activerdf-sesame/ext/openrdf-sesame-2.0-onejar.jar +0 -0
- data/activerdf-sesame/ext/openrdf-sesame-2.3-pr1-onejar.jar +0 -0
- data/activerdf-sesame/ext/slf4j-api-1.4.3.jar +0 -0
- data/activerdf-sesame/ext/slf4j-nop-1.4.3.jar +0 -0
- data/activerdf-sesame/ext/wrapper-sesame2.jar +0 -0
- data/activerdf-sesame/java/build.number +3 -0
- data/activerdf-sesame/java/build.xml +313 -0
- data/activerdf-sesame/java/javadoc/allclasses-frame.html +31 -0
- data/activerdf-sesame/java/javadoc/allclasses-noframe.html +31 -0
- data/activerdf-sesame/java/javadoc/constant-values.html +146 -0
- data/activerdf-sesame/java/javadoc/deprecated-list.html +146 -0
- data/activerdf-sesame/java/javadoc/help-doc.html +223 -0
- data/activerdf-sesame/java/javadoc/index-files/index-1.html +150 -0
- data/activerdf-sesame/java/javadoc/index-files/index-10.html +145 -0
- data/activerdf-sesame/java/javadoc/index-files/index-2.html +157 -0
- data/activerdf-sesame/java/javadoc/index-files/index-3.html +146 -0
- data/activerdf-sesame/java/javadoc/index-files/index-4.html +145 -0
- data/activerdf-sesame/java/javadoc/index-files/index-5.html +145 -0
- data/activerdf-sesame/java/javadoc/index-files/index-6.html +142 -0
- data/activerdf-sesame/java/javadoc/index-files/index-7.html +145 -0
- data/activerdf-sesame/java/javadoc/index-files/index-8.html +152 -0
- data/activerdf-sesame/java/javadoc/index-files/index-9.html +146 -0
- data/activerdf-sesame/java/javadoc/index.html +36 -0
- data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/WrapperForSesame2.html +665 -0
- data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/class-use/WrapperForSesame2.html +144 -0
- data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/package-frame.html +32 -0
- data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/package-summary.html +157 -0
- data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/package-tree.html +150 -0
- data/activerdf-sesame/java/javadoc/org/activerdf/wrapper/sesame2/package-use.html +144 -0
- data/activerdf-sesame/java/javadoc/overview-summary.html +156 -0
- data/activerdf-sesame/java/javadoc/overview-tree.html +152 -0
- data/activerdf-sesame/java/javadoc/package-list +1 -0
- data/activerdf-sesame/java/javadoc/resources/inherit.gif +0 -0
- data/activerdf-sesame/java/javadoc/stylesheet.css +29 -0
- data/activerdf-sesame/java/lib/commons-codec-1.3.jar +0 -0
- data/activerdf-sesame/java/lib/commons-dbcp-1.2.2.jar +0 -0
- data/activerdf-sesame/java/lib/commons-httpclient-3.1.jar +0 -0
- data/activerdf-sesame/java/lib/commons-logging-1.1.1.jar +0 -0
- data/activerdf-sesame/java/lib/commons-pool-1.3.jar +0 -0
- data/activerdf-sesame/java/lib/commons-pool-1.5.2.jar +0 -0
- data/activerdf-sesame/java/lib/junit-3.8.2.jar +0 -0
- data/activerdf-sesame/java/lib/openrdf-sesame-2.0-onejar.jar +0 -0
- data/activerdf-sesame/java/lib/openrdf-sesame-2.3-pr1-onejar.jar +0 -0
- data/activerdf-sesame/java/lib/slf4j-api-1.4.3.jar +0 -0
- data/activerdf-sesame/java/lib/slf4j-nop-1.4.3.jar +0 -0
- data/activerdf-sesame/java/manifest.mf +3 -0
- data/activerdf-sesame/java/settings.xml +135 -0
- data/activerdf-sesame/java/src/org/activerdf/wrapper/sesame2/WrapperForSesame2.java +145 -0
- data/activerdf-sesame/java/test-src/org/activerdf/wrapper/sesame2/TestWrapperForSesame2.java +41 -0
- data/activerdf-sesame/lib/activerdf_sesame/init.rb +11 -0
- data/activerdf-sesame/lib/activerdf_sesame/sesame.rb +400 -0
- data/activerdf-sesame/test/eyal-foaf.nt +39 -0
- data/activerdf-sesame/test/eyal-foaf.rdf +65 -0
- data/activerdf-sesame/test/test_sesame_adapter.rb +341 -0
- data/activerdf-sparql/CHANGELOG +35 -0
- data/activerdf-sparql/LICENSE +504 -0
- data/activerdf-sparql/README +10 -0
- data/activerdf-sparql/Rakefile +78 -0
- data/activerdf-sparql/VERSION +1 -0
- data/activerdf-sparql/lib/activerdf_sparql/init.rb +10 -0
- data/activerdf-sparql/lib/activerdf_sparql/sparql.rb +212 -0
- data/activerdf-sparql/lib/activerdf_sparql/sparql_result_parser.rb +55 -0
- data/activerdf-sparql/test/test_sparql_adapter.rb +108 -0
- data/activerdf-yars/LICENSE +504 -0
- data/activerdf-yars/README +10 -0
- data/activerdf-yars/Rakefile +38 -0
- data/activerdf-yars/lib/activerdf_yars/init.rb +10 -0
- data/activerdf-yars/lib/activerdf_yars/jars2.rb +119 -0
- data/lib/active_rdf.rb +85 -0
- data/lib/active_rdf/directaccess/direct_access.rb +49 -0
- data/lib/active_rdf/federation/active_rdf_adapter.rb +47 -0
- data/lib/active_rdf/federation/connection_pool.rb +156 -0
- data/lib/active_rdf/federation/federation_manager.rb +112 -0
- data/lib/active_rdf/instance_exec.rb +13 -0
- data/lib/active_rdf/objectmanager/bnode.rb +7 -0
- data/lib/active_rdf/objectmanager/literal.rb +71 -0
- data/lib/active_rdf/objectmanager/namespace.rb +106 -0
- data/lib/active_rdf/objectmanager/object_manager.rb +119 -0
- data/lib/active_rdf/objectmanager/ordered_set.rb +116 -0
- data/lib/active_rdf/objectmanager/property_list.rb +76 -0
- data/lib/active_rdf/objectmanager/resource.rb +609 -0
- data/lib/active_rdf/objectmanager/resource_like.rb +28 -0
- data/lib/active_rdf/queryengine/ntriples_parser.rb +90 -0
- data/lib/active_rdf/queryengine/query.rb +245 -0
- data/lib/active_rdf/queryengine/query2jars2.rb +22 -0
- data/lib/active_rdf/queryengine/query2sparql.rb +139 -0
- data/lib/active_rdf_helpers.rb +30 -0
- data/lib/active_rdf_log.rb +100 -0
- data/test/common.rb +119 -0
- data/test/directaccess/test_direct_access.rb +64 -0
- data/test/federation/test_connection_pool.rb +86 -0
- data/test/federation/test_federation_manager.rb +145 -0
- data/test/objectmanager/test_literal.rb +52 -0
- data/test/objectmanager/test_namespace.rb +83 -0
- data/test/objectmanager/test_object_manager.rb +96 -0
- data/test/objectmanager/test_ordered_set.rb +110 -0
- data/test/objectmanager/test_resource_reading.rb +150 -0
- data/test/objectmanager/test_resource_writing.rb +39 -0
- data/test/objectmanager/test_talia_syntax.rb +68 -0
- data/test/queryengine/my_external_resource.rb +24 -0
- data/test/queryengine/test_external_resource_class.rb +49 -0
- data/test/queryengine/test_ntriples_parser.rb +71 -0
- data/test/queryengine/test_query.rb +55 -0
- data/test/queryengine/test_query2jars2.rb +51 -0
- data/test/queryengine/test_query2sparql.rb +76 -0
- data/test/queryengine/test_query_engine.rb +52 -0
- data/test/test_adapters.rb +58 -0
- 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
|