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,58 @@
|
|
|
1
|
+
class EventProcessor
|
|
2
|
+
def initialize transaction
|
|
3
|
+
@transaction = transaction
|
|
4
|
+
@before_history = []
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def fire_before entity, event, *params
|
|
8
|
+
entity.should! :be_a, Entity
|
|
9
|
+
event.should! :be_in, Metadata::BEFORE_EVENT_TYPES
|
|
10
|
+
|
|
11
|
+
l_event = :"before_#{event}"
|
|
12
|
+
@transaction.repository.entity_listeners.each{|l| l.respond_to l_event, entity, *params}
|
|
13
|
+
@transaction.system_listener.respond_to l_event, entity, *params
|
|
14
|
+
|
|
15
|
+
entity.meta.before.fire entity, event, *params
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def fire_after entity, event, *params
|
|
19
|
+
entity.should! :be_a, Entity
|
|
20
|
+
event.should! :be_in, Metadata::AFTER_EVENT_TYPES
|
|
21
|
+
|
|
22
|
+
l_event = :"after_#{event}"
|
|
23
|
+
@transaction.repository.entity_listeners.each{|l| l.respond_to l_event, entity, *params}
|
|
24
|
+
@transaction.system_listener.respond_to l_event, entity, *params
|
|
25
|
+
|
|
26
|
+
entity.meta.after.fire entity, event, *params
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def fire_before_commit
|
|
30
|
+
entities = []
|
|
31
|
+
@transaction.copies.each do |entity_id, c|
|
|
32
|
+
entities << @transaction.resolve(entity_id)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
@transaction.repository.entity_listeners.each{|l| l.respond_to :before_commit, entities}
|
|
36
|
+
@transaction.system_listener.respond_to :before_commit, entities
|
|
37
|
+
|
|
38
|
+
entities.each{|e| e.meta.before.fire e, :commit}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def fire_after_commit
|
|
42
|
+
entities = []
|
|
43
|
+
@transaction.copies.each do |entity_id, c|
|
|
44
|
+
entity = if @transaction.deleted_entities.include? entity_id
|
|
45
|
+
@transaction.deleted_entities[entity_id]
|
|
46
|
+
else
|
|
47
|
+
@transaction.repository.by_id entity_id
|
|
48
|
+
end
|
|
49
|
+
entities << entity
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# :after_commit
|
|
53
|
+
@transaction.repository.entity_listeners.each{|l| l.respond_to :after_commit, entities}
|
|
54
|
+
@transaction.system_listener.respond_to :after_commit, entities
|
|
55
|
+
|
|
56
|
+
entities.each{|e| e.meta.after.fire e, :commit}
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
class ObjectStorage
|
|
2
|
+
inherit Log
|
|
3
|
+
TYPES_TO_INITIALIZE = []
|
|
4
|
+
|
|
5
|
+
attr_reader :metadata
|
|
6
|
+
|
|
7
|
+
def initialize name, dir
|
|
8
|
+
folder = File.expand_path "#{dir}/#{name}" #.sub(/^\.\//, "")
|
|
9
|
+
Dir.mkdir folder unless File.exist? folder
|
|
10
|
+
@db = Sequel.connect("sqlite://#{folder}/#{name}.db")
|
|
11
|
+
@db.logger = log
|
|
12
|
+
|
|
13
|
+
unless @db.table_exists? :metadata
|
|
14
|
+
initialize_db
|
|
15
|
+
TYPES_TO_INITIALIZE.each{|type| type.initialize_storage @db}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
@metadata ||= @db[:metadata]
|
|
19
|
+
@custom_metadata ||= @db[:custom_metadata]
|
|
20
|
+
@tables = {}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def [] type
|
|
24
|
+
@tables[type] ||= @db[type]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def generate generator_name
|
|
28
|
+
generator_name = generator_name.to_s
|
|
29
|
+
@db.transaction do
|
|
30
|
+
unless row = @metadata[:key => generator_name]
|
|
31
|
+
@metadata << {:key => generator_name, :value => "0"}
|
|
32
|
+
row = @metadata[:key => generator_name]
|
|
33
|
+
end
|
|
34
|
+
id = @metadata[:key => generator_name.to_s][:value].to_i
|
|
35
|
+
@metadata.filter(:key => generator_name).update(:value => (id + 1).to_s)
|
|
36
|
+
return id.to_s
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def size
|
|
41
|
+
@db.transaction do
|
|
42
|
+
id = @metadata[:key => "size"][:value].to_i
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def size= value
|
|
47
|
+
@db.transaction do
|
|
48
|
+
value.should! :be_a, Number
|
|
49
|
+
@metadata.filter(:key => "size").update(:value => value.to_s)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def close
|
|
54
|
+
@tables.clear
|
|
55
|
+
@db.disconnect
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def transaction &b
|
|
59
|
+
@db.transaction &b
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def print name = nil
|
|
63
|
+
TYPES_TO_INITIALIZE.each{|type| type.print_storage @db, name}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def get key
|
|
67
|
+
key.should! :be_a, String
|
|
68
|
+
row = @custom_metadata[:key => key]
|
|
69
|
+
return row ? row[:value] : nil
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def put key, value
|
|
73
|
+
key.should! :be_a, String
|
|
74
|
+
value.should! :be_a, String
|
|
75
|
+
|
|
76
|
+
@custom_metadata.filter(:key => key).delete
|
|
77
|
+
@custom_metadata << {:key => key, :value => value}
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
protected
|
|
81
|
+
def initialize_db
|
|
82
|
+
@db.create_table :metadata do
|
|
83
|
+
column :key, :text
|
|
84
|
+
column :value, :text
|
|
85
|
+
primary_key :key
|
|
86
|
+
# index :key
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
@db.create_table :custom_metadata do
|
|
90
|
+
column :key, :text
|
|
91
|
+
column :value, :text
|
|
92
|
+
primary_key :key
|
|
93
|
+
# index :key
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
@metadata = @db[:metadata]
|
|
97
|
+
# @metadata << {:key => "entity_id", :value => "0"}
|
|
98
|
+
# @metadata << {:key => "name", :value => "0"}
|
|
99
|
+
# @metadata << {:key => "stream_id", :value => "0"}
|
|
100
|
+
@metadata << {:key => "size", :value => "0"}
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class StreamID
|
|
2
|
+
attr_reader :sid
|
|
3
|
+
def initialize id = nil
|
|
4
|
+
@sid = id
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def == other
|
|
8
|
+
return false unless other.respond_to? :sid
|
|
9
|
+
@sid == other.sid
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def eql? other
|
|
13
|
+
return false unless self.class == other.class
|
|
14
|
+
@sid == other.sid
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def hash
|
|
18
|
+
return @sid.hash
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
class StreamStorage
|
|
2
|
+
STREAMS = "streams"
|
|
3
|
+
|
|
4
|
+
def initialize name, basedir, buffer_size = 8192
|
|
5
|
+
@buffer_size = buffer_size
|
|
6
|
+
raise "Invalid directory '#{basedir}'!" unless File.exist? basedir
|
|
7
|
+
@path = File.join(basedir.gsub("\\", '/'), name.to_s)
|
|
8
|
+
|
|
9
|
+
Dir.mkdir @path unless File.exist? @path
|
|
10
|
+
Dir.mkdir File.join(@path, STREAMS) unless File.exist? File.join(@path, STREAMS)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def clear
|
|
14
|
+
FileUtils.rm Dir.glob(File.join(@path, STREAMS, "*.dat"))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def strip_id id
|
|
18
|
+
id.sid
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def metadata_put id, metadata
|
|
22
|
+
id = strip_id(id)
|
|
23
|
+
metafile_name = File.join(@path, STREAMS, "#{id.to_s}.met")
|
|
24
|
+
File.open(metafile_name, "wb") do |datafile|
|
|
25
|
+
datafile.write YAML.dump(metadata)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def metadata_read id
|
|
30
|
+
id = strip_id(id)
|
|
31
|
+
begin
|
|
32
|
+
File.open(File.join(@path, STREAMS, "#{id.to_s}.met"), "rb") do |file|
|
|
33
|
+
return YAML.load(file.read)
|
|
34
|
+
end
|
|
35
|
+
rescue Exception => e
|
|
36
|
+
if e.message =~ /No such file or directory/
|
|
37
|
+
raise RuntimeError, "The Metadata with id '#{id}' not exist!", caller
|
|
38
|
+
else
|
|
39
|
+
raise e
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def stream_put id, data = nil, &block
|
|
45
|
+
id = strip_id(id)
|
|
46
|
+
datafile_name = File.join(@path, STREAMS, "#{id.to_s}.dat")
|
|
47
|
+
File.open(datafile_name, "wb") do |datafile|
|
|
48
|
+
if block
|
|
49
|
+
block.call datafile
|
|
50
|
+
elsif data
|
|
51
|
+
datafile.write data
|
|
52
|
+
else
|
|
53
|
+
raise "Data is not supplied!"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def stream_put_each id, stream
|
|
59
|
+
stream_put id do |out|
|
|
60
|
+
while part = stream.read(@buffer_size)
|
|
61
|
+
out.write part
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def stream_read id, &block
|
|
67
|
+
id = strip_id(id)
|
|
68
|
+
begin
|
|
69
|
+
File.open(File.join(@path, STREAMS, "#{id.to_s}.dat"), "rb") do |file|
|
|
70
|
+
if block
|
|
71
|
+
block.call file
|
|
72
|
+
else
|
|
73
|
+
return file.read
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
rescue Exception => e
|
|
77
|
+
if e.message =~ /No such file or directory/
|
|
78
|
+
raise RuntimeError, "The Stream with id '#{id}' has been deleted!", caller
|
|
79
|
+
else
|
|
80
|
+
raise e
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def stream_read_each id, &block
|
|
86
|
+
stream_read id do |f|
|
|
87
|
+
while part = f.read(@buffer_size)
|
|
88
|
+
block.call part
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def stream_size id
|
|
94
|
+
id = strip_id(id)
|
|
95
|
+
name = File.join(@path, STREAMS, "#{id.to_s}.dat")
|
|
96
|
+
raise RuntimeError, "The Stream with id '#{id}' has been deleted!", caller unless File.exist? name
|
|
97
|
+
File.size(name)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def size
|
|
101
|
+
Dir.glob(File.join(@path, STREAMS, "*.dat")).size
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def delete id
|
|
105
|
+
id = strip_id(id)
|
|
106
|
+
name = File.join(@path, STREAMS, "#{id.to_s}.dat")
|
|
107
|
+
File.delete name if File.exist? name
|
|
108
|
+
|
|
109
|
+
name = File.join(@path, STREAMS, "#{id.to_s}.met")
|
|
110
|
+
File.delete name if File.exist? name
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def list_of_ids
|
|
114
|
+
Dir.glob(File.join(@path, STREAMS, "*.dat")).collect{|name| File.basename(name, ".dat")}
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def self.delete name, basedir
|
|
118
|
+
path = File.join(basedir, name.to_s)
|
|
119
|
+
FileUtils.rm_rf path if File.exist? path
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
class SystemListener
|
|
2
|
+
def initialize transaction
|
|
3
|
+
@transaction = transaction
|
|
4
|
+
@deleted_parents = {}
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def before_attribute_update entity, name, new, old
|
|
8
|
+
name.should! :be_a, Symbol
|
|
9
|
+
AnEntity::EntityType.validate_attribute entity, name, new, old
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def before_name_update entity, new, old
|
|
13
|
+
return if new == old
|
|
14
|
+
raise_without_self "name '#{new}' should be a String!", ObjectModel unless new.is_a? String
|
|
15
|
+
raise_without_self "name '#{new}' shouldn't be Emtpy!", ObjectModel if new.empty?
|
|
16
|
+
raise_without_self "name '#{new}' should not include '/' Symbol!", ObjectModel if new.include? '/'
|
|
17
|
+
|
|
18
|
+
check_name_uniquity entity, new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def after_new_parent entity, old_parent
|
|
22
|
+
check_name_uniquity entity, entity.name
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def after_delete_parent entity, old_parent
|
|
26
|
+
check_name_uniquity entity, entity.name
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def before_commit entities
|
|
30
|
+
entities.should! :be_a, Array
|
|
31
|
+
entities.each do |e|
|
|
32
|
+
AnEntity::EntityType.validate_entity e
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def after_new entity
|
|
37
|
+
AnEntity::EntityType.custom_initialization entity
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def before_new_child entity, name, child
|
|
41
|
+
raise_without_self "Child should be Entity or Nil (#{child})!", ObjectModel unless child.is_a?(Entity) or child == nil
|
|
42
|
+
raise_without_self "Forbiden to add self as Child!", ObjectModel if child == entity
|
|
43
|
+
raise_without_self "Forbiden to add the same Child twice!", ObjectModel if child.parent == entity
|
|
44
|
+
|
|
45
|
+
name.should! :be_a, Symbol
|
|
46
|
+
|
|
47
|
+
old_parent = child.parent
|
|
48
|
+
if old_parent != nil # :move
|
|
49
|
+
AnEntity::EntityType.delete_from_parent child, old_parent
|
|
50
|
+
@transaction.event_processor.fire_before child, :move, entity, old_parent
|
|
51
|
+
@transaction.copies[entity.entity_id].moved!
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
@transaction.event_processor.fire_before child, :new_parent, entity
|
|
55
|
+
|
|
56
|
+
child._parent = entity
|
|
57
|
+
|
|
58
|
+
@transaction.event_processor.fire_after child, :new_parent, old_parent
|
|
59
|
+
|
|
60
|
+
if old_parent != nil # :move
|
|
61
|
+
@transaction.event_processor.fire_after child, :move, entity, old_parent
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def before_delete_child entity, name, child
|
|
66
|
+
child.should! :be_a, Entity
|
|
67
|
+
entity.should! :be_a, Entity
|
|
68
|
+
name.should! :be_a, Symbol
|
|
69
|
+
|
|
70
|
+
@transaction.event_processor.fire_before child, :delete_parent, entity
|
|
71
|
+
child._parent = nil
|
|
72
|
+
@transaction.event_processor.fire_after child, :delete_parent, entity
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def before_delete entity
|
|
76
|
+
if entity.name_get == "child2"
|
|
77
|
+
copy = @transaction.copies[entity.entity_id]
|
|
78
|
+
|
|
79
|
+
parent = entity.parent
|
|
80
|
+
parent.should! :be_a, [Entity, NilClass]
|
|
81
|
+
|
|
82
|
+
@transaction.deleted_entities[entity.entity_id] = entity
|
|
83
|
+
|
|
84
|
+
AnEntity::EntityType.delete_all_references_to @transaction, entity
|
|
85
|
+
AnEntity::EntityType.delete_from_parent entity, parent if parent
|
|
86
|
+
AnEntity::EntityType.delete_all_children entity
|
|
87
|
+
return
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
copy = @transaction.copies[entity.entity_id]
|
|
91
|
+
copy.should_not! :deleted?
|
|
92
|
+
|
|
93
|
+
parent = entity.parent
|
|
94
|
+
parent.should! :be_a, [Entity, NilClass]
|
|
95
|
+
|
|
96
|
+
@transaction.deleted_entities[entity.entity_id] = entity
|
|
97
|
+
|
|
98
|
+
AnEntity::EntityType.delete_all_references_to @transaction, entity
|
|
99
|
+
AnEntity::EntityType.delete_from_parent entity, parent if parent
|
|
100
|
+
AnEntity::EntityType.delete_all_children entity
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def before_delete_reference entity, name, reference
|
|
104
|
+
entity.should! :be_a, Entity
|
|
105
|
+
reference.should! :be_a, Entity
|
|
106
|
+
name.should! :be_a, Symbol
|
|
107
|
+
|
|
108
|
+
@transaction.event_processor.fire_before reference, :delete_referrer, entity
|
|
109
|
+
|
|
110
|
+
AnEntity::EntityType.delete_backreference @transaction, entity, reference
|
|
111
|
+
|
|
112
|
+
@transaction.event_processor.fire_after reference, :delete_referrer, entity
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def before_new_reference entity, name, reference
|
|
116
|
+
entity.should! :be_a, Entity
|
|
117
|
+
reference.should! :be_a, Entity
|
|
118
|
+
name.should! :be_a, Symbol
|
|
119
|
+
|
|
120
|
+
@transaction.event_processor.fire_before reference, :new_referrer, entity
|
|
121
|
+
|
|
122
|
+
AnEntity::EntityType.new_backreference @transaction, entity, reference
|
|
123
|
+
|
|
124
|
+
@transaction.event_processor.fire_after reference, :new_referrer, entity
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
protected
|
|
128
|
+
def check_name_uniquity entity, name
|
|
129
|
+
# Uniquity In Transaction Scope
|
|
130
|
+
the_same = @transaction.new_entities.values.any? do |e|
|
|
131
|
+
next if e == entity
|
|
132
|
+
e.name == name and e.parent == entity.parent
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Uniquitey In Database
|
|
136
|
+
parent = entity.parent
|
|
137
|
+
parent_path = parent != nil ? parent.path + "/" : ""
|
|
138
|
+
absolute_path = "#{parent_path}#{name}"
|
|
139
|
+
the_same ||= @transaction.repository.include? absolute_path
|
|
140
|
+
|
|
141
|
+
raise_without_self "Not unique name '#{name}' (Parent '#{entity.parent}')!", ObjectModel if the_same
|
|
142
|
+
end
|
|
143
|
+
end
|