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.
- data/README +849 -0
- data/lib/ObjectModel.res/config.yaml +5 -0
- data/lib/ObjectModel/AnEntity/BackReferences.rb +113 -0
- data/lib/ObjectModel/AnEntity/Bag.rb +129 -0
- data/lib/ObjectModel/AnEntity/BagCopy.rb +29 -0
- data/lib/ObjectModel/AnEntity/ChildrenBag.rb +10 -0
- data/lib/ObjectModel/AnEntity/EntityCopy.rb +38 -0
- data/lib/ObjectModel/AnEntity/EntityType.rb +408 -0
- data/lib/ObjectModel/AnEntity/ReferencesBag.rb +10 -0
- data/lib/ObjectModel/AnEntity/entity_cm.rb +108 -0
- data/lib/ObjectModel/Entity.rb +278 -0
- data/lib/ObjectModel/Errors/LoadError.rb +3 -0
- data/lib/ObjectModel/Errors/NoTransactionError.rb +3 -0
- data/lib/ObjectModel/Errors/NotFoundError.rb +2 -0
- data/lib/ObjectModel/Errors/OutdatedError.rb +8 -0
- data/lib/ObjectModel/Errors/ValidationError.rb +3 -0
- data/lib/ObjectModel/Indexes/HashIndex.rb +64 -0
- data/lib/ObjectModel/Indexes/IndexStorage.rb +64 -0
- data/lib/ObjectModel/Indexes/Manager.rb +72 -0
- data/lib/ObjectModel/Metadata.rb +34 -0
- data/lib/ObjectModel/Metadata.res/after_event_types.rb +25 -0
- data/lib/ObjectModel/Metadata.res/attribute_types_shortcuts.rb +10 -0
- data/lib/ObjectModel/Metadata.res/before_event_types.rb +25 -0
- data/lib/ObjectModel/Metadata.res/child_types_shortcuts.rb +4 -0
- data/lib/ObjectModel/Metadata.res/metadata_checks.rb +9 -0
- data/lib/ObjectModel/Metadata.res/reference_types_shortcuts.rb +4 -0
- data/lib/ObjectModel/Metadata/DSL.rb +11 -0
- data/lib/ObjectModel/Metadata/attribute.rb +56 -0
- data/lib/ObjectModel/Metadata/child.rb +50 -0
- data/lib/ObjectModel/Metadata/events.rb +109 -0
- data/lib/ObjectModel/Metadata/name.rb +20 -0
- data/lib/ObjectModel/Metadata/reference.rb +50 -0
- data/lib/ObjectModel/Metadata/require.rb +10 -0
- data/lib/ObjectModel/Metadata/validate.rb +66 -0
- data/lib/ObjectModel/Repository.rb +326 -0
- data/lib/ObjectModel/Repository/EventProcessor.rb +58 -0
- data/lib/ObjectModel/Repository/ObjectStorage.rb +102 -0
- data/lib/ObjectModel/Repository/StreamID.rb +20 -0
- data/lib/ObjectModel/Repository/StreamStorage.rb +121 -0
- data/lib/ObjectModel/Repository/SystemListener.rb +143 -0
- data/lib/ObjectModel/Repository/Transaction.rb +63 -0
- data/lib/ObjectModel/Repository/TransactionProcessor.rb +36 -0
- data/lib/ObjectModel/Tools/DefaultTransactionStrategy.rb +9 -0
- data/lib/ObjectModel/Tools/InMemoryCache.rb +9 -0
- data/lib/ObjectModel/Tools/NoCache.rb +18 -0
- data/lib/ObjectModel/Tools/OGLRUCache.rb +37 -0
- data/lib/ObjectModel/Types/BagType.rb +94 -0
- data/lib/ObjectModel/Types/BooleanType.rb +42 -0
- data/lib/ObjectModel/Types/ClassType.rb +43 -0
- data/lib/ObjectModel/Types/DataType.rb +44 -0
- data/lib/ObjectModel/Types/DateType.rb +43 -0
- data/lib/ObjectModel/Types/NumberType.rb +62 -0
- data/lib/ObjectModel/Types/ObjectType.rb +164 -0
- data/lib/ObjectModel/Types/ProcType.rb +43 -0
- data/lib/ObjectModel/Types/SingleType.rb +59 -0
- data/lib/ObjectModel/Types/StringType.rb +39 -0
- data/lib/ObjectModel/_require.rb +43 -0
- data/lib/ObjectModel/require.rb +1 -0
- data/rakefile +62 -0
- data/spec/ObjectModel/BasicSpec/BaseClass.rb +7 -0
- data/spec/ObjectModel/BasicSpec/BaseTypes.rb +11 -0
- data/spec/ObjectModel/BasicSpec/Descendant.rb +5 -0
- data/spec/ObjectModel/BasicSpec/EachTest.rb +14 -0
- data/spec/ObjectModel/BasicSpec/UpChild.rb +10 -0
- data/spec/ObjectModel/BasicSpec/UpParent.rb +11 -0
- data/spec/ObjectModel/ErrorsSpec/AfterCommitError.rb +9 -0
- data/spec/ObjectModel/ExtendedSpec/CustomInitialization.rb +11 -0
- data/spec/ObjectModel/ExtendedSpec/UpNotNil.rb +8 -0
- data/spec/ObjectModel/ExtendedSpec/UpParent.rb +11 -0
- data/spec/ObjectModel/ValidationSpec/BaseTypes.rb +11 -0
- data/spec/aspect_spec.rb +55 -0
- data/spec/back_references_spec.rb +161 -0
- data/spec/basic_spec.rb +162 -0
- data/spec/cascade_delete_spec.rb +168 -0
- data/spec/complex_events_spec.rb +134 -0
- data/spec/concurrency_spec.rb +186 -0
- data/spec/containment_spec.rb +146 -0
- data/spec/data_migration_spec.rb +51 -0
- data/spec/errors_spec.rb +65 -0
- data/spec/events_spec.rb +173 -0
- data/spec/extended_spec.rb +171 -0
- data/spec/indexing_spec.rb +56 -0
- data/spec/set_in_memory.rb +2 -0
- data/spec/set_no_cache.rb +2 -0
- data/spec/smoke_test_spec.rb +85 -0
- data/spec/stream_spec.rb +143 -0
- data/spec/stream_storage.rb +148 -0
- data/spec/timer.rb +5 -0
- data/spec/validation_spec.rb +87 -0
- metadata +186 -0
|
@@ -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,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
|