activerdf_net7 1.6.11
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 +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
|