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,10 @@
1
+ class ReferencesBag < Bag
2
+ protected
3
+ def delete_item_method_name
4
+ :delete_reference
5
+ end
6
+
7
+ def new_item_method_name
8
+ :new_reference
9
+ end
10
+ end
@@ -0,0 +1,108 @@
1
+ module ObjectModel
2
+ module Entity
3
+ module ClassMethods
4
+ attr_accessor :self_meta
5
+
6
+ def metadata &b
7
+ Metadata::DSL.new self, &b
8
+ end
9
+
10
+ def _define_attribute m
11
+ n = m.name
12
+ script = %{\
13
+ def #{n}
14
+ _single_attribute_get "@#{n}"
15
+ end
16
+
17
+ def #{n}= value
18
+ _single_attribute_set "@#{n}", :#{n}, value
19
+ end
20
+
21
+ def #{n}_get
22
+ @#{n}
23
+ end
24
+ }
25
+ class_eval script, __FILE__, __LINE__
26
+ end
27
+
28
+ def _define_child m
29
+ n = m.name
30
+ if m.type == Types::SingleType
31
+ script = %{\
32
+ def #{n}
33
+ _single_child_get "@#{n}"
34
+ end
35
+
36
+ def #{n}= value
37
+ _single_child_set "@#{n}", :#{n}, value
38
+ end
39
+
40
+ def #{n}_get
41
+ return @#{n} ? @om_repository.by_id(@#{n}) : nil
42
+ end
43
+ }
44
+ class_eval script, __FILE__, __LINE__
45
+ else
46
+ class_eval{attr_reader n}
47
+ end
48
+ end
49
+
50
+ def _define_reference m
51
+ n = m.name
52
+ if m.type == Types::SingleType
53
+ script = %{\
54
+ def #{n}
55
+ _single_reference_get "@#{n}"
56
+ end
57
+
58
+ def #{n}= value
59
+ _single_reference_set "@#{n}", :#{n}, value
60
+ end
61
+
62
+ def #{n}_get
63
+ return @#{n} ? @om_repository.by_id(@#{n}) : nil
64
+ end
65
+ }
66
+ class_eval script, __FILE__, __LINE__
67
+ else
68
+ class_eval{attr_reader n}
69
+ end
70
+ end
71
+
72
+ def meta
73
+ meta = ancestors.reverse.inject nil do |r, a|
74
+ if a.respond_to? :self_meta
75
+ self_meta.should_not! :be_nil
76
+ r ? a.self_meta.inherit(r) : a.self_meta
77
+ else
78
+ r
79
+ end
80
+ end
81
+ return meta
82
+ end
83
+
84
+ def new eid = nil, entity_id = nil, original_new = nil
85
+ e = super()
86
+ if original_new == "original_new"
87
+ return e
88
+ else
89
+ original_new.should! :be_nil
90
+ end
91
+
92
+ tr = Thread.current[:om_transaction]
93
+ raise_without_self NoTransactionError, "", ObjectModel unless tr
94
+
95
+ AnEntity::EntityType.initialize_new_entity e, eid, entity_id, tr
96
+
97
+ tr.new_entities[e.entity_id] = e
98
+ c = tr.copy_get! e
99
+ c.new!
100
+
101
+ tr.event_processor.fire_after e, :new
102
+
103
+ return e
104
+ end
105
+ end
106
+ extend ClassMethods
107
+ end
108
+ end
@@ -0,0 +1,278 @@
1
+ module Entity
2
+ include OpenConstructor
3
+ attr_reader :om_version, :entity_id, :om_repository, :back_references
4
+
5
+ def == other
6
+ @entity_id.should_not! :be_nil
7
+ return false unless other.respond_to? :entity_id
8
+ @entity_id == other.entity_id
9
+ end
10
+
11
+ def eql? other
12
+ @entity_id.should_not! :be_nil
13
+ return false unless self.class == other.class
14
+ @entity_id == other.entity_id
15
+ end
16
+
17
+ def hash
18
+ @entity_id.should_not! :be_nil
19
+ return @entity_id.hash
20
+ end
21
+
22
+ def to_s;
23
+ "#<#{self.class.name.split("::").last}: #{name}>"
24
+ end
25
+
26
+ def inspect
27
+ to_s
28
+ end
29
+
30
+ def to_yaml io
31
+ raise "You can't save Entity as YAML!"
32
+ end
33
+
34
+ def meta
35
+ self.class.meta
36
+ end
37
+
38
+ def delete
39
+ tr = Thread.current[:om_transaction]
40
+ raise NoTransactionError unless tr
41
+ copy = tr.copy_get!(self)
42
+ copy.new?.should! :be_false
43
+
44
+ tr.event_processor.fire_before self, :delete
45
+ tr.event_processor.fire_after self, :delete
46
+
47
+ copy.deleted!
48
+ end
49
+
50
+ def name
51
+ if tr = Thread.current[:om_transaction]
52
+ if tr.changed? @entity_id
53
+ tr.copies[@entity_id].name
54
+ else
55
+ @name
56
+ end
57
+ else
58
+ @name
59
+ end
60
+ end
61
+
62
+ def name_get
63
+ @name
64
+ end
65
+
66
+ def name= eid
67
+ if tr = Thread.current[:om_transaction]
68
+ copy = tr.copy_get! self
69
+ old_value = copy.name
70
+ tr.event_processor.fire_before self, :name_update, eid, old_value
71
+ copy.name = eid
72
+ tr.event_processor.fire_after self, :name_update, eid, old_value
73
+ else
74
+ raise NoTransactionError
75
+ end
76
+ end
77
+
78
+ def path
79
+ path, current = Path.new(name), self
80
+ while current = current.parent
81
+ path = Path.new(current.name) + path
82
+ end
83
+ path
84
+ end
85
+
86
+ def parent
87
+ tr = Thread.current[:om_transaction]
88
+ if tr and tr.changed? @entity_id
89
+ entity_id = tr.copies[@entity_id].parent
90
+ entity_id ? tr.resolve(entity_id) : nil
91
+ else
92
+ @parent ? @om_repository.by_id(@parent) : nil
93
+ end
94
+ end
95
+
96
+ def parent_get
97
+ @parent ? @om_repository.by_id(@parent) : nil
98
+ end
99
+
100
+ def _parent= parent
101
+ if tr = Thread.current[:om_transaction]
102
+ copy = tr.copy_get! self
103
+ copy.parent = parent != nil ? parent.entity_id : nil
104
+ else
105
+ raise NoTransactionError
106
+ end
107
+ end
108
+
109
+ def up method_name, *p, &b
110
+ result = nil
111
+ e = search_up do |e|
112
+ result = e.respond_to method_name, *p
113
+ result != nil
114
+ end
115
+ return result
116
+
117
+ # if respond_to? method_name
118
+ # value = send(method_name, *p, &b)
119
+ # if value != nil
120
+ # return value
121
+ # elsif parent_get and parent_get.respond_to? method_name
122
+ # parent_get.up method_name, *p, &b
123
+ # else
124
+ # return value
125
+ # end
126
+ # else
127
+ # return parent_get.up method_name, *p, &b if parent_get
128
+ # return nil #raise NoMethodError, "Undefined method '#{method_name}' for '#{self.class.name}' and for it's parents!", caller
129
+ # end
130
+ end
131
+
132
+ def search_up &b
133
+ return self if b.call self
134
+ parent = parent_get
135
+ if parent
136
+ if b.call(parent)
137
+ return parent
138
+ else
139
+ return parent.search_up &b
140
+ end
141
+ else
142
+ nil
143
+ end
144
+ end
145
+
146
+ def each specificator, &block
147
+ case specificator
148
+ when :attribute then AnEntity::EntityType.each_attribute self, &block
149
+ when :child then AnEntity::EntityType.each_child self, &block
150
+ when :reference then AnEntity::EntityType.each_reference self, &block
151
+ else
152
+ should! :be_never_called
153
+ end
154
+ end
155
+
156
+ def include? path
157
+ path = path.to_s if path.is_a? Path
158
+ path.should! :be_a, String
159
+
160
+ absolute_path = "#{path_get}/#{path}"
161
+ entity_id = @om_repository.index(:path).get_entity_id absolute_path
162
+
163
+ entity_id.should! :be_a, [String, NilClass]
164
+ return entity_id != nil
165
+ end
166
+
167
+ def [] path
168
+ path = path.to_s if path.is_a? Path
169
+ path.should! :be_a, String
170
+
171
+ absolute_path = "#{path_get}/#{path}"
172
+ entity_id = @om_repository.index(:path).get_entity_id absolute_path
173
+ raise_without_self NotFoundError, "Entity with Path '#{path}' not found!", ObjectModel if entity_id == nil
174
+
175
+ entity_id.should! :be_a, String
176
+ return @om_repository.by_id entity_id
177
+ end
178
+
179
+ def validate
180
+ AnEntity::EntityType.validate_entity self
181
+ end
182
+
183
+ protected
184
+ def path_get
185
+ path, current = Path.new(name_get), self
186
+ while current = current.parent_get
187
+ path = Path.new(current.name_get) + path
188
+ end
189
+ path
190
+ end
191
+
192
+ def _single_child_get ivname
193
+ tr = Thread.current[:om_transaction]
194
+ if tr and tr.changed? @entity_id
195
+ entity_id = tr.copies[@entity_id][ivname]
196
+ entity_id ? tr.resolve(entity_id) : nil
197
+ else
198
+ entity_id = instance_variable_get ivname
199
+ entity_id ? @om_repository.by_id(entity_id) : nil
200
+ end
201
+ end
202
+
203
+ def _single_child_set ivname, name, value
204
+ if tr = Thread.current[:om_transaction]
205
+ copy = tr.copy_get! self
206
+ old_value = copy[ivname]
207
+
208
+ if old_value != nil
209
+ old_entity = tr.resolve(old_value)
210
+ tr.event_processor.fire_before self, :delete_child, name, old_entity
211
+ copy[ivname] = nil
212
+ tr.event_processor.fire_after self, :delete_child, name, old_entity
213
+ end
214
+
215
+ tr.event_processor.fire_before self, :new_child, name, value if value != nil
216
+ copy[ivname] = value != nil ? value.entity_id : nil
217
+ tr.event_processor.fire_after self, :new_child, name, value if value != nil
218
+ else
219
+ raise NoTransactionError
220
+ end
221
+ end
222
+
223
+ def _single_reference_get ivname
224
+ tr = Thread.current[:om_transaction]
225
+ if tr and tr.changed? @entity_id
226
+ entity_id = tr.copies[@entity_id][ivname]
227
+ entity_id ? tr.resolve(entity_id) : nil
228
+ else
229
+ entity_id = instance_variable_get ivname
230
+ entity_id ? @om_repository.by_id(entity_id) : nil
231
+ end
232
+ end
233
+
234
+ def _single_reference_set ivname, name, value
235
+ if tr = Thread.current[:om_transaction]
236
+ copy = tr.copy_get! self
237
+ old_value = copy[ivname]
238
+
239
+ if old_value != nil
240
+ old_entity = tr.resolve(old_value)
241
+ tr.event_processor.fire_before self, :delete_reference, name, old_entity
242
+ copy[ivname] = nil
243
+ tr.event_processor.fire_after self, :delete_reference, name, old_entity
244
+ end
245
+
246
+ tr.event_processor.fire_before self, :new_reference, name, value if value != nil
247
+ copy[ivname] = value != nil ? value.entity_id : nil
248
+ tr.event_processor.fire_after self, :new_reference, name, value if value != nil
249
+ else
250
+ raise NoTransactionError
251
+ end
252
+ end
253
+
254
+ def _single_attribute_get ivname
255
+ if tr = Thread.current[:om_transaction]
256
+ if tr.changed? @entity_id
257
+ tr.copies[@entity_id][ivname]
258
+ else
259
+ instance_variable_get ivname
260
+ end
261
+ else
262
+ instance_variable_get ivname
263
+ end
264
+ end
265
+
266
+ def _single_attribute_set ivname, name, value
267
+ if tr = Thread.current[:om_transaction]
268
+ copy = tr.copy_get! self
269
+ old_value = copy[ivname]
270
+ tr.event_processor.fire_before self, :attribute_update, name, value, old_value
271
+ copy[ivname] = value
272
+ tr.event_processor.fire_after self, :attribute_update, name, value, old_value
273
+ else
274
+ raise NoTransactionError
275
+ end
276
+ end
277
+ end
278
+ require "#{File.dirname(__FILE__)}/AnEntity/entity_cm"
@@ -0,0 +1,3 @@
1
+ class LoadError < RuntimeError;
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class NoTransactionError < RuntimeError
2
+
3
+ end
@@ -0,0 +1,2 @@
1
+ class NotFoundError < RuntimeError
2
+ end
@@ -0,0 +1,8 @@
1
+ class OutdatedError < RuntimeError
2
+ attr_reader :outdated
3
+
4
+ def initialize outdated
5
+ super()
6
+ @outdated = outdated
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ class ValidationError < RuntimeError
2
+
3
+ end
@@ -0,0 +1,64 @@
1
+ class HashIndex
2
+ attr_accessor :storage, :name, :repository
3
+
4
+ def initialize name, &hasher
5
+ name.should! :be_a, Symbol
6
+ @name, @hasher = name, hasher
7
+ end
8
+
9
+ def include? hash
10
+ hash.should! :be_a, String
11
+ return storage[@name][:hash => hash] != nil
12
+ end
13
+
14
+ def [] hash
15
+ entity_id = get_entity_id hash
16
+ return entity_id != nil ? @repository.by_id(entity_id) : nil
17
+ end
18
+
19
+ def get_entity_id hash
20
+ row = storage[@name][:hash => hash.to_s]
21
+ return row ? row[:entity_id] : nil
22
+ end
23
+
24
+ def update entity, copy
25
+ storage[@name].filter(:entity_id => entity.entity_id).delete
26
+ unless copy.deleted?
27
+ hash = @hasher.call(entity)
28
+ storage[@name].insert :hash => hash.to_s, :entity_id => entity.entity_id if hash != nil
29
+ end
30
+ end
31
+
32
+ def add entity
33
+ hash = @hasher.call(entity)
34
+ # hash.should! :be_a, String
35
+ storage[@name].insert :hash => hash.to_s, :entity_id => entity.entity_id if hash != nil
36
+ end
37
+
38
+ def print_storage i_name
39
+ return unless i_name == nil or i_name == @name
40
+ puts "\nHashIndex #{@name}:"
41
+ storage[@name].print
42
+ @storage
43
+ end
44
+
45
+ def create_index
46
+ if storage.db.table_exists? @name
47
+ return true
48
+ else
49
+ storage.db.create_table @name do
50
+ column :hash, :text
51
+ column :entity_id, :text
52
+ primary_key :hash
53
+
54
+ # index :hash
55
+ # index :entity_id
56
+ end
57
+ return false
58
+ end
59
+ end
60
+
61
+ def delete_index
62
+ storage.db.drop_table @name if storage.db.table_exists? @name
63
+ end
64
+ end