diametric 0.1.1-java

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