diametric 0.1.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +28 -0
  3. data/Jarfile +20 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +264 -0
  6. data/Rakefile +49 -0
  7. data/bin/datomic-rest +33 -0
  8. data/bin/download-datomic +13 -0
  9. data/datomic_version.yml +4 -0
  10. data/diametric-java.gemspec +39 -0
  11. data/ext/diametric/DiametricCollection.java +147 -0
  12. data/ext/diametric/DiametricConnection.java +113 -0
  13. data/ext/diametric/DiametricDatabase.java +107 -0
  14. data/ext/diametric/DiametricEntity.java +90 -0
  15. data/ext/diametric/DiametricListenableFuture.java +47 -0
  16. data/ext/diametric/DiametricObject.java +66 -0
  17. data/ext/diametric/DiametricPeer.java +414 -0
  18. data/ext/diametric/DiametricService.java +102 -0
  19. data/ext/diametric/DiametricUUID.java +61 -0
  20. data/ext/diametric/DiametricUtils.java +183 -0
  21. data/lib/boolean_type.rb +3 -0
  22. data/lib/diametric.rb +42 -0
  23. data/lib/diametric/config.rb +54 -0
  24. data/lib/diametric/config/environment.rb +42 -0
  25. data/lib/diametric/entity.rb +659 -0
  26. data/lib/diametric/errors.rb +13 -0
  27. data/lib/diametric/generators/active_model.rb +42 -0
  28. data/lib/diametric/persistence.rb +48 -0
  29. data/lib/diametric/persistence/common.rb +82 -0
  30. data/lib/diametric/persistence/peer.rb +154 -0
  31. data/lib/diametric/persistence/rest.rb +107 -0
  32. data/lib/diametric/query.rb +259 -0
  33. data/lib/diametric/railtie.rb +52 -0
  34. data/lib/diametric/rest_service.rb +74 -0
  35. data/lib/diametric/service_base.rb +77 -0
  36. data/lib/diametric/transactor.rb +86 -0
  37. data/lib/diametric/version.rb +3 -0
  38. data/lib/diametric_service.jar +0 -0
  39. data/lib/tasks/create_schema.rb +27 -0
  40. data/lib/tasks/diametric_config.rb +45 -0
  41. data/lib/value_enums.rb +8 -0
  42. data/spec/conf_helper.rb +55 -0
  43. data/spec/config/free-transactor-template.properties +73 -0
  44. data/spec/config/logback.xml +59 -0
  45. data/spec/data/seattle-data0.dtm +452 -0
  46. data/spec/data/seattle-data1.dtm +326 -0
  47. data/spec/developer_create_sample.rb +39 -0
  48. data/spec/developer_query_spec.rb +120 -0
  49. data/spec/diametric/config_spec.rb +60 -0
  50. data/spec/diametric/entity_spec.rb +476 -0
  51. data/spec/diametric/peer_api_spec.rb +147 -0
  52. data/spec/diametric/persistence/peer_many2many_spec.rb +76 -0
  53. data/spec/diametric/persistence/peer_spec.rb +27 -0
  54. data/spec/diametric/persistence/rest_spec.rb +30 -0
  55. data/spec/diametric/persistence_spec.rb +59 -0
  56. data/spec/diametric/query_spec.rb +118 -0
  57. data/spec/diametric/rest_service_spec.rb +56 -0
  58. data/spec/diametric/transactor_spec.rb +68 -0
  59. data/spec/integration_spec.rb +107 -0
  60. data/spec/parent_child_sample.rb +42 -0
  61. data/spec/peer_integration_spec.rb +121 -0
  62. data/spec/peer_seattle_spec.rb +200 -0
  63. data/spec/rc2013_seattle_big.rb +82 -0
  64. data/spec/rc2013_seattle_small.rb +60 -0
  65. data/spec/rc2013_simple_sample.rb +72 -0
  66. data/spec/seattle_integration_spec.rb +106 -0
  67. data/spec/simple_validation_sample.rb +31 -0
  68. data/spec/spec_helper.rb +63 -0
  69. data/spec/support/entities.rb +157 -0
  70. data/spec/support/gen_entity_class.rb +9 -0
  71. data/spec/support/persistence_examples.rb +104 -0
  72. data/spec/test_version_file.yml +4 -0
  73. metadata +290 -0
