amigo 0.1.0

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