ObjectModel 0.3.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.
Files changed (90) hide show
  1. data/README +849 -0
  2. data/lib/ObjectModel.res/config.yaml +5 -0
  3. data/lib/ObjectModel/AnEntity/BackReferences.rb +113 -0
  4. data/lib/ObjectModel/AnEntity/Bag.rb +129 -0
  5. data/lib/ObjectModel/AnEntity/BagCopy.rb +29 -0
  6. data/lib/ObjectModel/AnEntity/ChildrenBag.rb +10 -0
  7. data/lib/ObjectModel/AnEntity/EntityCopy.rb +38 -0
  8. data/lib/ObjectModel/AnEntity/EntityType.rb +408 -0
  9. data/lib/ObjectModel/AnEntity/ReferencesBag.rb +10 -0
  10. data/lib/ObjectModel/AnEntity/entity_cm.rb +108 -0
  11. data/lib/ObjectModel/Entity.rb +278 -0
  12. data/lib/ObjectModel/Errors/LoadError.rb +3 -0
  13. data/lib/ObjectModel/Errors/NoTransactionError.rb +3 -0
  14. data/lib/ObjectModel/Errors/NotFoundError.rb +2 -0
  15. data/lib/ObjectModel/Errors/OutdatedError.rb +8 -0
  16. data/lib/ObjectModel/Errors/ValidationError.rb +3 -0
  17. data/lib/ObjectModel/Indexes/HashIndex.rb +64 -0
  18. data/lib/ObjectModel/Indexes/IndexStorage.rb +64 -0
  19. data/lib/ObjectModel/Indexes/Manager.rb +72 -0
  20. data/lib/ObjectModel/Metadata.rb +34 -0
  21. data/lib/ObjectModel/Metadata.res/after_event_types.rb +25 -0
  22. data/lib/ObjectModel/Metadata.res/attribute_types_shortcuts.rb +10 -0
  23. data/lib/ObjectModel/Metadata.res/before_event_types.rb +25 -0
  24. data/lib/ObjectModel/Metadata.res/child_types_shortcuts.rb +4 -0
  25. data/lib/ObjectModel/Metadata.res/metadata_checks.rb +9 -0
  26. data/lib/ObjectModel/Metadata.res/reference_types_shortcuts.rb +4 -0
  27. data/lib/ObjectModel/Metadata/DSL.rb +11 -0
  28. data/lib/ObjectModel/Metadata/attribute.rb +56 -0
  29. data/lib/ObjectModel/Metadata/child.rb +50 -0
  30. data/lib/ObjectModel/Metadata/events.rb +109 -0
  31. data/lib/ObjectModel/Metadata/name.rb +20 -0
  32. data/lib/ObjectModel/Metadata/reference.rb +50 -0
  33. data/lib/ObjectModel/Metadata/require.rb +10 -0
  34. data/lib/ObjectModel/Metadata/validate.rb +66 -0
  35. data/lib/ObjectModel/Repository.rb +326 -0
  36. data/lib/ObjectModel/Repository/EventProcessor.rb +58 -0
  37. data/lib/ObjectModel/Repository/ObjectStorage.rb +102 -0
  38. data/lib/ObjectModel/Repository/StreamID.rb +20 -0
  39. data/lib/ObjectModel/Repository/StreamStorage.rb +121 -0
  40. data/lib/ObjectModel/Repository/SystemListener.rb +143 -0
  41. data/lib/ObjectModel/Repository/Transaction.rb +63 -0
  42. data/lib/ObjectModel/Repository/TransactionProcessor.rb +36 -0
  43. data/lib/ObjectModel/Tools/DefaultTransactionStrategy.rb +9 -0
  44. data/lib/ObjectModel/Tools/InMemoryCache.rb +9 -0
  45. data/lib/ObjectModel/Tools/NoCache.rb +18 -0
  46. data/lib/ObjectModel/Tools/OGLRUCache.rb +37 -0
  47. data/lib/ObjectModel/Types/BagType.rb +94 -0
  48. data/lib/ObjectModel/Types/BooleanType.rb +42 -0
  49. data/lib/ObjectModel/Types/ClassType.rb +43 -0
  50. data/lib/ObjectModel/Types/DataType.rb +44 -0
  51. data/lib/ObjectModel/Types/DateType.rb +43 -0
  52. data/lib/ObjectModel/Types/NumberType.rb +62 -0
  53. data/lib/ObjectModel/Types/ObjectType.rb +164 -0
  54. data/lib/ObjectModel/Types/ProcType.rb +43 -0
  55. data/lib/ObjectModel/Types/SingleType.rb +59 -0
  56. data/lib/ObjectModel/Types/StringType.rb +39 -0
  57. data/lib/ObjectModel/_require.rb +43 -0
  58. data/lib/ObjectModel/require.rb +1 -0
  59. data/rakefile +62 -0
  60. data/spec/ObjectModel/BasicSpec/BaseClass.rb +7 -0
  61. data/spec/ObjectModel/BasicSpec/BaseTypes.rb +11 -0
  62. data/spec/ObjectModel/BasicSpec/Descendant.rb +5 -0
  63. data/spec/ObjectModel/BasicSpec/EachTest.rb +14 -0
  64. data/spec/ObjectModel/BasicSpec/UpChild.rb +10 -0
  65. data/spec/ObjectModel/BasicSpec/UpParent.rb +11 -0
  66. data/spec/ObjectModel/ErrorsSpec/AfterCommitError.rb +9 -0
  67. data/spec/ObjectModel/ExtendedSpec/CustomInitialization.rb +11 -0
  68. data/spec/ObjectModel/ExtendedSpec/UpNotNil.rb +8 -0
  69. data/spec/ObjectModel/ExtendedSpec/UpParent.rb +11 -0
  70. data/spec/ObjectModel/ValidationSpec/BaseTypes.rb +11 -0
  71. data/spec/aspect_spec.rb +55 -0
  72. data/spec/back_references_spec.rb +161 -0
  73. data/spec/basic_spec.rb +162 -0
  74. data/spec/cascade_delete_spec.rb +168 -0
  75. data/spec/complex_events_spec.rb +134 -0
  76. data/spec/concurrency_spec.rb +186 -0
  77. data/spec/containment_spec.rb +146 -0
  78. data/spec/data_migration_spec.rb +51 -0
  79. data/spec/errors_spec.rb +65 -0
  80. data/spec/events_spec.rb +173 -0
  81. data/spec/extended_spec.rb +171 -0
  82. data/spec/indexing_spec.rb +56 -0
  83. data/spec/set_in_memory.rb +2 -0
  84. data/spec/set_no_cache.rb +2 -0
  85. data/spec/smoke_test_spec.rb +85 -0
  86. data/spec/stream_spec.rb +143 -0
  87. data/spec/stream_storage.rb +148 -0
  88. data/spec/timer.rb +5 -0
  89. data/spec/validation_spec.rb +87 -0
  90. metadata +186 -0