@@ -0,0 +1,147 @@
1
+ require 'spec_helper'
2
+ require 'securerandom'
3
+
4
+ if is_jruby?
5
+ describe Diametric::Persistence::Peer, :jruby => true do
6
+ @db_name = "test-#{SecureRandom.uuid}"
7
+
8
+ it 'should create database' do
9
+ subject.create_database("datomic:mem://#{@db_name}").should be_true
10
+ end
11
+
12
+ context Diametric::Persistence::Peer do
13
+ it 'should connect to the database' do
14
+ subject.connect("datomic:mem://#{@db_name}").should be_true
15
+ end
16
+
17
+ it 'should get tempid' do
18
+ subject.tempid(":db.part/db").to_s.should match(/#db\/id\[:db.part\/db\s-\d+\]/)
19
+ subject.tempid(":db.part/user").to_s.should match(/#db\/id\[:db.part\/user\s-\d+\]/)
20
+ subject.tempid(":db.part/user", -1).to_s.should match(/#db\/id\[:db.part\/user\s-1\]/)
21
+ end
22
+
23
+ it "should return uuid from squuid" do
24
+ re = Regexp.new(/^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/)
25
+ subject.squuid.to_s.should match(re)
26
+ end
27
+
28
+ it "should return Fixnum from squuid_time_millis" do
29
+ du = Diametric::Persistence::UUID.new
30
+ subject.squuid_time_millis(du).class.should == Fixnum
31
+ end
32
+ end
33
+
34
+ context Diametric::Persistence::Connection do
35
+ @db_name = "test-#{SecureRandom.uuid}"
36
+ let(:connection) { Diametric::Persistence::Peer.connect("datomic:mem://#{@db_name}") }
37
+ let(:tempid) { Diametric::Persistence::Peer.tempid(":db.part/db") }
38
+ let(:tx_data) {
39
+ [{
40
+ ":db/id" => tempid,
41
+ ":db/ident" => ":person/name",
42
+ ":db/valueType" => ":db.type/string",
43
+ ":db/cardinality" => ":db.cardinality/one",
44
+ ":db/doc" => "A person's name",
45
+ ":db.install/_attribute" => ":db.part/db"
46
+ }]
47
+ }
48
+ let(:user_data) {
49
+ [{":db/id" => user_part_tempid, ":person/name" => "Alice"},
50
+ {":db/id" => user_part_tempid, ":person/name" => "Bob"},
51
+ {":db/id" => user_part_tempid, ":person/name" => "Chris"}]
52
+ }
53
+
54
+ it 'should transact schema' do
55
+ connection.transact(tx_data).class.should == Diametric::Persistence::ListenableFuture
56
+ end
57
+
58
+ it 'should get future object for schema' do
59
+ connection.transact(tx_data).get.should be_true
60
+ end
61
+
62
+ it 'should transact data' do
63
+ connection.transact(tx_data).get
64
+ connection.transact(user_data).get.should be_true
65
+ end
66
+
67
+ it 'should resolve tempid' do
68
+ tmp_tempid = user_part_tempid
69
+ connection.transact(tx_data).get
70
+ map = connection.transact([{":db/id" => tmp_tempid, ":person/name" => "Alice"}]).get
71
+ resolved_tempid = Diametric::Persistence::Peer.resolve_tempid(map, tmp_tempid)
72
+ resolved_tempid.should be_true
73
+ resolved_tempid.to_s.should match(/\d+/)
74
+ #puts "resolved_tempid: #{resolved_tempid}"
75
+ end
76
+ end
77
+
78
+ context 'Diametric query' do
79
+ before do
80
+ tx_data =
81
+ [{
82
+ ":db/id" => Diametric::Persistence::Peer.tempid(":db.part/db"),
83
+ ":db/ident" => ":person/name",
84
+ ":db/valueType" => ":db.type/string",
85
+ ":db/cardinality" => ":db.cardinality/one",
86
+ ":db/doc" => "A person's name",
87
+ ":db.install/_attribute" => ":db.part/db"
88
+ }]
89
+ user_data =
90
+ [{":db/id" => Diametric::Persistence::Peer.tempid(":db.part/user"), ":person/name" => "Alice"},
91
+ {":db/id" => Diametric::Persistence::Peer.tempid(":db.part/user"), ":person/name" => "Bob"},
92
+ {":db/id" => Diametric::Persistence::Peer.tempid(":db.part/user"), ":person/name" => "Chris"}]
93
+ @db_name = "test-#{SecureRandom.uuid}"
94
+ @connection = Diametric::Persistence::Peer.connect("datomic:mem://#{@db_name}")
95
+
96
+ @connection.transact(tx_data).get
97
+ @connection.transact(user_data).get
98
+ end
99
+
100
+ it 'should get ids from datomic' do
101
+ results = Diametric::Persistence::Peer.q("[:find ?c :where [?c :person/name]]", @connection.db)
102
+ results.class.should == Array
103
+ results.size.should be >= 3
104
+ #puts results.inspect
105
+ end
106
+
107
+ it 'should get names from datomic' do
108
+ results = Diametric::Persistence::Peer.q("[:find ?c ?name :where [?c :person/name ?name]]\
109
+ ", @connection.db)
110
+ results.flatten.should include("Alice")
111
+ results.flatten.should include("Bob")
112
+ results.flatten.should include("Chris")
113
+ #puts results.inspect
114
+ end
115
+
116
+ it 'should get entity by id' do
117
+ results = Diametric::Persistence::Peer.q("[:find ?c :where [?c :person/name]]",\
118
+ @connection.db)
119
+ id = results[0][0]
120
+ @connection.db.entity(id).should be_true
121
+ end
122
+
123
+ it 'should get keys from entity id' do
124
+ results = Diametric::Persistence::Peer.q("[:find ?c :where [?c :person/name]]",\
125
+ @connection.db)
126
+ id = results[0][0]
127
+ entity = @connection.db.entity(id)
128
+ entity.keys.should include(":person/name")
129
+ #puts entity.keys
130
+ end
131
+
132
+ it 'should get value from entity id' do
133
+ results = Diametric::Persistence::Peer.q("[:find ?c :where [?c :person/name]]",\
134
+ @connection.db)
135
+ id = results[0][0]
136
+ entity = @connection.db.entity(id)
137
+ value = entity.get(entity.keys[0])
138
+ value.should match(/Alice|Bob|Chris/)
139
+ #puts value
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ def user_part_tempid
146
+ Diametric::Persistence::Peer.tempid(":db.part/user")
147
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+ require 'diametric/persistence/peer'
3
+ require 'securerandom'
4
+
5
+ describe Diametric::Persistence::Peer, :jruby do
6
+ before do
7
+ db_uri = "datomic:mem://hello-#{SecureRandom.uuid}"
8
+ @conn = subject.connect(:uri => db_uri)
9
+ Author.create_schema(@conn)
10
+ Book.create_schema(@conn)
11
+ end
12
+ after do
13
+ @conn.release
14
+ end
15
+
16
+ it "should save one in caridinality many associations" do
17
+ author = Author.new(:name => "wilber", :books => [])
18
+ author.save
19
+ book = Book.new(:title => "Candy", :authors => [])
20
+ book.save
21
+ author.update(:books => [book])
22
+ result = Diametric::Persistence::Peer.q("[:find ?e ?name ?books :in $ :where [?e :author/name ?name] [?e :author/books ?books]]", @conn.db)
23
+ boo_dbid = result.first[2]
24
+ boo = Author.from_dbid_or_entity(boo_dbid, @conn)
25
+ boo.title.should == "Candy"
26
+ end
27
+
28
+ it "should save two in caridinality many associations" do
29
+ author = Author.new(:name => "wilber", :books => [])
30
+ author.save
31
+ book1 = Book.new(:title => "Honey", :authors => [])
32
+ book1.save
33
+ book2 = Book.new(:title => "Chips", :authors => [])
34
+ book2.save
35
+ author.update(:books => [book1, book2])
36
+ result = Diametric::Persistence::Peer.q("[:find ?e ?name ?books :in $ :where [?e :author/name ?name] [?e :author/books ?books]]", @conn.db)
37
+ result.size.should == 2
38
+ boo_dbid = result[0][2]
39
+ boo = Book.from_dbid_or_entity(boo_dbid, @conn)
40
+ boo.title.should match(/Honey|Chips/)
41
+ foo_dbid = result[1][2]
42
+ foo = Book.from_dbid_or_entity(boo_dbid, @conn)
43
+ foo.title.should match(/Honey|Chips/)
44
+ end
45
+
46
+ it "should save two in caridinality many associations" do
47
+ author1 = Author.new(:name => "Ms. Wilber", :books => [])
48
+ author1.save
49
+ author2 = Author.new(:name => "Mr. Smith", :books => [])
50
+ author2.save
51
+ book1 = Book.new(:title => "Pie", :authors => [])
52
+ book1.save
53
+ book2 = Book.new(:title => "Donuts", :authors => [])
54
+ book2.save
55
+ author1.update(:books => [book1, book2])
56
+ book1.update(:authors => [author1, author2])
57
+
58
+ result = Diametric::Persistence::Peer.q("[:find ?e :in $ [?name] :where [?e :author/name ?name]]", @conn.db, ["Ms. Wilber"])
59
+ result.size.should == 1
60
+ result.first.first.to_s.should == author1.dbid.to_s
61
+ a = Author.from_dbid_or_entity(result.first.first, @conn)
62
+ a.books.size.should == 2
63
+ a.books.each do |b|
64
+ Author.from_dbid_or_entity(b, @conn).title.should match(/Pie|Donuts/)
65
+ end
66
+
67
+ result = Diametric::Persistence::Peer.q("[:find ?e :in $ [?title] :where [?e :book/title ?title]]", @conn.db, ["Pie"])
68
+ result.size.should == 1
69
+ result.first.first.to_s.should == book1.dbid.to_s
70
+ b = Book.from_dbid_or_entity(result.first.first, @conn)
71
+ b.authors.size.should == 2
72
+ b.authors.each do |a|
73
+ Book.from_dbid_or_entity(a, @conn).name.should match(/Ms\.\sWilber|Mr\.\sSmith/)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+ require 'diametric/persistence/peer'
3
+ require 'securerandom'
4
+
5
+ describe Diametric::Persistence::Peer, :jruby do
6
+ before do
7
+ @db_uri = "datomic:mem://hello-#{SecureRandom.uuid}"
8
+ end
9
+
10
+ it "can connect to a Datomic database" do
11
+ connection = subject.connect(:uri => @db_uri)
12
+ connection.should be_a(Diametric::Persistence::Connection)
13
+ end
14
+
15
+ it_behaves_like "persistence API" do
16
+ let(:model_class) { Rat }
17
+
18
+ before do
19
+ @connection = Diametric::Persistence::Peer.connect(:uri => @db_uri)
20
+ Diametric::Persistence::Peer.create_schemas(@connection)
21
+ end
22
+
23
+ after do
24
+ @connection.release
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ require 'diametric/persistence/rest'
3
+ require 'securerandom'
4
+
5
+ describe Diametric::Persistence::REST, :integration do
6
+ before do
7
+ @db_uri = ENV['DATOMIC_URI'] || 'http://localhost:46291'
8
+ @storage = ENV['DATOMIC_STORAGE'] || 'free'
9
+ @dbname = ENV['DATOMIC_NAME'] || "test-#{SecureRandom.uuid}"
10
+ @connection_options = {
11
+ :uri => @db_uri,
12
+ :storage => @storage,
13
+ :database => @dbname
14
+ }
15
+ end
16
+
17
+ it "can connect to a Datomic database" do
18
+ subject.connect(@connection_options)
19
+ subject.connection.should be_a(Datomic::Client)
20
+ end
21
+
22
+ it_behaves_like "persistence API" do
23
+ let(:model_class) { Mouse }
24
+
25
+ before do
26
+ Diametric::Persistence::REST.connect(@connection_options)
27
+ Diametric::Persistence::REST.create_schemas
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ # Prevent CRuby from blowing up
4
+ module Diametric
5
+ module Persistence
6
+ module Peer
7
+ end
8
+ end
9
+ end
10
+
11
+ describe Diametric::Persistence do
12
+ let(:settings) { { :uri => 'http://example.com:9000' } }
13
+ let(:rest_class) { Diametric::Persistence::REST }
14
+
15
+ describe ".establish_base_connection" do
16
+ before { Diametric::Persistence.stub(:persistence_class => rest_class) }
17
+
18
+ it "connects" do
19
+ settings = { :uri => 'http://example.com:9000' }
20
+ rest_class.should_receive(:connect).with(settings)
21
+
22
+ Diametric::Persistence.establish_base_connection(settings)
23
+ end
24
+
25
+ it "records the base persistence class" do
26
+ rest_class.stub(:connect)
27
+ Diametric::Persistence.establish_base_connection(settings)
28
+ Diametric::Persistence.instance_variable_get(:"@_persistence_class").should == rest_class
29
+ end
30
+ end
31
+
32
+ describe ".included" do
33
+ before { Diametric::Persistence.stub(:persistence_class => rest_class) }
34
+
35
+ it "includes the recorded base persistence class" do
36
+ class FooEntity; end
37
+ FooEntity.should_receive(:send).with(:include, rest_class)
38
+ Diametric::Persistence.instance_variable_set(:"@_persistence_class", rest_class)
39
+
40
+ class FooEntity
41
+ include Diametric::Persistence
42
+ end
43
+ end
44
+ end
45
+
46
+ describe ".persistence_class" do
47
+ it "returns REST for REST-like options" do
48
+ klass = Diametric::Persistence.persistence_class("http://localhost:9000")
49
+ klass.should be Diametric::Persistence::REST
50
+ Diametric::Persistence.rest?.should == true
51
+ end
52
+
53
+ it "returns Peer for Peer-like options", :jruby do
54
+ klass = Diametric::Persistence.persistence_class("datomic:free://localhost:9000/sample")
55
+ klass.should be Diametric::Persistence::Peer
56
+ Diametric::Persistence.peer?.should == true
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ describe Diametric::Query do
4
+ let(:query) { Diametric::Query.new(Goat) }
5
+
6
+ describe "#where" do
7
+ it "is non-destructive" do
8
+ query.where(:age => 2)
9
+ query.conditions.should be_empty
10
+ end
11
+
12
+ it "raises when non-searchable conditions (id?) are passed"
13
+ end
14
+
15
+ describe "#filter" do
16
+ it "is non-destructive" do
17
+ query.filter(:<, :age, 2)
18
+ query.filters.should be_empty
19
+ end
20
+ end
21
+
22
+ describe "#each" do
23
+ it "collapses cardinality/many attribute results" do
24
+ model = gen_entity_class :person do
25
+ attribute :name, String
26
+ attribute :likes, String, :cardinality => :many
27
+ end
28
+ model.stub(:q => [[1, "Stu", "chocolate"], [1, "Stu", "vanilla"]])
29
+ model.should_receive(:from_query).with([1, "Stu", ["chocolate", "vanilla"]], nil, true)
30
+ Diametric::Query.new(model, nil, true).each {|x| x}
31
+ end
32
+ end
33
+
34
+ describe "#collapse_results" do
35
+ let (:model) do
36
+ gen_entity_class do
37
+ attribute :name, String
38
+ attribute :likes, String, :cardinality => :many
39
+ end
40
+ end
41
+ let(:query) { Diametric::Query.new(model, nil, true) }
42
+
43
+ context "with multiple results per entity" do
44
+ it "collapses cardinality/many attributes into lists" do
45
+ results = [[1, "Stu", "chocolate"], [1, "Stu", "vanilla"], [1, "Stu", "raspberry"]]
46
+ collapsed = query.send(:collapse_results, results).first
47
+ collapsed.should == [1, "Stu", ["chocolate", "vanilla", "raspberry"]]
48
+ end
49
+ end
50
+
51
+ context "with single result per entity" do
52
+ it "collapses cardinality/many attributes into lists" do
53
+ results = [[1, "Stu", "chocolate"]]
54
+ collapsed = query.send(:collapse_results, results).first
55
+ collapsed.should == [1, "Stu", ["chocolate"]]
56
+ end
57
+ end
58
+ end
59
+
60
+ describe "#all" do
61
+ it "returns set for values of cardinality/many" do
62
+ model = gen_entity_class :person do
63
+ attribute :name, String
64
+ attribute :likes, String, :cardinality => :many
65
+ end
66
+ model.stub(:q => [[1, "Stu", "chocolate"], [1, "Stu", "vanilla"]])
67
+ Diametric::Query.new(model, nil, true).all.each do |e|
68
+ e.name.should == "Stu"
69
+ e.likes.class.should == Set
70
+ e.likes.should include "chocolate"
71
+ e.likes.should include "vanilla"
72
+ end
73
+ end
74
+ end
75
+
76
+ describe "#data" do
77
+ it "should generate a query given no conditions or filters" do
78
+ query.data.should == [
79
+ [
80
+ :find, ~"?e", ~"?name", ~"?birthday",
81
+ :in, ~"\$",
82
+ :where,
83
+ [~"?e", :"goat/name", ~"?name"],
84
+ [~"?e", :"goat/birthday", ~"?birthday"]
85
+ ],
86
+ []
87
+ ]
88
+ end
89
+
90
+ it "should generate a query given a condition" do
91
+ query.where(:name => "Beans").data.should == [
92
+ [
93
+ :find, ~"?e", ~"?name", ~"?birthday",
94
+ :in, ~"\$", ~"?name",
95
+ :where,
96
+ [~"?e", :"goat/name", ~"?name"],
97
+ [~"?e", :"goat/birthday", ~"?birthday"]
98
+ ],
99
+ ["Beans"]
100
+ ]
101
+ end
102
+
103
+ it "should generate a query given multiple conditions" do
104
+ bday = DateTime.parse("2003-09-04 11:30 AM")
105
+
106
+ query.where(:name => "Beans", :birthday => bday).data.should == [
107
+ [
108
+ :find, ~"?e", ~"?name", ~"?birthday",
109
+ :in, ~"\$", ~"?name", ~"?birthday",
110
+ :where,
111
+ [~"?e", :"goat/name", ~"?name"],
112
+ [~"?e", :"goat/birthday", ~"?birthday"]
113
+ ],
114
+ ["Beans", bday]
115
+ ]
116
+ end
117
+ end
118
+ end