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,63 @@
1
+ class Transaction
2
+ attr_reader :copies, :name, :new_entities, :event_processor, :repository, :system_listener, :deleted_entities
3
+ attr_writer :repository, :name
4
+ attr_accessor :managed
5
+
6
+ def initialize
7
+ @name = "default"
8
+ @copies = Hash.new{|hash, key| raise "Can't find Copy for '#{key}'entity_id!"}
9
+ @new_entities = Hash.new{|hash, key| raise "Can't find New Entity for '#{key}' entity_id!"}
10
+ @deleted_entities = Hash.new{|hash, key| raise "Can't find Deleted Entity for '#{key}' entity_id!"}
11
+ @event_processor = EventProcessor.new(self)
12
+ @system_listener = SystemListener.new(self)
13
+ @commited = false
14
+ @managed = false
15
+ end
16
+
17
+ def copy_get! entity
18
+ unless @copies.include? entity.entity_id
19
+ copy = AnEntity::EntityType.create_copy entity
20
+ @copies[entity.entity_id] = copy
21
+ end
22
+ @copies[entity.entity_id]
23
+ end
24
+
25
+ def resolve entity_id
26
+ if @new_entities.include? entity_id
27
+ @new_entities[entity_id]
28
+ elsif @deleted_entities.include? entity_id
29
+ @deleted_entities[entity_id]
30
+ else
31
+ @repository.by_id(entity_id)
32
+ end
33
+ end
34
+
35
+ def commited!
36
+ @commited = true
37
+ end
38
+
39
+ def commited?
40
+ @commited
41
+ end
42
+
43
+ def commit
44
+ @repository.commit self
45
+ end
46
+
47
+ def changed? entity_id
48
+ entity_id.should! :be_a, String
49
+ @copies.include?(entity_id) || @new_entities.include?(entity_id)
50
+ end
51
+
52
+ def to_s
53
+ types = {:new => 0, :deleted => 0, :updated => 0, :moved => 0}
54
+ methods = types.keys
55
+ @copies.values.each do |c|
56
+ methods.each do |m|
57
+ types[m] += 1 if c.send :"#{m}?"
58
+ end
59
+ end
60
+ return "#<Transaction: #{@name}#{commited? ? ", commited" : ""}, #{types.inspect}>"
61
+ end
62
+ alias_method :inspect, :to_s
63
+ end
@@ -0,0 +1,36 @@
1
+ class TransactionProcessor
2
+ inherit Log
3
+
4
+ def initialize repository, transaction
5
+ @repository, @transaction = repository, transaction
6
+ end
7
+
8
+ def check_outdated
9
+ outdated = []
10
+ @transaction.copies.each do |entity_id, c|
11
+ next if c.new?
12
+ e = @repository.by_id(entity_id)
13
+ outdated << entity_id if c.om_version != e.om_version
14
+ end
15
+ raise_without_self OutdatedError.new(outdated), "Outdated Entities: ['#{outdated.join('\', \'')}']", ObjectModel unless outdated.empty?
16
+ end
17
+
18
+ def write_back
19
+ @transaction.copies.each do |entity_id, copy|
20
+ next if copy.deleted?
21
+ entity = @transaction.resolve entity_id
22
+ AnEntity::EntityType.write_back copy, entity
23
+ end
24
+ end
25
+
26
+ def persist
27
+ @transaction.copies.each do |entity_id, copy|
28
+ entity = @transaction.resolve entity_id
29
+ if copy.deleted?
30
+ AnEntity::EntityType.delete entity, @repository.storage
31
+ else
32
+ AnEntity::EntityType.persist copy, entity, @repository.storage
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,9 @@
1
+ class DefaultTransactionStrategy
2
+ def initialize repository; end
3
+
4
+ def create_new
5
+ Repository::Transaction.new
6
+ end
7
+
8
+ def after_commit transaction; end
9
+ end
@@ -0,0 +1,9 @@
1
+ class InMemoryCache < Hash
2
+ def initialize repository, *parameters
3
+ super()
4
+ end
5
+
6
+ def update transaction
7
+ transaction.copies.each{|entity_id, c| delete entity_id if c.deleted?}
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ class NoCache
2
+ def initialize repository, *parameters
3
+ end
4
+
5
+ def [] key
6
+ nil
7
+ end
8
+
9
+ def []= key, item
10
+ end
11
+
12
+ def update transaction
13
+ end
14
+
15
+ def delete key
16
+
17
+ end
18
+ end
@@ -0,0 +1,37 @@
1
+ # It should have max_items at least equal to 1!
2
+ class OGLRUCache < LRUCache
3
+ class EntityContainer
4
+ include LRUCache::Item
5
+
6
+ attr_reader :entity
7
+ def initialize entity
8
+ @entity = entity
9
+ end
10
+ end
11
+
12
+ def initialize repository, percentage
13
+ @repository, @percentage = repository, percentage
14
+ super(1)
15
+ update_size
16
+ end
17
+
18
+ def [](key)
19
+ container = super(key)
20
+ nil == container ? nil : container.entity
21
+ end
22
+
23
+ def []=(key, item)
24
+ container = EntityContainer.new item
25
+ super(key, container)
26
+ end
27
+
28
+ def update transaction
29
+ transaction.copies.each{|entity_id, c| delete entity_id if c.deleted?}
30
+ update_size
31
+ end
32
+
33
+ protected
34
+ def update_size
35
+ self.max_items = (@repository.size * @percentage).floor + 1
36
+ end
37
+ end
@@ -0,0 +1,94 @@
1
+ class BagType
2
+ class << self
3
+ def initial_value m, e
4
+ calculate_class(m).new e, m.name, e.om_repository
5
+ # e.instance_variable_set m.ivname, bag
6
+ end
7
+
8
+ def initialize_copy m, e, c
9
+ bag = e.instance_variable_get m.ivname
10
+ bag_copy = AnEntity::BagCopy.new bag._array
11
+ c[m.ivname] = bag_copy
12
+ end
13
+
14
+ def initialize_storage db
15
+ db.create_table :bags do
16
+ column :entity_id, :text
17
+ column :name, :text
18
+ column :reference_id, :text
19
+ # index :entity_id
20
+ end
21
+ end
22
+
23
+ def print_storage db, name
24
+ return unless name == nil or name == :bags
25
+ puts "\nBags:"
26
+ db[:bags].print
27
+ end
28
+
29
+ def load m, e, storage
30
+ rows = storage[:bags].filter :entity_id => e.entity_id, :name => m.name.to_s
31
+ bag = calculate_class(m).new e, m.name, e.om_repository
32
+ rows.each do |row|
33
+ value = AnEntity::EntityType.load_id row[:reference_id]
34
+ bag._array << value
35
+ end
36
+ e.instance_variable_set m.ivname, bag
37
+ end
38
+
39
+ def write_back c, e, m
40
+ bag_copy = c[m.ivname]
41
+ bag = e.instance_variable_get m.ivname
42
+ bag._array.replace bag_copy._array # TODO reimplement more efficiently
43
+ end
44
+
45
+ def persist c, entity_id, m, storage
46
+ # TODO reimplement more efficiently
47
+ sname = m.name.to_s
48
+ storage[:bags].filter(:entity_id => entity_id, :name => sname).delete
49
+ c[m.ivname]._array.each do |ref_id|
50
+ ref_id.should_not! :be_nil
51
+ storage[:bags].insert(
52
+ :entity_id => entity_id,
53
+ :name => sname,
54
+ :reference_id => AnEntity::EntityType.dump_id(ref_id)
55
+ )
56
+ end
57
+ end
58
+
59
+ def delete e, m, storage
60
+ storage[:bags].filter(:entity_id => e.entity_id).delete
61
+ end
62
+
63
+ def delete_all_children e, m
64
+ bag = e.send m.name
65
+ bag.every.delete
66
+ end
67
+
68
+ def delete_all_references_to referrer, e, m
69
+ bag = referrer.send m.name
70
+ bag.delete e
71
+ end
72
+
73
+ def delete_from_parent e, parent, m
74
+ bag = parent.send m.name
75
+ bag.delete e
76
+ end
77
+
78
+ def each e, m, &b
79
+ bag = e.send m.name
80
+ bag.each &b
81
+ end
82
+
83
+ protected
84
+ def calculate_class m
85
+ if m.is_a? Metadata::Child
86
+ AnEntity::ChildrenBag
87
+ elsif m.is_a? Metadata::Reference
88
+ AnEntity::ReferencesBag
89
+ else
90
+ should! :be_never_called
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,42 @@
1
+ class BooleanType
2
+ class << self
3
+ inherit Log
4
+
5
+ def initial_value m, e
6
+ false
7
+ # e.instance_variable_set m.ivname, false
8
+ end
9
+
10
+ def initialize_copy m, e, c
11
+ value_copy = e.instance_variable_get(m.ivname).copy
12
+ c[m.ivname] = value_copy
13
+ end
14
+
15
+ def load m, e, storage
16
+ row = storage[:entities_content][:entity_id => e.entity_id, :name => m.name.to_s]
17
+ raise LoadError unless row and row[:class] == "BOOLEAN"
18
+
19
+ e.instance_variable_set m.ivname, (row[:value] == "false" ? false : true)
20
+ end
21
+
22
+ def persist c, entity_id, m, storage
23
+ value = c[m.ivname] ? "true" : "false"
24
+ storage[:entities_content].insert(
25
+ :entity_id => entity_id,
26
+ :name => m.name.to_s,
27
+ :value => value,
28
+ :class => "BOOLEAN"
29
+ )
30
+ end
31
+
32
+ def write_back c, e, m
33
+ value = c[m.ivname]
34
+ value.should! :be_a, [TrueClass, FalseClass]
35
+ e.instance_variable_set m.ivname, value
36
+ end
37
+
38
+ def validate_type value
39
+ value == true or value == false
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,43 @@
1
+ class ClassType
2
+ class << self
3
+ def initial_value m, e
4
+ nil
5
+ # e.instance_variable_set m.ivname, nil
6
+ end
7
+
8
+ def initialize_copy m, e, c
9
+ value_copy = e.instance_variable_get(m.ivname)
10
+ c[m.ivname] = value_copy
11
+ end
12
+
13
+ def write_back c, e, m
14
+ value = c[m.ivname]
15
+ value.should! :be_a, [NilClass, Module, Class]
16
+ e.instance_variable_set m.ivname, value
17
+ end
18
+
19
+ def load m, e, storage
20
+ row = storage[:entities_content][:entity_id => e.entity_id, :name => m.name.to_s]
21
+
22
+ raise LoadError unless row and row[:class] == "CLASS"
23
+ value = row[:value]
24
+ value = eval(value, TOPLEVEL_BINDING, __FILE__, __LINE__) if value
25
+ e.instance_variable_set m.ivname, value
26
+ end
27
+
28
+ def persist c, entity_id, m, storage
29
+ value = c[m.ivname]
30
+ value = value.name if value
31
+ storage[:entities_content].insert(
32
+ :entity_id => entity_id,
33
+ :name => m.name.to_s,
34
+ :value => value,
35
+ :class => "CLASS"
36
+ )
37
+ end
38
+
39
+ def validate_type value
40
+ value == nil or value.is_a?(Module) or value.is_a?(Class)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,44 @@
1
+ class DataType
2
+ class << self
3
+ def initial_value m, e
4
+ nil
5
+ # e.instance_variable_set m.ivname, nil
6
+ end
7
+
8
+ def initialize_copy m, e, c
9
+ value = e.instance_variable_get(m.ivname)
10
+ value_copy = value != nil ? Repository::StreamID.new(value.sid) : nil
11
+ c[m.ivname] = value_copy
12
+ end
13
+
14
+ def write_back c, e, m
15
+ value = c[m.ivname]
16
+ value.should! :be_a, [NilClass, Repository::StreamID]
17
+ e.instance_variable_set m.ivname, value
18
+ end
19
+
20
+ def load m, e, storage
21
+ row = storage[:entities_content][:entity_id => e.entity_id, :name => m.name.to_s]
22
+ raise LoadError unless row and row[:class] == "STREAM_ID"
23
+
24
+ stream_id = row[:value]
25
+ value = stream_id == "nil" ? nil : Repository::StreamID.new(stream_id)
26
+ e.instance_variable_set m.ivname, value
27
+ end
28
+
29
+ def persist c, entity_id, m, storage
30
+ value = c[m.ivname]
31
+ stream_id = value == nil ? "nil" : value.sid
32
+ storage[:entities_content].insert(
33
+ :entity_id => entity_id,
34
+ :name => m.name.to_s,
35
+ :value => stream_id,
36
+ :class => "STREAM_ID"
37
+ )
38
+ end
39
+
40
+ def validate_type value
41
+ value == nil or value.is_a? StreamID
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,43 @@
1
+ class DateType
2
+ class << self
3
+ def initial_value m, e
4
+ nil
5
+ # e.instance_variable_set m.ivname, nil
6
+ end
7
+
8
+ def initialize_copy m, e, c
9
+ value = e.instance_variable_get(m.ivname)
10
+ value_copy = value != nil ? value.clone : nil
11
+ c[m.ivname] = value_copy
12
+ end
13
+
14
+ def write_back c, e, m
15
+ value = c[m.ivname]
16
+ value.should! :be_a, [NilClass, DateTime]
17
+ e.instance_variable_set m.ivname, value
18
+ end
19
+
20
+ def persist c, entity_id, m, storage
21
+ value = c[m.ivname]
22
+ str_value = value == nil ? "nil" : value.to_s
23
+ storage[:entities_content].insert(
24
+ :entity_id => entity_id,
25
+ :name => m.name.to_s,
26
+ :value => str_value,
27
+ :class => "DATE"
28
+ )
29
+ end
30
+
31
+ def load m, e, storage
32
+ row = storage[:entities_content][:entity_id => e.entity_id, :name => m.name.to_s]
33
+ raise LoadError unless row and row[:class] == "DATE"
34
+
35
+ value = row[:value]
36
+ e.instance_variable_set m.ivname, (value == "nil" ? nil : DateTime.parse(value))
37
+ end
38
+
39
+ def validate_type value
40
+ value == nil or value.is_a? DateTime
41
+ end
42
+ end
43
+ end