@@ -0,0 +1,56 @@
1
+ require 'ObjectModel/require'
2
+ require 'spec'
3
+
4
+ module ObjectModel
5
+ module IdexingSpec
6
+ describe "Indexing" do
7
+ class SimpleEntity
8
+ inherit Entity
9
+
10
+ metadata do
11
+ attribute :value, :number
12
+ end
13
+ end
14
+
15
+ it "Should create Index on the fly" do
16
+ @r.add_index(HashIndex.new(:square){|e| e.value ** 2})
17
+
18
+ @r.index(:square)[4].value.should == 2
19
+
20
+ @r.transaction{
21
+ SimpleEntity.new('e').set :value => 4
22
+ }.commit
23
+ @r.index(:square)[16].value.should == 4
24
+
25
+ @r.delete_index(:square)
26
+ lambda{@r.index(:square)}.should raise_error(/No Index/)
27
+ end
28
+
29
+ it "Should be able to rebuild index" do
30
+ @r.add_index(HashIndex.new(:square){|e| e.value ** 2})
31
+ @r.index(:square)[4].value.should == 2
32
+
33
+ @r.clear_indexes
34
+ @r.build_indexes
35
+ @r.index(:square)[4].value.should == 2
36
+ end
37
+
38
+ before :each do
39
+ CONFIG[:directory] = "#{File.dirname __FILE__}/data"
40
+ Repository.delete :test
41
+ @r = Repository.new :test
42
+
43
+ @r.transaction{
44
+ SimpleEntity.new('a').set :value => 1
45
+ SimpleEntity.new('b').set :value => 2
46
+ SimpleEntity.new('c').set :value => 3
47
+ }.commit
48
+ end
49
+
50
+ after :each do
51
+ @r.close
52
+ Repository.delete :test
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,2 @@
1
+ require 'ObjectModel/require'
2
+ ObjectModel::CONFIG[:cache] = "ObjectModel::Tools::InMemoryCache"
@@ -0,0 +1,2 @@
1
+ require 'ObjectModel/require'
2
+ ObjectModel::CONFIG[:cache] = "ObjectModel::Tools::NoCache"
@@ -0,0 +1,85 @@
1
+ require 'ObjectModel/require'
2
+ require 'spec'
3
+
4
+ module ObjectModel
5
+ describe "SmokeTest" do
6
+ class ESample
7
+ inherit Entity
8
+ metadata do
9
+ name :esample
10
+ child :bag, :bag
11
+ end
12
+ end
13
+
14
+ it "Metadata, entity_id and name Initialization" do
15
+ @r.transaction do
16
+ e = ESample.new
17
+ e.name.should_not be_nil
18
+ e.entity_id.should_not be_nil
19
+ e.should respond_to(:bag)
20
+ end
21
+
22
+ ESample.meta.children[:bag].type.should == Types::BagType
23
+ ESample.meta.name.should == :esample
24
+ end
25
+
26
+ class SimpleEntity
27
+ inherit Entity
28
+ metadata do
29
+ attribute :label, :string
30
+ # attribute :value_object, :object
31
+ end
32
+ end
33
+
34
+ it "Create & Delete Entity" do
35
+ @r.transaction{
36
+ SimpleEntity.new 'eid'
37
+ }.commit
38
+ @r.should include('eid')
39
+ @r.transaction{
40
+ @r['eid'].delete
41
+ }.commit
42
+
43
+ @r.should_not include('eid')
44
+ end
45
+
46
+ class VOTest
47
+ inherit Entity
48
+ metadata do
49
+ attribute :value_object, :object
50
+ end
51
+ end
52
+
53
+ class CustomValueObject
54
+ attr_accessor :value
55
+ end
56
+
57
+ it "ValueObjects" do
58
+ vo = CustomValueObject.new
59
+ vo.value = "value"
60
+
61
+ @r.transaction{
62
+ e = VOTest.new 'eid'
63
+ e.value_object = vo
64
+ }.commit
65
+ @r['eid'].value_object.value.should == "value"
66
+
67
+ @r.transaction{
68
+ @r['eid'].value_object = nil
69
+ }.commit
70
+ @r['eid'].value_object.should be_nil
71
+ end
72
+
73
+ before :each do
74
+ CONFIG[:directory] = "#{File.dirname __FILE__}/data"
75
+
76
+ Repository.delete :test
77
+ @r = Repository.new(:test)
78
+ end
79
+
80
+ after :each do
81
+ @r.close
82
+ Repository.delete :test
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,143 @@
1
+ require 'ObjectModel/require'
2
+ require 'spec'
3
+
4
+ module ObjectModel
5
+ describe "ObjectModel Stream" do
6
+ before :each do
7
+ CONFIG[:directory] = @dir = "#{File.dirname __FILE__}/data"
8
+ Repository.delete :test
9
+ @r = Repository.new :test
10
+ end
11
+
12
+ after :each do
13
+ @r.close
14
+ Repository.delete :test
15
+ end
16
+
17
+ it "Should revrite old Stream data if it where replaced with Simple Type (i.e. Image -> Integer)" do
18
+ # It's too expensive to automatically do it
19
+ # Old stream should be deleted manually or it will be deleted by garbage collector
20
+ # And this is much safe, because if there is for example AVI, someone watch it, we can simultaneously
21
+ # upload a new one, and when someone finished GC deletes it.
22
+ end
23
+
24
+ it "Write & Read" do
25
+ sid = @r.stream_put do |f|
26
+ f.write "Some data"
27
+ end
28
+
29
+ data = nil
30
+ @r.stream_read sid do |f|
31
+ data = f.read
32
+ end
33
+ data.should == "Some data"
34
+
35
+ data = ""
36
+ # The size of the Part is defined in 'config'
37
+ @r.stream_read_each sid do |part|
38
+ data << part
39
+ end
40
+ data.should == "Some data"
41
+ end
42
+
43
+ it "Id should works properly (from error)" do
44
+ sid = @r.stream_put do |f|
45
+ f.write "Some data"
46
+ end
47
+
48
+ sid2 = @r.stream_put do |f|
49
+ f.write "Some data2"
50
+ end
51
+
52
+ data = nil
53
+ @r.stream_read sid do |f|
54
+ data = f.read
55
+ end
56
+ data.should == "Some data"
57
+ end
58
+
59
+ it "collect_garbage stream" do
60
+ # # GC should work (but id doesn't)
61
+ # GCTest.new
62
+ # has = false
63
+ # ObjectSpace.each_object(GCTest){has = true}
64
+ # has.should be_true
65
+ # ObjectSpace.garbage_collect
66
+ # has = false
67
+ # ObjectSpace.each_object(GCTest){|o| has = true}
68
+ # has.should be_false
69
+
70
+ class GCStub
71
+ class << self
72
+ attr_accessor :objects
73
+ def each_object klass, &b; @objects.each{|o| b.call o} end
74
+ end
75
+ end
76
+
77
+ sid = @r.stream_put StringIO.new("Some data")
78
+ @r.stream_storage.size.should == 1
79
+ GCStub.objects = [sid]
80
+ @r.stream_collect_garbage GCStub
81
+ @r.stream_storage.size.should == 1
82
+ sid = nil
83
+ GCStub.objects = []
84
+ @r.stream_collect_garbage GCStub
85
+ @r.stream_storage.size.should == 0
86
+ end
87
+
88
+ class StreamEntity
89
+ inherit Entity
90
+
91
+ metadata do
92
+ attribute :stream, :data
93
+ attribute :streams, :object
94
+ end
95
+ end
96
+
97
+ it "Should correct restore after loading" do
98
+ @r.transaction{
99
+ e = StreamEntity.new 'e'
100
+ e.stream = @r.stream_put "After loading"
101
+ e.streams = [e.stream]
102
+ }.commit
103
+
104
+ @r.stream_read(@r['e'].stream).should == "After loading"
105
+ @r.stream_read(@r['e'].streams[0]).should == "After loading"
106
+ end
107
+
108
+ it "Read & Write to File" do
109
+ fname = "#{@dir}/frwtest"
110
+ File.delete fname if File.exist? fname
111
+
112
+ sid = @r.stream_put do |f|
113
+ f.write "Some data"
114
+ end
115
+
116
+ @r.stream_read_to_file sid, fname
117
+
118
+ sid2 = @r.stream_put_from_file fname
119
+
120
+ data = nil
121
+ @r.stream_read sid2 do |f|
122
+ data = f.read
123
+ end
124
+ data.should == "Some data"
125
+
126
+ File.delete fname if File.exist? fname
127
+ end
128
+
129
+ # it "Garbage collector shouldn't collect Streams that aren't managed yet, but referenced from memory" do
130
+ # stream = @r.put "Some data" # Referenced, but not managed yet
131
+ # @r.collect_garbage
132
+ # sleep 3
133
+ # stream.read.should == "Some data"
134
+ ## # Later this stream will be added to an Object, but right now it's not managed,
135
+ ## # and if during this time GarbageCollector will runs it should not delete it.
136
+ ##
137
+ ## # Later this stream will be processed further.
138
+ ## c = @r.copy
139
+ ## c[:stream] = stream
140
+ ## c.commit
141
+ # end
142
+ end
143
+ end
@@ -0,0 +1,148 @@
1
+ require 'ObjectModel/require'
2
+ require 'spec'
3
+
4
+ module ObjectModel
5
+ describe "StreamStorage" do
6
+ def before
7
+ @dir = "#{File.dirname(__FILE__)}/data"
8
+ Repository::StreamStorage.delete 'test', @dir
9
+ @storage = Repository::StreamStorage.new('test', @dir)
10
+ end
11
+
12
+ def after
13
+ Repository::StreamStorage.delete 'test', @dir
14
+ end
15
+
16
+ it "Onestep Save & stream_read operations" do
17
+ before
18
+ data = "Some binary data"
19
+ @storage.stream_put 1, data
20
+
21
+ @storage.stream_read(1).should == data
22
+ @storage.stream_size(1).should == "Some binary data".size
23
+
24
+ s = ""
25
+ @storage.stream_read_each 1 do |part|
26
+ s << part
27
+ end
28
+ s.should == data
29
+ after
30
+ end
31
+
32
+ it "clear" do
33
+ before
34
+ @storage.stream_put 1, 'b'
35
+
36
+ @storage.clear
37
+ lambda do
38
+ @storage.stream_read 1
39
+ end.should raise_error
40
+ after
41
+ end
42
+
43
+ it "size" do
44
+ before
45
+ @storage.size.should == 0
46
+ @storage.stream_put 1, "Some binary data"
47
+ @storage.size.should == 1
48
+ after
49
+ end
50
+
51
+ it "Save & stream_read operations" do
52
+ before
53
+ data = "Some binary data"
54
+ @storage.stream_put 1 do |f|
55
+ f.write data
56
+ end
57
+
58
+ stream_readed = ""
59
+ @storage.stream_read 1 do |f|
60
+ while c = f.read(1)
61
+ stream_readed << c
62
+ end
63
+ end
64
+ stream_readed.should == data
65
+ after
66
+ end
67
+
68
+ it "stream_put_each" do
69
+ before
70
+ data = "Some binary data"
71
+ stream = StringIO.new data
72
+ @storage.stream_put_each 3, stream
73
+
74
+ @storage.stream_read(3).should == data
75
+ sleep 0.5
76
+ after
77
+ end
78
+
79
+ it "Should return NotFound, if stream not found" do
80
+ before
81
+ lambda{@storage.stream_read 'invalid stream id'}.should raise_error
82
+ after
83
+ end
84
+
85
+ it "Should allow stream_read the same Stream simultaneously" do
86
+ before
87
+ @storage.stream_put 1, "Some data"
88
+
89
+ timeline = mock("Timeline")
90
+ timeline.should_receive(:first_stream_readed).ordered
91
+ timeline.should_receive(:second_stream_readed).ordered
92
+ timeline.should_receive(:second_finished).ordered
93
+ timeline.should_receive(:first_finished).ordered
94
+
95
+ t1 = Thread.new do
96
+ buff1 = ""
97
+ @storage.stream_read 1 do |f|
98
+ buff1 << f.read(2)
99
+ timeline.first_stream_readed
100
+ sleep 2
101
+ buff1 << f.read(10)
102
+ timeline.first_finished
103
+ end
104
+ "1#{buff1}".should == "1Some data"
105
+ end
106
+
107
+ t2 = Thread.new do
108
+ buff2 = ""
109
+ @storage.stream_read 1 do |f2|
110
+ buff2 << f2.read(2)
111
+ timeline.second_stream_readed
112
+ sleep 1
113
+ buff2 << f2.read(10)
114
+ timeline.second_finished
115
+ end
116
+ "2#{buff2}".should == "2Some data"
117
+ end
118
+
119
+ t2.join; t1.join
120
+ after
121
+ end
122
+
123
+ it "Should raise error if Stream has been deleted" do
124
+ before
125
+ @storage.stream_put 1, "Some data"
126
+ @storage.delete 1
127
+ lambda{@storage.stream_read 1}.should \
128
+ raise_error(RuntimeError, /The Stream with id '1' has been deleted!/)
129
+ after
130
+ end
131
+
132
+ it "Should return list of all stream_id" do
133
+ before
134
+ @storage.list_of_ids.should be_empty
135
+ @storage.stream_put 1, 'Some data'
136
+ @storage.list_of_ids.size.should == 1
137
+ @storage.list_of_ids[0].should == '1'
138
+ after
139
+ end
140
+
141
+ it "Should save metadata" do
142
+ before
143
+ @storage.metadata_put 1, :a => :b
144
+ @storage.metadata_read(1).should == {:a => :b}
145
+ after
146
+ end
147
+ end
148
+ end
data/spec/timer.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Timer
2
+ def initialize; @start = Time.new end
3
+
4
+ def time; (Time.new - @start).round end
5
+ end