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,5 @@
1
+ ---
2
+ :directory: "."
3
+ :buffer_size: 8192
4
+ :cache: "ObjectModel::Tools::InMemoryCache"
5
+ :cache_parameters: 0.2,
@@ -0,0 +1,113 @@
1
+ class BackReferences
2
+ def initialize entity_id
3
+ @entity_id, @array = entity_id, []
4
+ end
5
+
6
+ def each &b
7
+ tr = Thread.current[:om_transaction]
8
+ if tr and tr.changed? @entity_id
9
+ br = tr.copies[@entity_id].back_references
10
+ br._array.each{|entity_id| b.call tr.resolve(entity_id)}
11
+ else
12
+ self._array.each{|entity_id| b.call @om_repository.by_id(entity_id)}
13
+ end
14
+ end
15
+
16
+ def size
17
+ if tr = Thread.current[:om_transaction]
18
+ if tr.changed? @entity_id
19
+ tr.copies[@entity_id].back_references._array.size
20
+ else
21
+ @array.size
22
+ end
23
+ else
24
+ @array.size
25
+ end
26
+ end
27
+
28
+ def _array
29
+ @array
30
+ end
31
+
32
+ class << self
33
+ def initialize_storage db
34
+ db.create_table :back_references do
35
+ column :entity_id, :text
36
+ column :referrer_id, :text
37
+
38
+ # index :entity_id
39
+ end
40
+ end
41
+
42
+ def print_storage db, name
43
+ return unless name == nil or name == :back_references
44
+ puts "\nBackReferences:"
45
+ db[:back_references].print
46
+ end
47
+
48
+ def load e, storage
49
+ rows = storage[:back_references].filter :entity_id => e.entity_id
50
+
51
+ br = if rows.count > 0
52
+ br = BackReferences.new e.entity_id
53
+ rows.each do |row|
54
+ br._array << EntityType.load_id(row[:referrer_id])
55
+ end
56
+ br
57
+ else
58
+ BackReferences.new e.entity_id
59
+ end
60
+ # p [e, br._array]
61
+ e.instance_variable_set "@back_references", br
62
+ end
63
+
64
+ def write_back copy, entity
65
+ entity.back_references._array.replace copy.back_references._array # TODO reimplement more efficiently
66
+ end
67
+
68
+ def initialize_copy e, c
69
+ c.back_references = BackReferences.new e.entity_id
70
+ c.back_references._array.replace e.back_references._array
71
+ end
72
+
73
+ def initialize_entity e
74
+ e.instance_variable_set "@back_references", BackReferences.new(e.entity_id)
75
+ end
76
+
77
+ def persist c, entity_id, storage
78
+ # TODO reimplement more efficiently
79
+ br = c.back_references
80
+ storage[:back_references].filter(:entity_id => entity_id).delete
81
+ if br._array.size > 0
82
+ br._array.each do |ref_id|
83
+ ref_id.should_not! :be_nil
84
+ storage[:back_references].insert(
85
+ :entity_id => entity_id,
86
+ :referrer_id => EntityType.dump_id(ref_id)
87
+ )
88
+ end
89
+ end
90
+ end
91
+
92
+ def delete e, storage
93
+ storage[:back_references].filter(:entity_id => e.entity_id).delete
94
+ end
95
+
96
+ def delete_backreference entity, reference, reference_copy
97
+ br = reference_copy.back_references
98
+ index = br._array.index entity.entity_id
99
+ index.should! :>=, 0
100
+ br._array.delete_at index
101
+ end
102
+
103
+ def new_backreference entity, reference, reference_copy
104
+ br = reference_copy.back_references
105
+ br._array << entity.entity_id
106
+ end
107
+
108
+ def delete_all_references_to e, c, &callback
109
+ array = c.back_references._array.dup
110
+ array.each{|entity_id| callback.call entity_id}
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,129 @@
1
+ class Bag
2
+ include Enumerable
3
+
4
+ def initialize entity, attr_name, repository
5
+ @entity, @entity_id, @attr_name, @repository = entity, entity.entity_id, attr_name, repository
6
+ @array = []
7
+ @ivname = "@#{@attr_name}"
8
+ end
9
+
10
+ def _array
11
+ @array
12
+ end
13
+
14
+ def delete value
15
+ if tr = Thread.current[:om_transaction]
16
+ return unless value.is_a? Entity
17
+ copy = tr.copy_get! @entity
18
+ previous = false
19
+ copy[@ivname].delete_if do |entity_id|
20
+ if previous
21
+ tr.event_processor.fire_after @entity, delete_item_method_name, @attr_name, value
22
+ previous = false
23
+ end
24
+
25
+ if value.entity_id == entity_id
26
+ tr.event_processor.fire_before @entity, delete_item_method_name, @attr_name, value
27
+ previous = true
28
+ true
29
+ else
30
+ false
31
+ end
32
+ end
33
+
34
+ tr.event_processor.fire_after @entity, delete_item_method_name, @attr_name, value if previous
35
+ else
36
+ raise NoTransactionError
37
+ end
38
+ end
39
+
40
+ def size
41
+ if tr = Thread.current[:om_transaction]
42
+ if tr.changed? @entity_id
43
+ tr.copies[@entity_id][@ivname].size
44
+ else
45
+ @array.size
46
+ end
47
+ else
48
+ @array.size
49
+ end
50
+ end
51
+
52
+ def << value
53
+ if tr = Thread.current[:om_transaction]
54
+ tr.event_processor.fire_before @entity, new_item_method_name, @attr_name, value
55
+ copy = tr.copy_get! @entity
56
+ copy[@ivname].add value.entity_id
57
+ tr.event_processor.fire_after @entity, new_item_method_name, @attr_name, value
58
+ else
59
+ raise NoTransactionError
60
+ end
61
+ end
62
+
63
+ def clear
64
+ delete_if{true}
65
+ end
66
+
67
+ def delete_if &b
68
+ if tr = Thread.current[:om_transaction]
69
+ copy = tr.copy_get! @entity
70
+ previous_entity = nil
71
+ copy[@ivname].delete_if do |entity_id|
72
+ entity = tr.resolve(entity_id)
73
+
74
+ if previous_entity != nil
75
+ tr.event_processor.fire_after @entity, delete_item_method_name, @attr_name, previous_entity
76
+ previous_entity = entity
77
+ end
78
+
79
+ if b.call entity
80
+ tr.event_processor.fire_before @entity, delete_item_method_name, @attr_name, entity
81
+ previous = true
82
+ true
83
+ else
84
+ false
85
+ end
86
+ end
87
+
88
+ if previous_entity != nil
89
+ tr.event_processor.fire_after @entity, delete_item_method_name, @attr_name, previous_entity
90
+ end
91
+ else
92
+ raise NoTransactionError
93
+ end
94
+ end
95
+
96
+ def each &b
97
+ tr = Thread.current[:om_transaction]
98
+ if tr and tr.changed? @entity_id
99
+ array = tr.copies[@entity_id][@ivname]
100
+ array.each{|entity_id| b.call tr.resolve(entity_id)}
101
+ else
102
+ @array.each{|entity_id| b.call @repository.by_id(entity_id)}
103
+ end
104
+ end
105
+
106
+ def ids
107
+ if tr = Thread.current[:om_transaction]
108
+ if tr.changed? @entity_id
109
+ tr.copies[@entity_id][@ivname]
110
+ else
111
+ @array
112
+ end
113
+ else
114
+ @array
115
+ end
116
+ end
117
+
118
+ def to_s
119
+ "#<Bag '#{@entity_id}': [#{@array.join(', ')}]>"
120
+ end
121
+
122
+ def empty?
123
+ size == 0
124
+ end
125
+
126
+ def inspect
127
+ to_s
128
+ end
129
+ end
@@ -0,0 +1,29 @@
1
+ class BagCopy
2
+ def initialize array
3
+ @array = array
4
+ end
5
+
6
+ def _array
7
+ @array
8
+ end
9
+
10
+ def delete_if &b
11
+ @array.delete_if &b
12
+ end
13
+
14
+ def size
15
+ @array.size
16
+ end
17
+
18
+ def add value
19
+ @array << value
20
+ end
21
+
22
+ def clear
23
+ @array.clear
24
+ end
25
+
26
+ def each &b
27
+ @array.each &b
28
+ end
29
+ end
@@ -0,0 +1,10 @@
1
+ class ChildrenBag < Bag
2
+ protected
3
+ def delete_item_method_name
4
+ :delete_child
5
+ end
6
+
7
+ def new_item_method_name
8
+ :new_child
9
+ end
10
+ end
@@ -0,0 +1,38 @@
1
+ class EntityCopy
2
+ attr_accessor :om_version, :parent, :back_references, :name, :entity_id
3
+
4
+ def initialize
5
+ @hash = {}
6
+ @new, @moved, @deleted, @updated = false, false, false, false
7
+ end
8
+
9
+ def [] ivname
10
+ ivname.should!(:=~, /^@.+/) if $debug
11
+ @hash[ivname]
12
+ end
13
+
14
+ def []= ivname, value
15
+ ivname.should!(:=~, /^@.+/) if $debug
16
+ @hash[ivname] = value
17
+ end
18
+
19
+ def new?; @new end
20
+ def new!; @new = true end
21
+
22
+ def updated?; @updated end
23
+ def updated!; @updated = true end
24
+
25
+ def deleted?; @deleted end
26
+ def deleted!; @deleted = true end
27
+
28
+ def moved?; @moved end
29
+ def moved!; @moved = true end
30
+
31
+ def to_s
32
+ "#<#EntityCopy: #{name}>"
33
+ end
34
+
35
+ def inspect
36
+ to_s
37
+ end
38
+ end
@@ -0,0 +1,408 @@
1
+ class EntityType
2
+ class << self
3
+ inherit Log
4
+
5
+ def initialize_storage db
6
+ db.create_table :entities do
7
+ column :entity_id, :text
8
+ column :name, :text
9
+ column :class, :text
10
+
11
+ column :om_version, :text
12
+ column :parent_id, :text
13
+
14
+ primary_key :entity_id
15
+ # index :entity_id
16
+ end
17
+
18
+ db.create_table :entities_content do
19
+ column :entity_id, :text
20
+
21
+ column :name, :text
22
+
23
+ column :value, :text
24
+ column :class, :text
25
+
26
+ primary_key :entity_id, :attr_name, :key
27
+ # index :entity_id
28
+ end
29
+ end
30
+
31
+ def print_storage db, name
32
+ if name == nil or name == :entities
33
+ puts "\nEntities:"
34
+ db[:entities].print
35
+ end
36
+ if name == nil or name == :entities_content
37
+ puts "EntitiesContent:"
38
+ db[:entities_content].print
39
+ end
40
+ end
41
+
42
+ def create_copy e
43
+ e.entity_id.should_not! :be_nil
44
+
45
+ c = EntityCopy.new
46
+ c.om_version, c.entity_id, c.name = e.om_version, e.entity_id, e.name
47
+ c.parent = e.instance_variable_get "@parent"
48
+ c.updated!
49
+
50
+ # Attributes
51
+ e.meta.attributes.each do |n, m|
52
+ m.type.initialize_copy m, e, c
53
+ end
54
+
55
+ # Children
56
+ e.meta.children.each do |n, m|
57
+ m.type.initialize_copy m, e, c
58
+ end
59
+
60
+ # References
61
+ e.meta.references.each do |n, m|
62
+ m.type.initialize_copy m, e, c
63
+ end
64
+
65
+ BackReferences.initialize_copy e, c
66
+
67
+ return c
68
+ end
69
+
70
+ def initialize_new_entity e, eid, entity_id, tr
71
+ new_entity_id = if entity_id
72
+ entity_id.should! :be_a, String
73
+ # path_index = tr.repository._index_manager.get_index_without_transaction_check(:path)
74
+ # path_index.get_entity_id(entity_id).should! :be_nil
75
+ raise_without_self "Not Unique :entity_id ('#{entity_id}')!", ObjectModel if storage_include? entity_id, tr.repository.storage
76
+
77
+ tr.copies.should_not! :include, entity_id
78
+ entity_id
79
+ else
80
+ tr.repository.storage.generate(:entity_id)
81
+ end
82
+
83
+ unless eid
84
+ eid = "eid_" + tr.repository.storage.generate(:name)
85
+ end
86
+
87
+ e.instance_variable_set "@entity_id", new_entity_id
88
+ e.instance_variable_set "@om_repository", tr.repository
89
+ e.instance_variable_set "@om_version", 0
90
+
91
+ # Attributes
92
+ e.meta.attributes.each do |n, m|
93
+ value = m.type.initial_value m, e
94
+ e.instance_variable_set m.ivname, value
95
+ end
96
+
97
+ # Children
98
+ e.meta.children.each do |n, m|
99
+ value = m.type.initial_value m, e
100
+ e.instance_variable_set m.ivname, value
101
+ end
102
+
103
+ # References
104
+ e.meta.references.each do |n, m|
105
+ value = m.type.initial_value m, e
106
+ e.instance_variable_set m.ivname, value
107
+ end
108
+
109
+ BackReferences.initialize_entity e
110
+
111
+ tr.event_processor.fire_before e, :new
112
+
113
+ e.name = eid # after :new
114
+ end
115
+
116
+ def load entity_id, repository, storage
117
+ entity_id.should! :be_a, String
118
+ row = storage[:entities][:entity_id => entity_id]
119
+ unless row
120
+ raise NotFoundError, "Entity with entity_id '#{entity_id}' not found!"
121
+ # raise_without_self NotFoundError, "Entity with Path '#{path}' not found!", ObjectModel
122
+ end
123
+
124
+ # Entity
125
+ klass_name = row[:class]
126
+ begin
127
+ klass = eval klass_name, TOPLEVEL_BINDING, __FILE__, __LINE__
128
+ e = klass.new nil, nil, "original_new"
129
+ e.should! :be_a, Entity
130
+ rescue NameError => err
131
+ log.error "Can't find '#{klass}' Class for '#{entity_id}' Entity!"
132
+ raise LoadError.new(err)
133
+ end
134
+
135
+ e.instance_variable_set "@entity_id", entity_id
136
+ e.instance_variable_set "@name", row[:name].should_not!(:be_nil).should_not!(:be_empty)
137
+ e.instance_variable_set "@om_version", row[:om_version].should_not!(:be_nil).to_i
138
+ e.instance_variable_set "@parent", load_id(row[:parent_id].should_not!(:be_nil))
139
+ e.instance_variable_set "@om_repository", repository
140
+
141
+ outdated = []
142
+
143
+ # Attributes
144
+ e.meta.attributes.each do |n, m|
145
+ value = begin
146
+ m.type.load m, e, storage
147
+ rescue LoadError
148
+ outdated << n
149
+ log.warn "Can't load '#{entity_id}.#{n}' Attribute, default value will be used!"
150
+ value = m.type.initial_value m, e
151
+ e.instance_variable_set m.ivname, value
152
+ end
153
+ end
154
+
155
+ # Children
156
+ e.meta.children.each do |n, m|
157
+ value = begin
158
+ m.type.load m, e, storage
159
+ rescue LoadError
160
+ log.warn "Can't load '#{entity_id}.#{n}' Child, default value will be used!"
161
+ value = m.type.initial_value m, e
162
+ e.instance_variable_set m.ivname, value
163
+ end
164
+ end
165
+
166
+ # References
167
+ e.meta.references.each do |n, m|
168
+ value = begin
169
+ m.type.load m, e, storage
170
+ rescue LoadError
171
+ log.warn "Can't load '#{entity_id}.#{n}' Reference, default value will be used!"
172
+ value = m.type.initial_value m, e
173
+ e.instance_variable_set m.ivname, value
174
+ end
175
+ end
176
+
177
+ # BackReferences
178
+ BackReferences.load e, storage
179
+
180
+ # Data Migration
181
+ custom_initialization e, outdated if outdated.size > 0
182
+
183
+ return e
184
+ end
185
+
186
+ def storage_include? entity_id, storage
187
+ storage[:entities][:entity_id => entity_id] != nil
188
+ end
189
+
190
+ def write_back c, e
191
+ c.should! :be_a, EntityCopy
192
+
193
+ # Entity
194
+ c.om_version += 1
195
+ e.instance_variable_set "@om_version", c.om_version
196
+ e.instance_variable_set "@parent", c.parent
197
+ e.instance_variable_set "@name", c.name
198
+
199
+ # Attributes
200
+ e.meta.attributes.each do |n, m|
201
+ m.type.write_back c, e, m
202
+ end
203
+
204
+ # Children
205
+ e.meta.children.each do |n, m|
206
+ m.type.write_back c, e, m
207
+ end
208
+
209
+ # References
210
+ e.meta.references.each do |n, m|
211
+ m.type.write_back c, e, m
212
+ end
213
+
214
+ # BackReferences
215
+ BackReferences.write_back c, e
216
+ end
217
+
218
+ def persist c, e, storage
219
+ entity_id = e.entity_id
220
+
221
+ # Entity
222
+ entities = storage[:entities]
223
+ entities.filter(:entity_id => entity_id).delete
224
+ entities.insert(
225
+ :entity_id => entity_id.should!(:be_a, String).should_not!(:be_empty),
226
+ :name => e.name.should!(:be_a, String).should_not!(:be_empty),
227
+ :class => e.class.name,
228
+ :om_version => c.om_version,
229
+ :parent_id => AnEntity::EntityType.dump_id(c.parent)
230
+ )
231
+ storage[:entities_content].filter(:entity_id => entity_id).delete
232
+
233
+ # Attributes
234
+ e.meta.attributes.each do |n, m|
235
+ m.type.persist c, entity_id, m, storage
236
+ end
237
+
238
+ # Children
239
+ e.meta.children.each do |n, m|
240
+ m.type.persist c, entity_id, m, storage
241
+ end
242
+
243
+ # References
244
+ e.meta.references.each do |n, m|
245
+ m.type.persist c, entity_id, m, storage
246
+ end
247
+
248
+ # BackReferences
249
+ BackReferences.persist c, entity_id, storage
250
+ end
251
+
252
+ def delete e, storage
253
+ entity_id = e.entity_id
254
+
255
+ # Entity
256
+ storage[:entities].filter(:entity_id => entity_id).delete
257
+ storage[:entities_content].filter(:entity_id => entity_id).delete
258
+
259
+ # Attributes
260
+ e.meta.attributes.each do |n, m|
261
+ m.type.respond_to :delete, e, m, storage
262
+ end
263
+
264
+ # Children
265
+ e.meta.children.each do |n, m|
266
+ m.type.respond_to :delete, e, m, storage
267
+ end
268
+
269
+ # References
270
+ e.meta.references.each do |n, m|
271
+ m.type.respond_to :delete, e, m, storage
272
+ end
273
+
274
+ # BackReferences
275
+ BackReferences.delete e, storage
276
+ end
277
+
278
+ def custom_initialization e, outdated = nil
279
+ e.meta.attributes.each do |n, m|
280
+ next if m.initialize == NotDefined or (outdated and !outdated.include?(n))
281
+ value = if m.initialize.is_a? Proc
282
+ e.instance_eval &m.initialize
283
+ else
284
+ m.initialize
285
+ end
286
+ e.send m.name.to_writer, value
287
+ end
288
+ end
289
+
290
+ def validate_attribute e, name, new, old
291
+ m = e.class.meta.attributes[name]
292
+
293
+ unless m.type.validate_type new
294
+ raise_without_self Errors::ValidationError,
295
+ "Invalid Value Type '#{new}' for Attribute '#{e.class.name}.#{name}'!",
296
+ ObjectModel
297
+ end
298
+
299
+ v = m.validate
300
+ if v != nil
301
+ v.should! :be_a, Proc
302
+ begin
303
+ v.call new
304
+ rescue RuntimeError => err
305
+ raise Errors::ValidationError, err.message, err.backtrace
306
+ end
307
+ # unless v.call new
308
+ # raise_without_self Errors::ValidationError,
309
+ # "Invalid Value '#{new}' for Attribute '#{e.class.name}.#{name}'!",
310
+ # ObjectModel
311
+ # end
312
+ end
313
+ end
314
+
315
+ def validate_entity e
316
+ begin
317
+ e.class.meta.validation.validate e
318
+ rescue RuntimeError => err
319
+ raise Errors::ValidationError, err.message, err.backtrace
320
+ end
321
+ # unless e.class.meta.validation.validate e
322
+ # raise_without_self Errors::ValidationError,
323
+ # "Invalid Entity #{e}!",
324
+ # ObjectModel
325
+ # end
326
+ end
327
+
328
+ def delete_all_children e
329
+ e.meta.children.each do |n, m|
330
+ m.type.delete_all_children e, m
331
+ end
332
+ end
333
+
334
+ def delete_all_references_to tr, e
335
+ c = tr.copies[e.entity_id]
336
+ processed = Set.new
337
+ BackReferences.delete_all_references_to e, c do |referrer_entity_id|
338
+ next if processed.include? referrer_entity_id
339
+ processed << referrer_entity_id
340
+
341
+ referrer = tr.resolve referrer_entity_id
342
+ referrer.meta.references.each do |n, m|
343
+ m.type.delete_all_references_to referrer, e, m
344
+ end
345
+ end
346
+ end
347
+
348
+ def delete_from_parent e, parent
349
+ e.should! :be_a, Entity
350
+ parent.should! :be_a, Entity
351
+ parent.meta.children.each do |n, m|
352
+ m.type.delete_from_parent e, parent, m
353
+ end
354
+ end
355
+
356
+ def delete_backreference transaction, entity, reference
357
+ reference_copy = transaction.copy_get! reference
358
+ BackReferences.delete_backreference entity, reference, reference_copy
359
+ end
360
+
361
+ def new_backreference transaction, entity, reference
362
+ reference_copy = transaction.copy_get! reference
363
+ BackReferences.new_backreference entity, reference, reference_copy
364
+ end
365
+
366
+ def each_attribute e, &b
367
+ e.meta.attributes.each{|n, m| b.call e.send(n)}
368
+ end
369
+
370
+ def each_child e, &b
371
+ e.meta.children.each{|n, m| m.type.each e, m, &b}
372
+ end
373
+
374
+ def each_reference e, &b
375
+ e.meta.references.each{|n, m| m.type.each e, m, &b}
376
+ end
377
+
378
+ def each_entity_in_repository repository, &b
379
+ repository.storage[:entities].each do |row|
380
+ e = repository.by_id row[:entity_id]
381
+ b.call e
382
+ end
383
+ end
384
+
385
+ def load_id data
386
+ raise LoadError if data == nil
387
+ data == "nil" ? nil : data
388
+ end
389
+
390
+ def dump_id id
391
+ if id == nil
392
+ "nil"
393
+ else
394
+ id.should! :be_a, String
395
+ id
396
+ end
397
+ end
398
+
399
+ def load_id! data, klass
400
+ raise LoadError unless klass == "ENTITY_ID"
401
+ load_id data
402
+ end
403
+
404
+ def dump_id! id
405
+ [dump_id(id), "ENTITY_ID"]
406
+ end
407
+ end
408
+ end