amigo 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,56 @@
1
+ require 'hamster/immutable'
2
+ require 'hamster/list'
3
+
4
+ module Amigo
5
+
6
+ class Variables
7
+
8
+ include Hamster::Immutable
9
+
10
+ module ALL
11
+
12
+ class << self
13
+
14
+ def include?(name)
15
+ true
16
+ end
17
+
18
+ def to_sparql
19
+ "*"
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+
26
+ def self.new(*names)
27
+ return ALL if names.include?(:*)
28
+ super(names)
29
+ end
30
+
31
+ def initialize(names)
32
+ @names = Hamster.list(*names)
33
+ end
34
+
35
+ def include?(name)
36
+ @names.include?(name)
37
+ end
38
+
39
+ def to_sparql
40
+ @names.map { |name| "?#{name}" }.join(" ")
41
+ end
42
+
43
+ def eql?(other)
44
+ return true if other.equal?(self)
45
+ other.class.equal?(self.class) &&
46
+ @names.eql?(other.instance_variable_get(:@names))
47
+ end
48
+ alias_method :==, :eql?
49
+
50
+ def hash
51
+ @names.hash
52
+ end
53
+
54
+ end
55
+
56
+ end
@@ -0,0 +1,5 @@
1
+ module Amigo
2
+
3
+ VERSION = "0.1.0".freeze
4
+
5
+ end
@@ -0,0 +1,78 @@
1
+ require 'hamster/immutable'
2
+ require 'hamster/list'
3
+ require 'hamster/hash'
4
+ require 'hamster/set'
5
+
6
+ require 'amigo/variable'
7
+ require 'amigo/term'
8
+
9
+ module Amigo
10
+
11
+ class Where
12
+
13
+ include Hamster::Immutable
14
+
15
+ def initialize(subject, predicate, object)
16
+ @components = Hamster.list(
17
+ component(:subject, subject),
18
+ component(:predicate, predicate),
19
+ component(:object, object)
20
+ )
21
+ end
22
+
23
+ def ask(statements)
24
+ statements.any? { |statement| select?(statement) }
25
+ end
26
+
27
+ def select(statements)
28
+ statements.reduce(Hamster.set) do |result, statement|
29
+ next result unless select?(statement)
30
+ result.add(bind(statement, Hamster.hash))
31
+ end
32
+ end
33
+
34
+ def join(statements, rows)
35
+ rows.reduce(Hamster.set) do |result, row|
36
+ statements.reduce(result) do |result, statement|
37
+ next result unless join?(statement, row)
38
+ result.add(bind(statement, row))
39
+ end
40
+ end
41
+ end
42
+
43
+ def select?(statement)
44
+ @components.all? { |component| component.select?(statement) }
45
+ end
46
+
47
+ def join?(statement, row)
48
+ select?(statement) && @components.all? { |component| component.join?(statement, row) }
49
+ end
50
+
51
+ def bind(statement, row)
52
+ @components.reduce(row) { |row, component| component.bind(statement, row) }
53
+ end
54
+
55
+ def to_sparql
56
+ "#{@components.map(&:to_sparql).join(" ")} ."
57
+ end
58
+
59
+ def eql?(other)
60
+ return true if other.equal?(self)
61
+ other.class.equal?(self.class) &&
62
+ @components.eql?(other.instance_variable_get(:@components))
63
+ end
64
+ alias_method :==, :eql?
65
+
66
+ def hash
67
+ @components.hash
68
+ end
69
+
70
+ private
71
+
72
+ def component(component, value)
73
+ (Symbol === value ? Variable : Term).new(component, value)
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,184 @@
1
+ require 'spec_helper'
2
+
3
+ require 'hamster/set'
4
+ require 'hamster/hash'
5
+
6
+ require 'amigo/uri'
7
+ require 'amigo/triple'
8
+ require 'amigo/select'
9
+
10
+ module Amigo
11
+
12
+ describe Select do
13
+
14
+ describe "#execute" do
15
+
16
+ describe "with no where clauses" do
17
+
18
+ before do
19
+ @result = Select.new(:title).
20
+ execute(Hamster.set(Triple.new(URI.parse(URI.parse("ex_book:book1")), URI.parse(URI.parse("dc:title")), "SPARQL Tutorial")))
21
+ end
22
+
23
+ it "the result has a single solution" do
24
+ @result.size.should == 1
25
+ end
26
+
27
+ describe "the solution" do
28
+
29
+ before do
30
+ @solution = @result.first
31
+ end
32
+
33
+ it "binds no variables" do
34
+ @solution.include?(:title).should == false
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+
41
+ describe "when matching URIs" do
42
+
43
+ before do
44
+ @result = Select.new(:title).
45
+ where(URI.parse("ex_book:book1"), URI.parse("dc:title"), :title).
46
+ execute(Hamster.set(Triple.new(URI.parse("ex_book:book1"), URI.parse("dc:title"), "SPARQL Tutorial")))
47
+ end
48
+
49
+ it "returns the correct number of solutions" do
50
+ @result.size.should == 1
51
+ end
52
+
53
+ describe "each solution" do
54
+
55
+ before do
56
+ @solution = @result.first
57
+ end
58
+
59
+ it "correctly bind the selected variables" do
60
+ @solution[:title].should == "SPARQL Tutorial"
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ describe "when matching literals" do
68
+
69
+ before do
70
+ @result = Select.new(:v).
71
+ where(:v, :p, 42).
72
+ execute(Hamster.set(Triple.new(URI.parse("ns:y"), URI.parse("ns:p"), 42)))
73
+ end
74
+
75
+ it "returns the correct number of solutions" do
76
+ @result.size.should == 1
77
+ end
78
+
79
+ describe "each solution" do
80
+
81
+ before do
82
+ @solution = @result.first
83
+ end
84
+
85
+ it "correctly bind the the selected variables" do
86
+ @solution[:v].should == URI.parse("ns:y")
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ describe "with unselected variables" do
94
+
95
+ before do
96
+ @result = Select.new(:title).
97
+ where(:x, :y, :title).
98
+ execute(Hamster.set(Triple.new(URI.parse("ex_book:book1"), URI.parse("dc:title"), "SPARQL Tutorial")))
99
+ end
100
+
101
+ it "returns the correct number of solutions" do
102
+ @result.size.should == 1
103
+ end
104
+
105
+ describe "each solution" do
106
+
107
+ before do
108
+ @solution = @result.first
109
+ end
110
+
111
+ it "correctly bind the the selected variables" do
112
+ @solution[:title].should == "SPARQL Tutorial"
113
+ end
114
+
115
+ it "do not bind any non-selected variables" do
116
+ @solution.include?(:x).should == false
117
+ @solution.include?(:y).should == false
118
+ end
119
+
120
+ end
121
+
122
+ end
123
+
124
+ describe "with joins" do
125
+
126
+ before do
127
+ @result = Select.new(:name, :mbox).
128
+ where(:x, URI.parse("foaf:name"), :name).
129
+ where(:x, URI.parse("foaf:mbox"), :mbox).
130
+ execute(Hamster.set(
131
+ Triple.new("a", URI.parse("foaf:name"), "Johnny Lee Outlaw"),
132
+ Triple.new("a", URI.parse("foaf:mbox"), URI.parse("mailto:jlow@example.com")),
133
+ Triple.new("b", URI.parse("foaf:name"), "Peter Goodguy"),
134
+ Triple.new("b", URI.parse("foaf:mbox"), URI.parse("mailto:peter@example.com")),
135
+ Triple.new("c", URI.parse("foaf:mbox"), URI.parse("mailto:carol@example.com"))
136
+ )).
137
+ sort_by(&:name)
138
+ end
139
+
140
+ it "returns the correct number of solutions" do
141
+ @result.size == 2
142
+ end
143
+
144
+ describe "each solution" do
145
+
146
+ before do
147
+ @solution = @result.first
148
+ end
149
+
150
+ it "correctly bind the selected variables" do
151
+ @solution[:name].should == "Johnny Lee Outlaw"
152
+ @solution[:mbox].should == URI.parse("mailto:jlow@example.com")
153
+ end
154
+
155
+ it "does not bind any un-selected variables" do
156
+ @solution.include?(:x).should == false
157
+ end
158
+
159
+ end
160
+
161
+ describe "each solution" do
162
+
163
+ before do
164
+ @solution = @result.last
165
+ end
166
+
167
+ it "correctly bind the selected variables" do
168
+ @solution[:name].should == "Peter Goodguy"
169
+ @solution[:mbox].should == URI.parse("mailto:peter@example.com")
170
+ end
171
+
172
+ it "does not bind any un-selected variables" do
173
+ @solution.include?(:x).should == false
174
+ end
175
+
176
+ end
177
+
178
+ end
179
+
180
+ end
181
+
182
+ end
183
+
184
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ require 'amigo/select'
4
+
5
+ module Amigo
6
+
7
+ describe Select do
8
+
9
+ it "is immutable" do
10
+ Select.should include(Hamster::Immutable)
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ require 'amigo/select'
4
+
5
+ module Amigo
6
+
7
+ describe Select do
8
+
9
+ describe "#to_sparql" do
10
+
11
+ [
12
+ [Select.new(:*), "SELECT * WHERE {}"],
13
+ [Select.new(:*).where(:a, :b, :c), "SELECT * WHERE {?a ?b ?c .}"],
14
+ [Select.new(:a, :b, :c).where(:a, :b, :c), "SELECT ?a ?b ?c WHERE {?a ?b ?c .}"],
15
+ [Select.new(:a, :c).where(:a, :b, :c), "SELECT ?a ?c WHERE {?a ?b ?c .}"],
16
+ [Select.new(:*).where(:a, "bee", :c), "SELECT * WHERE {?a \"bee\" ?c .}"],
17
+ [Select.new(:a, :c).where(:a, "bee", :c), "SELECT ?a ?c WHERE {?a \"bee\" ?c .}"],
18
+ [Select.new(:*).where(:a, "bee", :c).where("dee", :e, "eff"), "SELECT * WHERE {?a \"bee\" ?c . \"dee\" ?e \"eff\" .}"],
19
+ ].each do |select, sparql|
20
+
21
+ describe "given #{select.inspect}" do
22
+
23
+ it "returns #{sparql.inspect}" do
24
+ select.to_sparql.should == sparql
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ require 'amigo/select'
4
+
5
+ module Amigo
6
+
7
+ describe Select do
8
+
9
+ describe "#to_sql" do
10
+
11
+ [
12
+ [Select.new(:*), "SELECT * FROM triples LIMIT 0"],
13
+ [Select.new(:*).where(:x, :y, :z), "SELECT subject x, predicate y, object z FROM triples"],
14
+ [Select.new(:x, :y, :z).where(:x, :y, :z), "SELECT subject x, predicate y, object z FROM triples"],
15
+ [Select.new(:x, :z).where(:x, :y, :z), "SELECT subject x, object z FROM triples"],
16
+ [Select.new(:*).where(:x, "bee", :z), "SELECT subject x, object z, FROM triples WHERE triples.predicate = 'bee'"],
17
+ [Select.new(:x, :z).where(:x, "bee", :z), "SELECT subject x, object z FROM triples WHERE triples.predicate = 'bee'"],
18
+ [Select.new(:*).where(:x, "bee", :z).where("dee", :y, "eff"), "SELECT a.subject x, a.object z, b.predicate y FROM triples a CROSS JOIN triples b WHERE a.predicate = 'bee' AND b.subject = 'dee' AND b.object = 'eff'"],
19
+ [Select.new(:x, :y).where(:x, "bee", :z).where(:z, :y, "see"), "SELECT a.subject x, b.predicate y FROM triples a JOIN triples b ON (a.object = b.subject) WHERE a.predicate = 'bee' AND b.object = 'see'"],
20
+ ].each do |select, sql|
21
+
22
+ describe "given #{select.inspect}" do
23
+
24
+ it "returns #{sql.inspect}" do
25
+ pending {
26
+ select.to_sql.should == sql
27
+ }
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ require 'amigo/store'
4
+
5
+ module Amigo
6
+
7
+ describe Store do
8
+
9
+ describe "#to_ntriples" do
10
+
11
+
12
+
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ require 'amigo/term'
4
+
5
+ module Amigo
6
+
7
+ describe Term do
8
+
9
+ describe "#to_sparql" do
10
+
11
+ [
12
+ [:subject, "a", "\"a\""],
13
+ [:predicate, "x", "\"x\""],
14
+ [:object, "flibble", "\"flibble\""]
15
+ ].each do |component, value, sparql|
16
+
17
+ describe "given #{name.inspect}" do
18
+
19
+ before do
20
+ @term = Term.new(component, value)
21
+ end
22
+
23
+ it "returns #{sparql.inspect}" do
24
+ @term.to_sparql.should == sparql
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end